diff --git a/.eslintrc.js b/.eslintrc.js index 9c3b37adfb8..1fc51bfcf4b 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -31,6 +31,7 @@ module.exports = { curly: ['error', 'all'], eqeqeq: ['error', 'smart'], 'func-names': ['warn', 'as-needed'], + 'guard-for-in': 'warn', indent: ['error', 4, { VariableDeclarator: 'first', SwitchCase: 1 @@ -39,15 +40,20 @@ module.exports = { code: 140, ignoreComments: true }], + 'new-cap': 'warn', 'no-continue': 'warn', + 'no-global-assign': 'warn', 'no-new': 'warn', 'no-param-reassign': 'warn', - 'no-plusplus': ['error', { + 'no-plusplus': ['warn', { allowForLoopAfterthoughts: true }], + 'no-restricted-syntax': 'warn', 'no-underscore-dangle': 'warn', 'no-unused-vars': ['error', { args: 'none' }], 'no-use-before-define': ['error', 'nofunc'], + 'no-useless-escape': 'warn', + 'no-shadow': ['warn', { allow: ['response'] }], 'object-shorthand': ['error', 'consistent'], 'one-var': ['error', 'consecutive'], 'prefer-arrow-callback': 'warn', diff --git a/_build/templates/default/sass/_forms.scss b/_build/templates/default/sass/_forms.scss index 1a0a0dbce53..bd405b32353 100644 --- a/_build/templates/default/sass/_forms.scss +++ b/_build/templates/default/sass/_forms.scss @@ -76,7 +76,7 @@ textarea.x-form-field, border-radius: $borderRadius; border: 1px solid $borderColor; position: relative; - transition: border-color .25s; + transition: border-color 0.25s; } .x-viewport .x-trigger-wrap-focus, @@ -143,7 +143,7 @@ input::-moz-focus-inner { padding: 0 0 0 3px; top: 0; right: 0; - transition: all .25s; + transition: all 0.25s; width: 16px; height: 16px; @@ -289,7 +289,7 @@ input::-moz-focus-inner { border: 1px solid $borderColor; border-radius: $borderRadius; padding: 5px; - transition: all .25s; + transition: all 0.25s; &:focus { border: 1px solid $borderColorFocus; @@ -410,7 +410,7 @@ input::-moz-focus-inner { } &.toggle-slider-above { - margin: .3em 0; + margin: 0.3em 0; padding-left: 3.9em; } @@ -422,15 +422,15 @@ input::-moz-focus-inner { .example-list { ul { - margin: .4em 0; + margin: 0.4em 0; li { position: relative; - margin-bottom: .25em; + margin-bottom: 0.25em; padding-left: 1.25em; &::before { @extend %pseudo-font; position: absolute; - left: .2em; + left: 0.2em; top: 0; content: fa-content($fa-var-angle-double-right); color: scale-color($mediumGray, $lightness: 20%); @@ -440,7 +440,7 @@ input::-moz-focus-inner { } .example-input, .copy-this { - padding: 0 .3em; + padding: 0 0.3em; border-radius: 2px; transition: width 1s; } @@ -478,7 +478,14 @@ input::-moz-focus-inner { } } } - } + &:active { + color: $darkGray; + &::after { + color: $darkGray; + } + } + } + .feedback { margin-left: 1.4rem; color: scale-color($blue, $lightness: -35%); @@ -507,7 +514,7 @@ input::-moz-focus-inner { .fs-toggle { padding-top: 1em; margin-top: 2em; - margin-bottom: .5em; + margin-bottom: 0.5em; border-top: 1px dashed $borderColor; } @@ -636,7 +643,7 @@ input::-moz-focus-inner { transform: translate(-50%, -50%); text-align: center; width: 30px; - transition: opacity .25s; + transition: opacity 0.25s; } &.x-form-trigger-over, @@ -932,11 +939,11 @@ input::-moz-focus-inner { left: unset; } - &+.x-form-cb-label, - &+.x-fieldset-header-text { + & + .x-form-cb-label, + & + .x-fieldset-header-text { position: relative; padding-left: 3.6em; - padding-top: .2em; + padding-top: 0.2em; margin-left: 0; cursor: pointer; box-sizing: border-box; @@ -946,7 +953,7 @@ input::-moz-focus-inner { &:after { content: ''; position: absolute; - transition: all .2s ease; + transition: all 0.2s ease; font-size: inherit; } @@ -963,7 +970,7 @@ input::-moz-focus-inner { &:after { left: 0.1em; top: 0.8em; - margin-top: -.65em; + margin-top: -0.65em; height: 1.3em; width: 1.3em; border-radius: 50%; @@ -973,9 +980,8 @@ input::-moz-focus-inner { } &:checked { - - &+.x-form-cb-label, - &+.x-fieldset-header-text { + & + .x-form-cb-label, + & + .x-fieldset-header-text { &:after { left: 1.6em; top: 0.8em; @@ -989,9 +995,8 @@ input::-moz-focus-inner { } &.danger:checked { - - &+.x-form-cb-label, - &+.x-fieldset-header-text { + & + .x-form-cb-label, + & + .x-fieldset-header-text { &:before { background-color: $red; border-color: $red; @@ -1000,9 +1005,8 @@ input::-moz-focus-inner { } &.warning:checked { - - &+.x-form-cb-label, - &+.x-fieldset-header-text { + & + .x-form-cb-label, + & + .x-fieldset-header-text { &:before { background-color: $orange; border-color: $orange; @@ -1089,13 +1093,13 @@ input::-moz-focus-inner { cursor: pointer; display: inline-block; /*font-size: 1px;*/ outline: 0; /* fix firefox dotted outlines */ - opacity: .6; + opacity: 0.6; filter: alpha(opacity=60); /* for IE <= 8 */ padding: 0; position: absolute; top: 0; right: 0; - transition: opacity .25s; + transition: opacity 0.25s; width: 16px; height: 100%; @@ -1226,21 +1230,22 @@ input::-moz-focus-inner { } .x-editor .x-form-check-wrap { - background-color: $white -} - -/* fix combo on grid editor bug */ -.x-grid-editor .x-form-field-wrap { - background: #f6f2f7 url($imgPath + 'modx-theme/form/combo-bck.png') repeat-x scroll 0 100%; + background-color: $white; } -.x-grid-editor .x-form-field-wrap input { +.x-grid-editor { + z-index: 9002 !important; + .x-form-field-wrap { + background: #f6f2f7 url($imgPath + "modx-theme/form/combo-bck.png") repeat-x + scroll 0 100%; + input { background-color: transparent !important; } - -.x-grid-editor .x-form-field-wrap img { + img { background-color: $white; - background-image: url($imgPath + 'modx-theme/form/trigger.png'); + background-image: url($imgPath + "modx-theme/form/trigger.png"); + } + } } .x-form-grow-sizer { @@ -1374,7 +1379,7 @@ input::-moz-focus-inner { .x-btn { padding: 1px; - transition: color .25s; + transition: color 0.25s; &.x-btn-over, &:hover, @@ -1389,7 +1394,7 @@ input::-moz-focus-inner { &.x-item-disabled { color: $buttonColor; - opacity: .4; + opacity: 0.4; } button:before { @@ -1433,7 +1438,11 @@ input::-moz-focus-inner { } /* the second text cell, "of X" */ - .x-toolbar-cell + .x-toolbar-cell + .x-toolbar-cell + .x-toolbar-cell + .x-toolbar-cell { + .x-toolbar-cell + + .x-toolbar-cell + + .x-toolbar-cell + + .x-toolbar-cell + + .x-toolbar-cell { .xtb-text { display: inline-block; position: absolute; @@ -1445,7 +1454,15 @@ input::-moz-focus-inner { } /* the last regular button >>, yes, I know it's ugly but tell that Microsoft and say thanks for IE8 =) */ - .x-toolbar-cell + .x-toolbar-cell + .x-toolbar-cell + .x-toolbar-cell + .x-toolbar-cell + .x-toolbar-cell + .x-toolbar-cell + .x-toolbar-cell + .x-toolbar-cell { + .x-toolbar-cell + + .x-toolbar-cell + + .x-toolbar-cell + + .x-toolbar-cell + + .x-toolbar-cell + + .x-toolbar-cell + + .x-toolbar-cell + + .x-toolbar-cell + + .x-toolbar-cell { .x-btn { margin-right: 0; } @@ -1454,13 +1471,13 @@ input::-moz-focus-inner { /* the refresh button */ .x-toolbar-cell:last-child { opacity: 0; - transition: opacity .25s; + transition: opacity 0.25s; .x-btn { font-size: 12px; line-height: 1; margin: 0; - opacity: .4; + opacity: 0.4; padding: 0; position: absolute; bottom: 2px; @@ -1549,11 +1566,11 @@ input::-moz-focus-inner { .x-date-mp-ybtn a.x-date-mp-prev, .x-date-mp-ybtn a.x-date-mp-next { display: inline-block; - opacity: .6; + opacity: 0.6; filter: alpha(opacity=60); /* for IE <= 8 */ margin: 0 auto; position: relative; - transition: opacity .25s; + transition: opacity 0.25s; &:before { @extend %pseudo-font; @@ -1810,6 +1827,6 @@ td.x-date-mp-sep { bottom: 0; padding: 10px 20px; color: #fff; - background-color: rgba(0, 0, 0, .8); + background-color: rgba(0, 0, 0, 0.8); } } diff --git a/_build/templates/default/sass/_utility.scss b/_build/templates/default/sass/_utility.scss index 27c6b20ed18..b5ff5bc8cd4 100644 --- a/_build/templates/default/sass/_utility.scss +++ b/_build/templates/default/sass/_utility.scss @@ -145,7 +145,6 @@ } } - /* Instead of writing the same code for every nav bar */ @mixin navigation-list { list-style-type: none; @@ -212,3 +211,13 @@ } } } + +@mixin textLink { + color: $colorSplash; + text-decoration-style: dotted; + text-decoration-color: scale-color($colorSplash, $lightness: 50%); + &:hover { + color: $black; + border-bottom-color: scale-color($black, $lightness: 40%); + } +} \ No newline at end of file diff --git a/_build/templates/default/sass/index.scss b/_build/templates/default/sass/index.scss index bd5f5cb2b09..dee3cc75f89 100644 --- a/_build/templates/default/sass/index.scss +++ b/_build/templates/default/sass/index.scss @@ -69,7 +69,7 @@ body { } } -/* TODO: conver font heirarchy into a vertical rhythm formula */ +/* TODO: convert font heirarchy into a vertical rhythm formula */ h2, h3 { color: $treeHeaderText; @@ -542,6 +542,14 @@ textarea.x-form-field { } /* grids */ + +.modx-protected-row { + .x-grid3-cell-inner { + font-style: italic; + color: $colorSplash; + } +} + .x-small-editor .x-form-field { font-size: 12px !important; } @@ -554,14 +562,15 @@ textarea.x-form-field { color: #999 !important; } -a.x-grid-link { - color: $colorSplash; - text-decoration: underline; -} - -a.x-grid-link:hover, -a.x-grid-link:focus { - text-decoration: none; +.x-grid-link { + @include textLink; + &.simulated-link { + cursor: pointer; + } + .grid-row-inactive & { + color: #999 !important; + text-decoration-color: #999 !important; + } } .x-editable-column { @@ -911,6 +920,37 @@ a.x-grid-link:focus { } /* rowactions */ +.x-grid3-row { + &.disable-selection, + &.disable-selection.x-grid3-row-selected { + .x-grid3-row-checker { + position: relative; + &::before, + &::after { + color: $disabledTextColor; + } + &::before { + content: '\f0c8'; + } + &::after { + content: '\f715'; + font-size: 6px; + position: absolute; + left: 50%; + top: 50%; + margin-left: 2px; + margin-top: 1px; + transform: translate(-50%, -50%) rotate(98deg); + font-weight: 600; + font-family: 'Font Awesome 5 Free'; + } + &:hover { + cursor: default; + } + } + } +} + .ux-row-action-cell .x-grid3-cell-inner { padding: 1px 0 0 0; } @@ -1877,6 +1917,12 @@ iframe[classname="x-hidden"] { user-select: text !important; } +.x-selectable { + &.simulated-link * { + @include textLink; + } +} + /* Lightbox */ #ux-lightbox { left: 0; diff --git a/core/lexicon/en/content_type.inc.php b/core/lexicon/en/content_type.inc.php index 62063f93228..a6411fed17a 100644 --- a/core/lexicon/en/content_type.inc.php +++ b/core/lexicon/en/content_type.inc.php @@ -1,4 +1,5 @@ Each setting will be available via the [[++key]] placeholder.'; $_lang['context_with_key_not_found'] = 'Context with key %s not found!'; diff --git a/core/lexicon/en/dashboards.inc.php b/core/lexicon/en/dashboards.inc.php index f6cb29fd2d2..e27f87976e6 100644 --- a/core/lexicon/en/dashboards.inc.php +++ b/core/lexicon/en/dashboards.inc.php @@ -7,16 +7,19 @@ * @language en */ $_lang['dashboard'] = 'Dashboard'; -$_lang['dashboard_desc_name'] = 'The name of the Dashboard.'; -$_lang['dashboard_desc_description'] = 'A short description of the Dashboard.'; -$_lang['dashboard_desc_hide_trees'] = 'Checking this will hide the left-hand trees when this Dashboard is rendered on the welcome page.'; -$_lang['dashboard_hide_trees'] = 'Hide Left-Hand Trees'; -$_lang['dashboard_desc_customizable'] = 'Allow users to customize this dashboard for their accounts: create, delete and change position or size of widgets.'; $_lang['dashboard_customizable'] = 'Customizable'; +$_lang['dashboard_customizable_desc'] = 'Allow users to customize this dashboard for their accounts: create, delete and change position or size of widgets.'; +$_lang['dashboard_description_desc'] = 'A short description of the Dashboard.'; +$_lang['dashboard_edit'] = 'Edit the settings and Widget placements for this Dashboard'; +$_lang['dashboard_hide_trees'] = 'Hide Left-Hand Trees'; +$_lang['dashboard_hide_trees_desc'] = 'Checking this will hide the left-hand trees when this Dashboard is rendered on the welcome page.'; +$_lang['dashboard_name_desc'] = 'The name of the Dashboard.'; $_lang['dashboard_remove_confirm'] = 'Are you sure you want to delete this Dashboard?'; $_lang['dashboard_remove_multiple_confirm'] = 'Are you sure you want to delete the selected Dashboards?'; +$_lang['dashboard_reserved_general_desc'] = 'Note that this is a protected, built-in Dashboard. Its general values are locked, but other specifications (such as assigned Widgets) are editable by users with the appropriate permissions.'; $_lang['dashboard_err_ae_name'] = 'A dashboard with the name "[[+name]]" already exists! Please try another name.'; $_lang['dashboard_err_duplicate'] = 'An error occurred while trying to duplicate the dashboard.'; +$_lang['dashboard_err_name_reserved'] = 'The dashboard name “[[+reservedName]]” is reserved. Please choose another name.'; $_lang['dashboard_err_nf'] = 'Dashboard not found.'; $_lang['dashboard_err_ns'] = 'Dashboard not specified.'; $_lang['dashboard_err_ns_name'] = 'Please specify a name for the widget.'; @@ -27,8 +30,9 @@ $_lang['dashboard_usergroup_remove'] = 'Delete Dashboard from User Group'; $_lang['dashboard_usergroup_remove_confirm'] = 'Are you sure you want to revert this User Group to using the default Dashboard?'; $_lang['dashboard_usergroups.intro_msg'] = 'Here is a list of all the User Groups using this Dashboard.'; +$_lang['dashboard_widget_edit'] = 'Edit this Widget’s specifications and properties'; $_lang['dashboard_widget_err_placed'] = 'This widget is already placed in this Dashboard!'; -$_lang['dashboard_widgets.intro_msg'] = 'Manage widgets in this dashboard. You can also drag and drop rows in the grid to rearrange them.

Please note: if a dashboard is "customizable", this settings will be applied only for the first load for every user. From here they will be able to create, delete and change the position or size of their widgets. User access to widgets can be limited by applying permissions.'; +$_lang['dashboard_widgets.intro_msg'] = 'Manage the widgets to be showin in this dashboard. Widgets may be re-ordered by changing their Rank or by dragging and dropping their grid rows into the desired position.

Note that if a dashboard is “Customizable,” its initial settings will only apply until a user adds, removes, or makes other changes to the dashboard’s widgets. User access to widgets can be limited by applying permissions.'; $_lang['dashboards'] = 'Dashboards'; $_lang['dashboards.intro_msg'] = 'Here you can manage all the available Dashboards for this MODX manager.'; $_lang['rank'] = 'Rank'; @@ -100,3 +104,9 @@ $_lang['w_whosonline_desc'] = 'Shows a list of online users.'; $_lang['w_view_all'] = 'View all'; $_lang['w_no_data'] = 'No data to display'; + +// Temporarily match old keys to new ones to ensure compatibility +$_lang['dashboard_desc_customizable'] = $_lang['dashboard_customizable_desc']; +$_lang['dashboard_desc_description'] = $_lang['dashboard_description_desc']; +$_lang['dashboard_desc_hide_trees'] = $_lang['dashboard_hide_trees_desc']; +$_lang['dashboard_desc_name'] = $_lang['dashboard_name_desc']; diff --git a/core/lexicon/en/default.inc.php b/core/lexicon/en/default.inc.php index 702944098f2..deab08bc1af 100644 --- a/core/lexicon/en/default.inc.php +++ b/core/lexicon/en/default.inc.php @@ -75,6 +75,7 @@ $_lang['confirm_delete_message'] = 'Are you sure you want to delete this message?'; $_lang['confirm_remove'] = 'Are you sure you want to delete this item?'; $_lang['confirm_remove_locks'] = 'Users sometimes close their browser while editing documents, templates, snippets or parsers, possibly leaving the item they were editing in locked state. By pressing OK you can delete ALL locks currently in place.

Proceed?'; +$_lang['confirm_remove_multiple'] = 'Are you sure you want to delete the selected items?'; $_lang['confirm_undelete'] = 'Any children documents deleted at the same time as this document will also be undeleted, but children documents deleted at an earlier time will still be deleted.'; $_lang['confirm_unpublish'] = 'Un-publishing this document now will delete any (un)publishing dates that may have been set. If you wish to set or keep publish or unpublish dates, please choose to edit the document instead.\n\nProceed?'; $_lang['console'] = 'Console'; @@ -92,6 +93,7 @@ $_lang['create_user_group'] = 'Create User Group'; $_lang['created'] = 'Created'; $_lang['createdon'] = 'Creation date'; +$_lang['creator'] = 'Creator'; $_lang['current'] = 'Current'; $_lang['dashboard'] = 'Dashboard'; $_lang['data_err_load'] = 'Error loading data.'; @@ -217,6 +219,8 @@ $_lang['general_information'] = 'General Information'; $_lang['general_settings'] = 'General Settings'; $_lang['go'] = 'Go'; +$_lang['grid_column_creator_header'] = $_lang['creator']; +$_lang['grid_column_creator_description'] = 'Indicates the entity that created the row’s data/setting (read-only)'; $_lang['group'] = 'Group'; $_lang['guid'] = 'GUID'; $_lang['handler'] = 'Handler'; @@ -317,6 +321,9 @@ $_lang['orm_container_rename'] = 'Rename Container'; $_lang['orm_container_remove'] = 'Delete Container'; $_lang['orm_container_remove_confirm'] = 'Are you sure you want to delete this container and all attributes below it? This is irreversible.'; +// "Extra(s)" below refers to a third-party software package. Translate to shortest length term possible. +$_lang['package_extra'] = 'Extra'; +$_lang['package_extras'] = 'Extras'; $_lang['pagetitle'] = 'Resource\'s Title'; $_lang['page_title'] = 'Resource Title'; $_lang['parameter'] = 'Parameter'; @@ -575,6 +582,13 @@ */ // All +// Templates (some entries also used in Form Customization) +$_lang['template_empty'] = '(empty)'; +$_lang['template_empty_desc'] = '(Note: A template has not been assigned to this set)'; +$_lang['template_missing'] = '(missing)'; +$_lang['template_missing_reassign'] = '(missing — please select a template or “empty” from this list)'; +$_lang['template_missing_desc'] = '(Note: The assigned template no longer exists)'; + // TVs $_lang['tv_type'] = 'Input Type'; $_lang['tv_default'] = 'Default Value'; diff --git a/core/lexicon/en/formcustomization.inc.php b/core/lexicon/en/formcustomization.inc.php index d9cc680cfad..56a977b3397 100644 --- a/core/lexicon/en/formcustomization.inc.php +++ b/core/lexicon/en/formcustomization.inc.php @@ -80,6 +80,7 @@ $_lang['set_change_template_confirm'] = 'Are you sure you want to do this? This will change the Template that these Rules apply to. If so, MODX will first save your changes before reloading the page to refresh the new TVs for the new Template.'; $_lang['set_constraint_field_desc'] = 'Setting the Constraint field will prevent the rules in this Set from executing unless the field for this Resource matches the "constraint" value.'; $_lang['set_constraint_desc'] = 'Set the value of the field (specified above) to restrict the rules in this Set from being executed unless the Resource has this value on the specified constraint field.'; +$_lang['set_edit'] = 'Edit this set’s rules'; $_lang['set_err_nfs'] = 'No Set found with ID [[+id]]'; $_lang['set_err_ns'] = 'No Set specified.'; $_lang['set_fields_msg'] = 'Here you can adjust the fields for this page, including their visibility, labels and default values. Just double-click on a row to edit its value. Leave a field empty to use the default setting.
Please note: when hiding an element inside this profile, it will be hidden in overlapping profiles too (even if Visible is checked).'; diff --git a/core/lexicon/en/namespace.inc.php b/core/lexicon/en/namespace.inc.php index e569bf8120a..ec549d219d6 100644 --- a/core/lexicon/en/namespace.inc.php +++ b/core/lexicon/en/namespace.inc.php @@ -18,7 +18,7 @@ $_lang['namespace_name_desc'] = 'Specify a name for the Namespace here.'; $_lang['namespace_path'] = 'Core Path'; $_lang['namespace_path_desc'] = 'Specify an absolute path to the core for this Namespace here. You may use placeholders like {core_path}. Example: {core_path}components/democomponent/'; -$_lang['namespace_remove_confirm'] = 'Are you sure you want to delete "[[+name]]" namespace and all related content?'; +$_lang['namespace_remove_confirm'] = 'Are you sure you want to delete the "[[+name]]" namespace and all related content?'; $_lang['namespace_remove_multiple_confirm'] = 'Are you sure you want to delete these namespaces and all their related content?'; $_lang['namespaces'] = 'Namespaces'; $_lang['namespaces_desc'] = 'Namespaces are global identifiers for packages and components, registering their vehicles, lexicon entries and resources all together.'; diff --git a/core/lexicon/en/policy.inc.php b/core/lexicon/en/policy.inc.php index 6d35864b353..3df209dbfe1 100644 --- a/core/lexicon/en/policy.inc.php +++ b/core/lexicon/en/policy.inc.php @@ -28,6 +28,7 @@ $_lang['policy_desc_template'] = 'The Policy Template used for this Policy. Policies get their Permission lists from their Template.'; $_lang['policy_desc_lexicon'] = 'Optional. The Lexicon Topic that this Policy uses to translate the Permissions it owns.'; $_lang['policy_duplicate_confirm'] = 'Are you sure you want to duplicate this policy and all of its data?'; +$_lang['policy_edit'] = 'Edit the permissions assigned to this Policy'; $_lang['policy_err_ae'] = 'A Policy already exists with the name `[[+name]]`. Please select another name.'; $_lang['policy_err_nf'] = 'Policy not found.'; $_lang['policy_err_ns'] = 'Policy not specified.'; @@ -47,6 +48,7 @@ $_lang['policy_template_desc'] = 'A Policy Template defines which Permissions will show up in the Permissions grid when editing a specific Policy. You can add or remove specific Permissions from this template below. Note that removing a Permission from a Template will remove it from any Policies that use this Template.'; $_lang['policy_template_desc_name'] = 'The name of the Access Policy Template'; $_lang['policy_template_desc_description'] = 'Optional. A short description of the Access Policy Template. Also you might use lexicon keys here.'; +$_lang['policy_template_edit'] = 'Edit the permissions assigned to this Policy Template'; $_lang['policy_template_lexicon'] = 'Lexicon Topic'; $_lang['policy_template_desc_lexicon'] = 'Optional. The Lexicon Topic that this Policy Template uses to translate the Permissions it owns.'; $_lang['policy_template_desc_template_group'] = 'The Policy Template Group to use. This is used when selecting Policies from a dropdown menu; usually they are filtered by template group. Select an appropriate group for your Policy Template.'; @@ -61,6 +63,10 @@ $_lang['policy_template_remove_confirm_in_use'] = 'Are you sure you want to delete this Policy Template? It will delete all Policies attached to this Template as well - this could break your MODX installation if any active Policies are attached to this Template.

This template is used by existing Policies ([[+count]] in total). Are you sure you want to delete this template and all attached policies?'; $_lang['policy_template_remove_multiple_confirm'] = 'Are you sure you want to delete these Policy Templates? It will delete all Policies attached to these Templates as well - this could break your MODX installation if any active Policies are attached to these Templates.'; $_lang['policy_template_remove_multiple_confirm_in_use'] = 'Are you sure you want to delete these Policy Templates? It will delete all Policies attached to these Templates as well - this could break your MODX installation if any active Policies are attached to these Templates.

Some of selected templates are still used by existing Policies ([[+count]] in total). Are you sure you want to delete these template and all attached policies?'; +$_lang['policy_template_remove_multiple_confirm_in_use_ignoring_protected'] = 'In addition to the [[+count-templates]] Policy Templates you have selected, [[+count-policies]] Access Policies (attached to one or more of these Policy Templates) will be deleted. If any of these Access Policies are currently assigned to a permissions rule, you could break your MODX installation by removing them. (Note that the [[+protected]] protected Templates in your selection will not be removed.) +

+Are you sure you want to continue? +'; $_lang['policy_templates'] = 'Policy Templates'; $_lang['policy_templates.intro_msg'] = 'This is a list of Policy Templates which define lists of Permissions that are checked or unchecked in specific Policies.'; $_lang['policy_template_administrator_desc'] = 'Context administration policy template with all permissions.'; diff --git a/core/lexicon/en/source.inc.php b/core/lexicon/en/source.inc.php index 13a1f4932aa..371c0f54de5 100644 --- a/core/lexicon/en/source.inc.php +++ b/core/lexicon/en/source.inc.php @@ -20,7 +20,9 @@ $_lang['source_access_remove_confirm'] = 'Are you sure you want to delete Access to this Source for this User Group?'; $_lang['source_access_update'] = 'Edit Access'; $_lang['source_description_desc'] = 'A short description of the Media Source.'; +$_lang['source_edit'] = 'Edit the settings and User Group access for this Media Source'; $_lang['source_err_ae_name'] = 'A Media Source with that name already exists! Please specify a new name.'; +$_lang['source_err_name_reserved'] = 'The source name “[[+reservedName]]” is reserved. Please choose another name.'; $_lang['source_err_nf'] = 'Media Source not found!'; $_lang['source_err_init'] = 'Could not initialize "[[+source]]" Media Source!'; $_lang['source_err_nfs'] = 'No Media Source can be found with the id: [[+id]].'; @@ -30,6 +32,7 @@ $_lang['source_properties.intro_msg'] = 'Manage the properties for this Source below.'; $_lang['source_remove_confirm'] = 'Are you sure you want to delete this Media Source? This might break any TVs you have assigned to this source.'; $_lang['source_remove_multiple_confirm'] = 'Are you sure you want to delete these Media Sources? This might break any TVs you have assigned to these sources.'; +$_lang['source_reserved_general_desc'] = 'Note that this is a protected, built-in Media Source. The values shown below are for informational purposes only. Its properties and assigned User Group(s) are, however, editable by users with the appropriate permissions.'; $_lang['source_type'] = 'Source Type'; $_lang['source_type_desc'] = 'The type, or driver, of the Media Source. The Source will use this driver to connect to when gathering its data. For example: File System will grab files from the file system. S3 will get files from an S3 bucket.'; $_lang['source_type.file'] = 'File System'; diff --git a/core/lexicon/en/template.inc.php b/core/lexicon/en/template.inc.php index 738b49ea204..eae311fade3 100644 --- a/core/lexicon/en/template.inc.php +++ b/core/lexicon/en/template.inc.php @@ -18,7 +18,6 @@ $_lang['template_description_desc'] = 'Usage information for this Template shown in search results and as a tooltip in the Elements tree.'; $_lang['template_duplicate_confirm'] = 'Are you sure you want to duplicate this template?'; $_lang['template_edit_tab'] = 'Edit Template'; -$_lang['template_empty'] = '(empty)'; $_lang['template_err_default_template'] = 'This template is set as the default template. Please choose a different default template in the MODX configuration before deleting this template.
'; $_lang['template_err_delete'] = 'An error occurred while trying to delete the template.'; $_lang['template_err_duplicate'] = 'An error occurred while duplicating the template.'; diff --git a/core/lexicon/en/user.inc.php b/core/lexicon/en/user.inc.php index 163d78f4a28..e9c25a9e23c 100644 --- a/core/lexicon/en/user.inc.php +++ b/core/lexicon/en/user.inc.php @@ -1,4 +1,5 @@
Also, should you choose to generate a new password for yourself, it will be sent to you through email.'; $_lang['user_email'] = 'Email address'; $_lang['user_err_access_permissions_save'] = 'An error occurred while saving user access permissions.'; @@ -179,7 +182,7 @@ $_lang['user_remove_confirm'] = 'Are you sure you want to delete this user? This is irreversible!'; $_lang['user_remove_multiple_confirm'] = 'Are you sure you want to delete these users? This is irreversible!'; $_lang['user_remote_data_msg'] = 'Edit remote user data here.'; -$_lang['user_role_update'] = 'Edit User Role'; +$_lang['user_role_update'] = 'Change User’s Role'; $_lang['user_setting_err_remove'] = 'An error occurred while trying to delete user settings.'; $_lang['user_setting_err_save'] = 'An error occurred while saving user settings.'; $_lang['user_settings'] = 'User Settings'; @@ -201,3 +204,6 @@ $_lang['user_createdon_desc'] = 'The date the user was created.'; $_lang['user_password_email_subject'] = 'Set up your password'; $_lang['user_password_email'] = '

Set up your password

We received a request to set up your MODX Revolution password. You can set up your password by clicking the button below and following the instructions on screen.

Set up my password

If you did not send this request, please ignore this email.

'; + +// Aliases +$_lang['user_group_user_create'] = $_lang['user_group_user_add']; diff --git a/core/src/Revolution/Processors/Context/Get.php b/core/src/Revolution/Processors/Context/Get.php index 624c8a77086..cc5626f407f 100644 --- a/core/src/Revolution/Processors/Context/Get.php +++ b/core/src/Revolution/Processors/Context/Get.php @@ -1,4 +1,5 @@ classKey::getCoreContexts(); + $contextKey = $this->object->get('key'); + if (in_array($contextKey, $coreContexts)) { + $contextData = $this->object->toArray(); + $reserved = $contextKey === 'mgr'; + $this->object->set('isProtected', true); + $this->object->set('reserved', $reserved); + } + } } diff --git a/core/src/Revolution/Processors/Context/GetList.php b/core/src/Revolution/Processors/Context/GetList.php index 56aafadbe55..7e6827b3015 100644 --- a/core/src/Revolution/Processors/Context/GetList.php +++ b/core/src/Revolution/Processors/Context/GetList.php @@ -22,8 +22,8 @@ /** * Grabs a list of contexts. * - * @property integer $start (optional) The record to start at. Defaults to 0. - * @property integer $limit (optional) The number of records to limit to. Defaults + * @property int $start (optional) The record to start at. Defaults to 0. + * @property int $limit (optional) The number of records to limit to. Defaults * to 20. * @property string $sort (optional) The column to sort by. Defaults to key. * @property string $dir (optional) The direction of the sort. Defaults to ASC. @@ -36,31 +36,36 @@ class GetList extends GetListProcessor public $permission = 'view_context'; public $languageTopics = ['context']; public $defaultSortField = 'key'; - /** @var boolean $canEdit Determines whether or not the user can edit a Context */ + + /** @var bool $canCreate Determines whether or not the user can create a context (/duplicate one) */ + public $canCreate = false; + /** @var bool $canEdit Determines whether or not the user can edit a Context */ public $canEdit = false; - /** @var boolean $canRemove Determines whether or not the user can remove a Context */ + /** @var bool $canRemove Determines whether or not the user can remove a Context */ public $canRemove = false; - /** @var boolean $canCreate Determines whether or not the user can create a context (/duplicate one) */ - public $canCreate = false; - /** @param boolean $isGridFilter Indicates the target of this list data is a filter field */ + protected $coreContexts; + + /** @var bool $isGridFilter Indicates the target of this list data is a filter field */ protected $isGridFilter = false; /** * {@inheritDoc} - * @return boolean + * @return bool */ public function initialize() { $initialized = parent::initialize(); $this->setDefaultProperties([ 'query' => '', - 'exclude' => '', + 'exclude' => 'creator' ]); $this->canCreate = $this->modx->hasPermission('new_context'); $this->canEdit = $this->modx->hasPermission('edit_context'); $this->canRemove = $this->modx->hasPermission('delete_context'); $this->isGridFilter = $this->getProperty('isGridFilter', false); + $this->coreContexts = $this->classKey::getCoreContexts(); + return $initialized; } @@ -76,7 +81,8 @@ public function prepareQueryBeforeCount(xPDOQuery $c) if (!empty($query)) { $c->where([ 'key:LIKE' => '%' . $query . '%', - 'OR:description:LIKE' => '%' . $query . '%', + 'OR:name:LIKE' => '%' . $query . '%', + 'OR:description:LIKE' => '%' . $query . '%' ]); } $exclude = $this->getProperty('exclude'); @@ -149,24 +155,30 @@ public function prepareQueryAfterCount(xPDOQuery $c) /** * {@inheritDoc} - * @param xPDOObject $object - * + * @param xPDOObject|modContext $object * @return array */ public function prepareRow(xPDOObject $object) { - $contextArray = $object->toArray(); - $contextArray['perm'] = []; - if ($this->canCreate) { - $contextArray['perm'][] = 'pnew'; - } - if ($this->canEdit) { - $contextArray['perm'][] = 'pedit'; - } - if (!in_array($object->get('key'), $this->classKey::RESERVED_KEYS) && $this->canRemove) { - $contextArray['perm'][] = 'premove'; + $permissions = [ + 'create' => $this->canCreate && $object->checkPolicy('save'), + 'duplicate' => $this->canCreate && $object->checkPolicy('copy'), + 'update' => $this->canEdit && $object->checkPolicy('save'), + 'delete' => $this->canRemove && $object->checkPolicy('remove') + ]; + + $contextData = $object->toArray(); + $contextKey = $contextData['key']; + $isCoreContext = $object->isCoreContext($contextKey); + + $contextData['reserved'] = ['key' => $this->coreContexts, 'name' => ['Manager']]; + $contextData['isProtected'] = $isCoreContext; + $contextData['creator'] = $isCoreContext ? 'modx' : strtolower($this->modx->lexicon('user')) ; + if ($isCoreContext) { + unset($permissions['delete']); } + $contextData['permissions'] = $permissions; - return $contextArray; + return $contextData; } } diff --git a/core/src/Revolution/Processors/Element/PropertySet/Get.php b/core/src/Revolution/Processors/Element/PropertySet/Get.php index 7b04a021a7b..64137141435 100644 --- a/core/src/Revolution/Processors/Element/PropertySet/Get.php +++ b/core/src/Revolution/Processors/Element/PropertySet/Get.php @@ -1,4 +1,5 @@ default = $this->getDefaultSet(); $id = $this->getProperty($this->primaryKeyField); + + $canSave = $this->modx->hasPermission('save_propertyset'); + $this->canCreate = $canSave && $this->modx->hasPermission('new_propertyset'); + $this->canEdit = $canSave && $this->modx->hasPermission('edit_propertyset'); + $this->canRemove = $this->modx->hasPermission('delete_propertyset'); + if ($id == 0) { if (empty($this->default)) { return $this->modx->lexicon($this->objectType . '_err_nfs', ['id' => $id]); @@ -158,6 +168,11 @@ public function setData(array $properties, array &$data, $isDefault = false) $property['desc_trans'], !empty($property['area']) ? $property['area'] : '', !empty($property['area_trans']) ? $property['area_trans'] : ($isDefault ? '' : $property['area']), + [ + 'create' => $this->canCreate, + 'update' => $this->canEdit, + 'delete' => $this->canRemove + ] ]; } } diff --git a/core/src/Revolution/Processors/Element/PropertySet/GetList.php b/core/src/Revolution/Processors/Element/PropertySet/GetList.php index ee2ce443cb5..3bed14e4e12 100644 --- a/core/src/Revolution/Processors/Element/PropertySet/GetList.php +++ b/core/src/Revolution/Processors/Element/PropertySet/GetList.php @@ -1,4 +1,5 @@ node = explode('_', $id); - /* check permissions */ - $this->has = [ - 'save' => $this->modx->hasPermission('save_propertyset'), - 'remove' => $this->modx->hasPermission('delete_propertyset'), - 'new' => $this->modx->hasPermission('new_propertyset'), - ]; + $this->canCreate = $this->modx->hasPermission('save_propertyset') && $this->modx->hasPermission('new_propertyset'); + $this->canEdit = $this->modx->hasPermission('save_propertyset') && $this->modx->hasPermission('edit_propertyset'); + $this->canRemove = $this->modx->hasPermission('delete_propertyset'); return true; } @@ -65,7 +64,7 @@ public function initialize() * * @return string */ - function getNodeIcon($elementIdentifier = '') + public function getNodeIcon($elementIdentifier = '') { $elementIdentifier = strtolower($elementIdentifier); $defaults = [ @@ -134,7 +133,7 @@ public function getCategoryNode($category) /** @var modPropertySet $set */ foreach ($sets as $set) { $menu = []; - if ($this->has['save']) { + if ($this->canEdit) { $menu[] = [ 'text' => $this->modx->lexicon($this->objectType . '_element_add'), 'handler' => 'function(itm,e) { @@ -149,7 +148,7 @@ public function getCategoryNode($category) }', ]; } - if ($this->has['new'] && $this->has['save']) { + if ($this->canCreate) { $menu[] = [ 'text' => $this->modx->lexicon($this->objectType . '_duplicate'), 'handler' => 'function(itm,e) { @@ -157,7 +156,7 @@ public function getCategoryNode($category) }', ]; } - if ($this->has['remove']) { + if ($this->canRemove) { $menu[] = '-'; $menu[] = [ 'text' => $this->modx->lexicon($this->objectType . '_remove'), @@ -218,7 +217,10 @@ public function getPropertySetNode() continue; } $menu = []; - if ($this->has['remove']) { + /* + Note that this action removes (detaches) an Element from a given Property Set, which is really an edit of that Set + */ + if ($this->canEdit) { $menu[] = [ 'text' => $this->modx->lexicon($this->objectType . '_element_remove'), 'handler' => 'function(itm,e) { diff --git a/core/src/Revolution/Processors/Element/Template/TemplateVar/GetList.php b/core/src/Revolution/Processors/Element/Template/TemplateVar/GetList.php index b32d6c4d63e..eee08d166c5 100644 --- a/core/src/Revolution/Processors/Element/Template/TemplateVar/GetList.php +++ b/core/src/Revolution/Processors/Element/Template/TemplateVar/GetList.php @@ -42,6 +42,9 @@ class GetList extends GetListProcessor protected $query = ''; protected $isFiltered = false; + public $canEdit = false; + public $canEditTv = false; + /** * {@inheritDoc} */ @@ -50,6 +53,9 @@ public function initialize() $this->category = (int)$this->getProperty('category', 0); $this->query = $this->getProperty('query', ''); $this->isFiltered = $this->category > 0 || $this->query; + $this->canEdit = $this->modx->hasPermission('edit_template') && $this->modx->hasPermission('save_template'); + $this->canEditTv = $this->modx->hasPermission('edit_tv') && $this->modx->hasPermission('save_tv'); + return parent::initialize(); } @@ -156,16 +162,17 @@ public function prepareQueryBeforeCount(xPDOQuery $c) /** * {@inheritDoc} + * @param xPDOObject|modTemplateVar $object */ public function prepareRow(xPDOObject $object) { + $permissions = [ + 'update' => $this->canEdit, + 'updateTv' => $this->canEditTv && $object->checkPolicy('save') + ]; $tvArray = $object->get(['id', 'name', 'caption', 'tv_rank', 'category_name']); $tvArray['access'] = (bool)$object->get('access'); - - $tvArray['perm'] = []; - if ($this->modx->hasPermission('edit_tv')) { - $tvArray['perm'][] = 'pedit'; - } + $tvArray['permissions'] = $permissions; return $tvArray; } diff --git a/core/src/Revolution/Processors/Element/TemplateVar/ResourceGroup/GetList.php b/core/src/Revolution/Processors/Element/TemplateVar/ResourceGroup/GetList.php index cd2ccd45ec7..29927770f5a 100644 --- a/core/src/Revolution/Processors/Element/TemplateVar/ResourceGroup/GetList.php +++ b/core/src/Revolution/Processors/Element/TemplateVar/ResourceGroup/GetList.php @@ -1,4 +1,5 @@ toArray(); $resourceGroupArray['access'] = $rgtv ? true : false; - $resourceGroupArray['menu'] = []; return $resourceGroupArray; } diff --git a/core/src/Revolution/Processors/Element/TemplateVar/Template/GetList.php b/core/src/Revolution/Processors/Element/TemplateVar/Template/GetList.php index 0b995785b5d..7a623b6ab2e 100644 --- a/core/src/Revolution/Processors/Element/TemplateVar/Template/GetList.php +++ b/core/src/Revolution/Processors/Element/TemplateVar/Template/GetList.php @@ -30,6 +30,9 @@ */ class GetList extends Processor { + public $canEdit = false; + public $canEditTemplate = false; + public function checkPermissions() { return $this->modx->hasPermission('view_tv'); @@ -49,8 +52,10 @@ public function initialize() 'dir' => 'ASC', 'tv' => false, ]); + $this->canEdit = $this->modx->hasPermission('edit_tv') && $this->modx->hasPermission('save_tv'); + $this->canEditTemplate = $this->modx->hasPermission('edit_template') && $this->modx->hasPermission('save_template'); - return true; + return parent::initialize(); } public function process() @@ -133,9 +138,14 @@ public function getData() */ public function prepareRow(modTemplate $template) { + $permissions = [ + 'update' => $this->canEdit, + 'updateTemplate' => $this->canEditTemplate && $template->checkPolicy('save') + ]; $templateArray = $template->toArray(); $templateArray['category_name'] = $template->get('category_name'); unset($templateArray['content']); + $templateArray['permissions'] = $permissions; return $templateArray; } diff --git a/core/src/Revolution/Processors/Model/GetListProcessor.php b/core/src/Revolution/Processors/Model/GetListProcessor.php index f9ff359eb16..e7cff26f76d 100644 --- a/core/src/Revolution/Processors/Model/GetListProcessor.php +++ b/core/src/Revolution/Processors/Model/GetListProcessor.php @@ -25,7 +25,9 @@ */ abstract class GetListProcessor extends ModelProcessor { + /** @deprecated as of MODX 3.1.0; new permissions handling replaces css class-based specifiers */ public const CLASS_ALLOW_EDIT = 'pedit'; + /** @deprecated as of MODX 3.1.0; new permissions handling replaces css class-based specifiers */ public const CLASS_ALLOW_REMOVE = 'premove'; /** @var string $defaultSortField The default field to sort by */ diff --git a/core/src/Revolution/Processors/Resource/Trash/GetList.php b/core/src/Revolution/Processors/Resource/Trash/GetList.php index 79234f46ac6..52766c890e1 100644 --- a/core/src/Revolution/Processors/Resource/Trash/GetList.php +++ b/core/src/Revolution/Processors/Resource/Trash/GetList.php @@ -40,11 +40,21 @@ class GetList extends GetListProcessor public $permission = 'view'; + public $canPurge = false; + public $canUndelete = false; + public $canUPublish = false; + private modManagerDateFormatter $formatter; public function initialize() { $this->formatter = $this->modx->services->get(modManagerDateFormatter::class); + + $canChange = $this->modx->hasPermission('save_document') && $this->modx->hasPermission('edit_document'); + $this->canPurge = $canChange && $this->modx->hasPermission('purge_deleted'); + $this->canUndelete = $canChange && $this->modx->hasPermission('undelete_document'); + $this->canUPublish = $canChange && $this->modx->hasPermission('publish_document'); + return parent::initialize(); } @@ -138,16 +148,22 @@ public function prepareRow(xPDOObject $object) return []; } + $permissions = [ + 'purge' => $this->canPurge && $object->checkPolicy('purge_deleted'), + 'undelete' => $this->canUndelete && $object->checkPolicy('undelete_document'), + 'publish' => $this->canUPublish && $object->checkPolicy('publish_document') + ]; + $charset = $this->modx->getOption('modx_charset', null, 'UTF-8'); - $objectArray = $object->toArray(); - $objectArray['pagetitle'] = htmlentities($objectArray['pagetitle'], ENT_COMPAT, $charset); - $objectArray['content'] = htmlentities($objectArray['content'], ENT_COMPAT, $charset); + $resourceData = $object->toArray(); + $resourceData['pagetitle'] = htmlentities($resourceData['pagetitle'], ENT_COMPAT, $charset); + $resourceData['content'] = htmlentities($resourceData['content'], ENT_COMPAT, $charset); // to enable a better detection of the resource's location, we also construct the // parent-child path to the resource $parents = []; - $parent = $objectArray['parent']; + $parent = $resourceData['parent']; while ($parent != 0) { $parentObject = $this->modx->getObject(modResource::class, $parent); @@ -163,46 +179,11 @@ public function prepareRow(xPDOObject $object) foreach ($parents as $parent) { $parentPath = $parent->get('pagetitle') . ' (' . $parent->get('id') . ') > ' . $parentPath; } - $objectArray['parentPath'] = '[' . $objectArray['context_key'] . '] ' . $parentPath; - - // TODO implement permission checks for every resource and return only resources user is allowed to see - - // show the permissions for the context - $canView = $this->modx->hasPermission('view_document'); - $canPurge = $this->modx->hasPermission('purge_deleted'); - $canUndelete = $this->modx->hasPermission('undelete_document'); - $canPublish = $this->modx->hasPermission('publish_document'); - $canSave = $this->modx->hasPermission('save_document'); - $canEdit = $this->modx->hasPermission('edit_document'); - $canList = $this->modx->hasPermission('list'); - $canLoad = $this->modx->hasPermission('load'); - - $objectArray['iconCls'] = $this->modx->getOption('mgr_source_icon', null, 'icon-folder-open-o'); - - $cls = []; - $cls[] = 'restore'; - $cls[] = 'purge'; - $cls[] = 'undelete_document'; - - $cls = []; - if ($object->checkPolicy('purge_deleted') && $canSave && $canEdit && $canPurge) { - $cls[] = 'trashpurge'; - } - if ($object->checkPolicy('undelete_document') && $canSave && $canEdit) { - $cls[] = 'trashundelete'; - } - if ($object->checkPolicy('save') && $canSave && $canEdit) { - $cls[] = 'trashsave'; - } - if ($object->checkPolicy('edit') && $canSave && $canEdit) { - $cls[] = 'trashedit'; - } - $cls[] = 'trashrow'; - - $objectArray['cls'] = implode(' ', $cls); + $resourceData['parentPath'] = '[' . $resourceData['context_key'] . '] ' . $parentPath; - $objectArray['deletedon'] = $this->formatter->formatDateTime($objectArray['deletedon']); + $resourceData['deletedon'] = $this->formatter->formatDateTime($resourceData['deletedon']); + $resourceData['permissions'] = $permissions; - return $objectArray; + return $resourceData; } } diff --git a/core/src/Revolution/Processors/Security/Access/GetList.php b/core/src/Revolution/Processors/Security/Access/GetList.php index e1d4da8362d..847f018ba4f 100644 --- a/core/src/Revolution/Processors/Security/Access/GetList.php +++ b/core/src/Revolution/Processors/Security/Access/GetList.php @@ -1,4 +1,5 @@ modx->lexicon('access_type_err_ns'); } + $canManage = $this->modx->hasPermission('access_permissions'); + $this->canCreate = $canManage; + $this->canEdit = $canManage; + $this->canRemove = $canManage; + $this->canEditGroups = $this->modx->hasPermission('usergroup_edit'); + $this->canEditPolicies = $this->modx->hasPermission('policy_edit'); + return parent::initialize(); } @@ -135,7 +149,7 @@ public function prepareRow(xPDOObject $object) $targetName = $this->getAnonymName(); } - $objArray = [ + $accessData = [ 'id' => $object->get('id'), 'target' => $object->get('target'), 'target_name' => $targetName, @@ -148,13 +162,24 @@ public function prepareRow(xPDOObject $object) ]; if (isset($object->_fieldMeta['context_key'])) { - $objArray['context_key'] = $object->get('context_key'); + $accessData['context_key'] = $object->get('context_key'); } // Prevent default Admin ACL from edit and remove - $objArray['cls'] = (($object->get('target') === 'mgr') && ($principal->get('name') === 'Administrator') && ($policyName === 'Administrator') && ($object->get('authority') === 0)) ? '' : 'pedit premove'; + if (($object->get('target') === 'mgr') && ($principal->get('name') === 'Administrator') && ($policyName === 'Administrator') && ($object->get('authority') === 0)) { + $accessData['permissions'] = []; + $accessData['isProtected'] = true; + } else { + $accessData['permissions'] = [ + 'create' => $this->canCreate, + 'update' => $this->canEdit, + 'delete' => $this->canRemove + ]; + } + $accessData['canEditGroups'] = $this->canEditGroups; + $accessData['canEditPolicies'] = $this->canEditPolicies; - return $objArray; + return $accessData; } /** diff --git a/core/src/Revolution/Processors/Security/Access/Policy/GetList.php b/core/src/Revolution/Processors/Security/Access/Policy/GetList.php index 94c420f6b5b..7c15d59a28e 100644 --- a/core/src/Revolution/Processors/Security/Access/Policy/GetList.php +++ b/core/src/Revolution/Processors/Security/Access/Policy/GetList.php @@ -44,6 +44,13 @@ class GetList extends GetListProcessor /** @param boolean $isGridFilter Indicates the target of this list data is a filter field */ protected $isGridFilter = false; + public $canCreate = false; + public $canEdit = false; + public $canEditTemplate = false; + public $canRemove = false; + protected $corePolicies; + protected $corePolicyTemplates; + // private $templatesTranslated = []; /** * @return bool @@ -56,8 +63,17 @@ public function initialize() 'group' => false, 'combo' => false, 'query' => '', + 'exclude' => 'creator' ]); $this->isGridFilter = $this->getProperty('isGridFilter', false); + + $this->canCreate = $this->modx->hasPermission('policy_new') && $this->modx->hasPermission('policy_save'); + $this->canEdit = $this->modx->hasPermission('policy_edit'); + $this->canEditTemplate = $this->modx->hasPermission('policy_template_edit'); + $this->canRemove = $this->modx->hasPermission('policy_delete'); + $this->corePolicies = $this->classKey::getCorePolicies(); + $this->corePolicyTemplates = modAccessPolicyTemplate::getCoreTemplates(); + return $initialized; } @@ -206,45 +222,60 @@ public function beforeIteration(array $list) } /** - * @param xPDOObject $object + * @param xPDOObject|modAccessPolicy $object * @return array */ public function prepareRow(xPDOObject $object) { - $policy = $object->toArray(); + $permissions = [ + 'create' => $this->canCreate, + 'duplicate' => $this->canCreate, + 'update' => $this->canEdit, + 'updateTemplate' => $this->canEditTemplate, + 'delete' => $this->canRemove + ]; + $policyData = $object->toArray(); + $policyName = $object->get('name'); + $policyPermissions = $object->get('data'); + $isCorePolicy = $object->isCorePolicy($policyName); + $this->setActivePermissionsCount($policyData, $policyPermissions); + + $policyData['reserved'] = ['name' => $this->corePolicies]; + $policyData['isProtected'] = $isCorePolicy; + $policyData['creator'] = $isCorePolicy ? 'modx' : strtolower($this->modx->lexicon('user')) ; + if ($isCorePolicy) { + unset($permissions['delete']); + } + $policyData['permissions'] = $permissions; + $policyData['policyPermissions'] = array_keys($policyPermissions, 1); + $policyData['description_trans'] = $this->modx->lexicon($policyData['description']); + unset($policyData['data']); - $policy['cls'] = $this->prepareRowClasses($object); + return $policyData; + } - $permissions = []; + protected function setActivePermissionsCount(array &$policy, array $data) + { if (!empty($policy['total_permissions'])) { - $data = $object->get('data'); - $ct = 0; + $n = 0; if (!empty($data)) { foreach ($data as $k => $v) { if (!empty($v)) { - $permissions[] = $k; - $ct++; + $n++; } } } - $policy['active_permissions'] = $ct; + $policy['active_permissions'] = $n; $policy['active_of'] = $this->modx->lexicon('active_of', [ 'active' => $policy['active_permissions'], 'total' => $policy['total_permissions'], ]); - $policy['permissions'] = $permissions; } - - unset($policy['data']); - - $policy['description_trans'] = $this->modx->lexicon($policy['description']); - - return $policy; } /** * @param xPDOObject|modAccessPolicy $object - * + * @deprecated as of MODX 3.1.0; new permissions handling replaces css class-based specifiers * @return string */ protected function prepareRowClasses(xPDOObject $object) diff --git a/core/src/Revolution/Processors/Security/Access/Policy/Template/GetList.php b/core/src/Revolution/Processors/Security/Access/Policy/Template/GetList.php index 877a7b5f32f..5008e29bb92 100644 --- a/core/src/Revolution/Processors/Security/Access/Policy/Template/GetList.php +++ b/core/src/Revolution/Processors/Security/Access/Policy/Template/GetList.php @@ -36,6 +36,14 @@ class GetList extends GetListProcessor public $permission = 'policy_template_view'; public $languageTopics = ['policy', 'en:policy']; + /** @param boolean $isGridFilter Indicates the target of this list data is a filter field */ + protected $isGridFilter = false; + public $canCreate = false; + public $canEdit = false; + public $canRemove = false; + protected $corePolicyTemplates; + protected $corePolicyTemplateGroups; + /** * @return bool */ @@ -45,7 +53,16 @@ public function initialize() $this->setDefaultProperties([ 'sortAlias' => 'modAccessPolicyTemplate', 'query' => '', + 'exclude' => 'creator' ]); + $this->isGridFilter = $this->getProperty('isGridFilter', false); + + $this->canCreate = $this->modx->hasPermission('policy_template_new') && $this->modx->hasPermission('policy_template_save'); + $this->canEdit = $this->modx->hasPermission('policy_template_edit'); + $this->canRemove = $this->modx->hasPermission('policy_template_delete'); + $this->corePolicyTemplates = $this->classKey::getCoreTemplates(); + $this->corePolicyTemplateGroups = modAccessPolicyTemplateGroup::getCoreGroups(); + return $initialized; } @@ -104,22 +121,36 @@ public function prepareQueryAfterCount(xPDOQuery $c) } /** - * @param xPDOObject $object + * @param xPDOObject|modAccessPolicyTemplate $object * @return array */ public function prepareRow(xPDOObject $object) { - $template = $object->toArray(); - - $template['description_trans'] = $this->modx->lexicon($template['description']); - $template['cls'] = $this->prepareRowClasses($object); + $permissions = [ + 'create' => $this->canCreate, + 'duplicate' => $this->canCreate, + 'update' => $this->canEdit, + 'delete' => $this->canRemove + ]; + $templateData = $object->toArray(); + $templateName = $object->get('name'); + $isCoreTemplate = $object->isCoreTemplate($templateName); + + $templateData['reserved'] = ['name' => $this->corePolicyTemplates]; + $templateData['isProtected'] = $isCoreTemplate; + $templateData['creator'] = $isCoreTemplate ? 'modx' : strtolower($this->modx->lexicon('user')) ; + if ($isCoreTemplate) { + unset($permissions['delete']); + } + $templateData['permissions'] = $permissions; + $templateData['description_trans'] = $this->modx->lexicon($templateData['description']); - return $template; + return $templateData; } /** * @param xPDOObject|modAccessPolicyTemplate $object - * + * @deprecated as of MODX 3.1.0; new permissions handling replaces css class-based specifiers * @return string */ protected function prepareRowClasses(xPDOObject $object) diff --git a/core/src/Revolution/Processors/Security/Access/Policy/Template/Group/GetList.php b/core/src/Revolution/Processors/Security/Access/Policy/Template/Group/GetList.php index 9ba6a537f4e..74691b65303 100644 --- a/core/src/Revolution/Processors/Security/Access/Policy/Template/Group/GetList.php +++ b/core/src/Revolution/Processors/Security/Access/Policy/Template/Group/GetList.php @@ -1,4 +1,5 @@ toArray(); - - $group['cls'] = static::CLASS_ALLOW_EDIT; $group['description'] = $this->modx->lexicon($group['description']); return $group; diff --git a/core/src/Revolution/Processors/Security/Access/UserGroup/AccessNamespace/GetList.php b/core/src/Revolution/Processors/Security/Access/UserGroup/AccessNamespace/GetList.php index 10ed7a3fd00..02361ce4679 100644 --- a/core/src/Revolution/Processors/Security/Access/UserGroup/AccessNamespace/GetList.php +++ b/core/src/Revolution/Processors/Security/Access/UserGroup/AccessNamespace/GetList.php @@ -42,6 +42,13 @@ class GetList extends GetListProcessor /** @var modUserGroup $userGroup */ public $userGroup; + /** @var bool $canCreate Whether user can assign a new Category ACL entry for a given User Group */ + public $canCreate = false; + /** @var bool $canEdit Whether user can change a Category ACL entry for a given User Group */ + public $canEdit = false; + /** @var bool $canRemove Whether user can remove a Category ACL entry for a given User Group */ + public $canRemove = false; + /** * @return bool */ @@ -64,6 +71,15 @@ public function initialize() if ($this->getProperty('sort') == 'role_display') { $this->setProperty('sort', 'authority'); } + /* + Currently, all actions essentially relate to editing a User Group. + Nonetheless, we maintain each separately to remain consistent with how permissions + are relayed throughout the MODX app + */ + $canChange = $this->modx->hasPermission('usergroup_edit') && $this->modx->hasPermission('usergroup_save'); + $this->canCreate = $canChange; + $this->canEdit = $canChange; + $this->canRemove = $canChange; return $initialized; } @@ -142,33 +158,31 @@ public function useSecondaryGroupCondition(string $sortBy, string $groupBy, stri */ public function prepareRow(xPDOObject $object) { - $objectArray = $object->toArray(); - if (empty($objectArray['name'])) { - $objectArray['name'] = '(' . $this->modx->lexicon('none') . ')'; + $permissions = [ + 'create' => $this->canCreate, + 'update' => $this->canEdit, + 'delete' => $this->canRemove + ]; + + $aclData = $object->toArray(); + if (empty($aclData['name'])) { + $aclData['name'] = '(' . $this->modx->lexicon('none') . ')'; } - $objectArray['authority_name'] = !empty($objectArray['role_name']) - ? $objectArray['role_name'] . ' - ' . $objectArray['authority'] - : $objectArray['authority'] + $aclData['authority_name'] = !empty($aclData['role_name']) + ? $aclData['role_name'] . ' - ' . $aclData['authority'] + : $aclData['authority'] ; /* get permissions list */ - $data = $objectArray['policy_data']; - unset($objectArray['policy_data']); + $aclData['policyPermissions'] = []; + $data = $aclData['policy_data']; + unset($aclData['policy_data']); $data = $this->modx->fromJSON($data); if (!empty($data)) { - $permissions = []; - foreach ($data as $permission => $enabled) { - if (!$enabled) { - continue; - } - $permissions[] = $permission; - } - $objectArray['permissions'] = implode(', ', $permissions); + $aclData['policyPermissions'] = array_keys($data, 1); } + $aclData['permissions'] = $permissions; - $cls = 'pedit premove'; - $objectArray['cls'] = $cls; - - return $objectArray; + return $aclData; } } diff --git a/core/src/Revolution/Processors/Security/Access/UserGroup/Category/GetList.php b/core/src/Revolution/Processors/Security/Access/UserGroup/Category/GetList.php index a65e1f1198f..ccfdf0ff795 100644 --- a/core/src/Revolution/Processors/Security/Access/UserGroup/Category/GetList.php +++ b/core/src/Revolution/Processors/Security/Access/UserGroup/Category/GetList.php @@ -43,6 +43,13 @@ class GetList extends GetListProcessor /** @var modUserGroup $userGroup */ public $userGroup; + /** @var bool $canCreate Whether user can assign a new Category ACL entry for a given User Group */ + public $canCreate = false; + /** @var bool $canEdit Whether user can change a Category ACL entry for a given User Group */ + public $canEdit = false; + /** @var bool $canRemove Whether user can remove a Category ACL entry for a given User Group */ + public $canRemove = false; + /** * @return bool */ @@ -65,6 +72,15 @@ public function initialize() if ($this->getProperty('sort') == 'role_display') { $this->setProperty('sort', 'authority'); } + /* + Currently, all actions essentially relate to editing a User Group. + Nonetheless, we maintain each separately to remain consistent with how permissions + are relayed throughout the MODX app + */ + $canChange = $this->modx->hasPermission('usergroup_edit') && $this->modx->hasPermission('usergroup_save'); + $this->canCreate = $canChange; + $this->canEdit = $canChange; + $this->canRemove = $canChange; return $initialized; } @@ -143,33 +159,35 @@ public function useSecondaryGroupCondition(string $sortBy, string $groupBy, stri */ public function prepareRow(xPDOObject $object) { - $objectArray = $object->toArray(); - if (empty($objectArray['name'])) { - $objectArray['name'] = '(' . $this->modx->lexicon('none') . ')'; + $permissions = [ + 'create' => $this->canCreate, + 'update' => $this->canEdit, + 'delete' => $this->canRemove + ]; + + $aclData = $object->toArray(); + if (empty($aclData['name'])) { + $aclData['name'] = '(' . $this->modx->lexicon('none') . ')'; } /* get permissions list */ - $data = $objectArray['policy_data']; - unset($objectArray['policy_data']); + $aclData['policyPermissions'] = []; + $data = $aclData['policy_data']; + unset($aclData['policy_data']); $data = $this->modx->fromJSON($data); if (!empty($data)) { - $permissions = []; - foreach ($data as $permission => $enabled) { - if (!$enabled) { - continue; - } - $permissions[] = $permission; - } - $objectArray['permissions'] = implode(', ', $permissions); + $aclData['policyPermissions'] = array_keys($data, 1); } - - $cls = ''; - if (($objectArray['target'] === 'web' || $objectArray['target'] === 'mgr') && $objectArray['policy_name'] === 'Administrator' && ($this->userGroup && $this->userGroup->get('name') === 'Administrator')) { - } else { - $cls .= 'pedit premove'; + if ( + in_array($aclData['target'], ['web', 'mgr']) + && $aclData['policy_name'] === 'Administrator' + && ($this->userGroup && $this->userGroup->get('name') === 'Administrator') + ) { + $permissions['edit'] = false; + $permissions['delete'] = false; } - $objectArray['cls'] = $cls; + $aclData['permissions'] = $permissions; - return $objectArray; + return $aclData; } } diff --git a/core/src/Revolution/Processors/Security/Access/UserGroup/Context/GetList.php b/core/src/Revolution/Processors/Security/Access/UserGroup/Context/GetList.php index 26ced21f3b9..ea97f0989ea 100644 --- a/core/src/Revolution/Processors/Security/Access/UserGroup/Context/GetList.php +++ b/core/src/Revolution/Processors/Security/Access/UserGroup/Context/GetList.php @@ -41,6 +41,13 @@ class GetList extends GetListProcessor /** @var modUserGroup $userGroup */ public $userGroup; + /** @var bool $canCreate Whether user can assign a new Context ACL entry for a given User Group */ + public $canCreate = false; + /** @var bool $canEdit Whether user can change a Context ACL entry for a given User Group */ + public $canEdit = false; + /** @var bool $canRemove Whether user can remove a Context ACL entry for a given User Group */ + public $canRemove = false; + /** * @return mixed */ @@ -63,6 +70,15 @@ public function initialize() if ($this->getProperty('sort') == 'role_display') { $this->setProperty('sort', 'authority'); } + /* + Currently, all actions essentially relate to editing a User Group. + Nonetheless, we maintain each separately to remain consistent with how permissions + are relayed throughout the MODX app + */ + $canChange = $this->modx->hasPermission('usergroup_edit') && $this->modx->hasPermission('usergroup_save'); + $this->canCreate = $canChange; + $this->canEdit = $canChange; + $this->canRemove = $canChange; return $initialized; } @@ -135,37 +151,35 @@ public function useSecondaryGroupCondition(string $sortBy, string $groupBy, stri */ public function prepareRow(xPDOObject $object) { - $objectArray = $object->toArray(); - if (empty($objectArray['name'])) { - $objectArray['name'] = '(' . $this->modx->lexicon('none') . ')'; + $permissions = [ + 'create' => $this->canCreate, + 'update' => $this->canEdit, + 'delete' => $this->canRemove + ]; + + $aclData = $object->toArray(); + if (empty($aclData['name'])) { + $aclData['name'] = '(' . $this->modx->lexicon('none') . ')'; } /* get permissions list */ - $data = $objectArray['policy_data']; - unset($objectArray['policy_data']); + $aclData['policyPermissions'] = []; + $data = $aclData['policy_data']; + unset($aclData['policy_data']); $data = $this->modx->fromJSON($data); if (!empty($data)) { - $permissions = []; - foreach ($data as $permission => $enabled) { - if (!$enabled) { - continue; - } - $permissions[] = $permission; - } - $objectArray['permissions'] = implode(', ', $permissions); + $aclData['policyPermissions'] = array_keys($data, 1); } - - $cls = ''; if ( - ($objectArray['target'] === 'web' || $objectArray['target'] === 'mgr') - && $objectArray['policy_name'] === 'Administrator' + in_array($aclData['target'], ['web', 'mgr']) + && $aclData['policy_name'] === 'Administrator' && ($this->userGroup && $this->userGroup->get('name') === 'Administrator') ) { - } else { - $cls .= 'pedit premove'; + $permissions['edit'] = false; + $permissions['delete'] = false; } - $objectArray['cls'] = $cls; + $aclData['permissions'] = $permissions; - return $objectArray; + return $aclData; } } diff --git a/core/src/Revolution/Processors/Security/Access/UserGroup/ResourceGroup/GetList.php b/core/src/Revolution/Processors/Security/Access/UserGroup/ResourceGroup/GetList.php index 2b951b2392a..2e49ace8927 100644 --- a/core/src/Revolution/Processors/Security/Access/UserGroup/ResourceGroup/GetList.php +++ b/core/src/Revolution/Processors/Security/Access/UserGroup/ResourceGroup/GetList.php @@ -43,6 +43,13 @@ class GetList extends GetListProcessor /** @var modUserGroup $userGroup */ public $userGroup; + /** @var bool $canCreate Whether user can assign a new Resource Group ACL entry for a given User Group */ + public $canCreate = false; + /** @var bool $canEdit Whether user can change a Resource Group ACL entry for a given User Group */ + public $canEdit = false; + /** @var bool $canRemove Whether user can remove a Resource Group ACL entry for a given User Group */ + public $canRemove = false; + /** * @return bool */ @@ -65,6 +72,16 @@ public function initialize() if ($this->getProperty('sort') == 'role_display') { $this->setProperty('sort', 'authority'); } + /* + Currently, all actions essentially relate to editing a User Group. + Nonetheless, we maintain each separately to remain consistent with how permissions + are relayed throughout the MODX app + */ + $canChange = $this->modx->hasPermission('usergroup_edit') && $this->modx->hasPermission('usergroup_save'); + $this->canCreate = $canChange; + $this->canEdit = $canChange; + $this->canRemove = $canChange; + return $initialized; } @@ -143,36 +160,35 @@ public function useSecondaryGroupCondition(string $sortBy, string $groupBy, stri */ public function prepareRow(xPDOObject $object) { - $objectArray = $object->toArray(); - if (empty($objectArray['name'])) { - $objectArray['name'] = '(' . $this->modx->lexicon('none') . ')'; + $permissions = [ + 'create' => $this->canCreate, + 'update' => $this->canEdit, + 'delete' => $this->canRemove + ]; + + $aclData = $object->toArray(); + if (empty($aclData['name'])) { + $aclData['name'] = '(' . $this->modx->lexicon('none') . ')'; } /* get permissions list */ - $data = $objectArray['policy_data']; - unset($objectArray['policy_data']); + $aclData['policyPermissions'] = []; + $data = $aclData['policy_data']; + unset($aclData['policy_data']); $data = $this->modx->fromJSON($data); if (!empty($data)) { - foreach ($data as $permission => $enabled) { - if (!$enabled) { - continue; - } - $permissions[] = $permission; - } - $objectArray['permissions'] = implode(', ', $permissions); + $aclData['policyPermissions'] = array_keys($data, 1); } - - $cls = ''; if ( - ($objectArray['target'] === 'web' || $objectArray['target'] == 'mgr') - && $objectArray['policy_name'] === 'Administrator' + in_array($aclData['target'], ['web', 'mgr']) + && $aclData['policy_name'] === 'Administrator' && ($this->userGroup && $this->userGroup->get('name') === 'Administrator') ) { - } else { - $cls .= 'pedit premove'; + $permissions['edit'] = false; + $permissions['delete'] = false; } - $objectArray['cls'] = $cls; + $aclData['permissions'] = $permissions; - return $objectArray; + return $aclData; } } diff --git a/core/src/Revolution/Processors/Security/Access/UserGroup/Source/GetList.php b/core/src/Revolution/Processors/Security/Access/UserGroup/Source/GetList.php index dc3269c4ad9..a77f844e89a 100644 --- a/core/src/Revolution/Processors/Security/Access/UserGroup/Source/GetList.php +++ b/core/src/Revolution/Processors/Security/Access/UserGroup/Source/GetList.php @@ -42,6 +42,13 @@ class GetList extends GetListProcessor /** @var modUserGroup $userGroup */ public $userGroup; + /** @var bool $canCreate Whether user can assign a new Category ACL entry for a given User Group */ + public $canCreate = false; + /** @var bool $canEdit Whether user can change a Category ACL entry for a given User Group */ + public $canEdit = false; + /** @var bool $canRemove Whether user can remove a Category ACL entry for a given User Group */ + public $canRemove = false; + /** * @return mixed */ @@ -64,6 +71,15 @@ public function initialize() if ($this->getProperty('sort') == 'role_display') { $this->setProperty('sort', 'authority'); } + /* + Currently, all actions essentially relate to editing a User Group. + Nonetheless, we maintain each separately to remain consistent with how permissions + are relayed throughout the MODX app + */ + $canChange = $this->modx->hasPermission('usergroup_edit') && $this->modx->hasPermission('usergroup_save'); + $this->canCreate = $canChange; + $this->canEdit = $canChange; + $this->canRemove = $canChange; return $initialized; } @@ -149,41 +165,39 @@ public function useSecondaryGroupCondition(string $sortBy, string $groupBy, stri */ public function prepareRow(xPDOObject $object) { - $objectArray = $object->toArray(); - if (empty($objectArray['name'])) { - $objectArray['name'] = '(' . $this->modx->lexicon('none') . ')'; + $permissions = [ + 'create' => $this->canCreate, + 'update' => $this->canEdit, + 'delete' => $this->canRemove + ]; + + $aclData = $object->toArray(); + if (empty($aclData['name'])) { + $aclData['name'] = '(' . $this->modx->lexicon('none') . ')'; } - $objectArray['authority_name'] = !empty($objectArray['role_name']) - ? $objectArray['role_name'] . ' - ' . $objectArray['authority'] - : $objectArray['authority'] + $aclData['authority_name'] = !empty($aclData['role_name']) + ? $aclData['role_name'] . ' - ' . $aclData['authority'] + : $aclData['authority'] ; /* get permissions list */ - $data = $objectArray['policy_data']; - unset($objectArray['policy_data']); + $aclData['policyPermissions'] = []; + $data = $aclData['policy_data']; + unset($aclData['policy_data']); $data = $this->modx->fromJSON($data); if (!empty($data)) { - $permissions = []; - foreach ($data as $permission => $enabled) { - if (!$enabled) { - continue; - } - $permissions[] = $permission; - } - $objectArray['permissions'] = implode(', ', $permissions); + $aclData['policyPermissions'] = array_keys($data, 1); } - - $cls = ''; if ( - ($objectArray['target'] === 'web' || $objectArray['target'] === 'mgr') - && $objectArray['policy_name'] === 'Administrator' + in_array($aclData['target'], ['web', 'mgr']) + && $aclData['policy_name'] === 'Administrator' && ($this->userGroup && $this->userGroup->get('name') === 'Administrator') ) { - } else { - $cls .= 'pedit premove'; + $permissions['edit'] = false; + $permissions['delete'] = false; } - $objectArray['cls'] = $cls; + $aclData['permissions'] = $permissions; - return $objectArray; + return $aclData; } } diff --git a/core/src/Revolution/Processors/Security/Forms/Profile/GetList.php b/core/src/Revolution/Processors/Security/Forms/Profile/GetList.php index 907f2106a03..32c354b730c 100644 --- a/core/src/Revolution/Processors/Security/Forms/Profile/GetList.php +++ b/core/src/Revolution/Processors/Security/Forms/Profile/GetList.php @@ -28,6 +28,8 @@ class GetList extends GetListProcessor public $classKey = modFormCustomizationProfile::class; public $languageTopics = ['formcustomization']; public $permission = 'customize_forms'; + + public $canCreate = false; public $canEdit = false; public $canRemove = false; @@ -36,8 +38,12 @@ class GetList extends GetListProcessor */ public function initialize() { - $this->setDefaultProperties(['query' => '']); - $this->canEdit = $this->modx->hasPermission('save'); + $this->setDefaultProperties([ + 'query' => '' + ]); + $canSave = $this->modx->hasPermission('save'); + $this->canCreate = $canSave; + $this->canEdit = $canSave; $this->canRemove = $this->modx->hasPermission('remove'); return parent::initialize(); } @@ -74,14 +80,12 @@ public function getData() */ public function prepareRow(xPDOObject $object) { - $objectArray = $object->toArray(); - $objectArray['perm'] = []; - if ($this->canEdit) { - $objectArray['perm'][] = 'pedit'; - } - if ($this->canRemove) { - $objectArray['perm'][] = 'premove'; - } - return $objectArray; + $profileArray = $object->toArray(); + $profileArray['permissions'] = [ + 'create' => $this->canCreate, + 'update' => $this->canEdit, + 'delete' => $this->canRemove + ]; + return $profileArray; } } diff --git a/core/src/Revolution/Processors/Security/Forms/Set/GetList.php b/core/src/Revolution/Processors/Security/Forms/Set/GetList.php index 1fcd77a4cf9..4ceffddd44d 100644 --- a/core/src/Revolution/Processors/Security/Forms/Set/GetList.php +++ b/core/src/Revolution/Processors/Security/Forms/Set/GetList.php @@ -1,4 +1,5 @@ setDefaultProperties(['profile' => 0, 'query' => '']); - $this->canEdit = $this->modx->hasPermission('save'); + $this->setDefaultProperties([ + 'profile' => 0, + 'query' => '' + ]); + $canSave = $this->modx->hasPermission('save'); + $this->canCreate = $canSave; + $this->canEdit = $canSave; $this->canRemove = $this->modx->hasPermission('remove'); return parent::initialize(); } @@ -83,7 +91,7 @@ public function prepareQueryAfterCount(xPDOQuery $c) */ public function prepareRow(xPDOObject $object) { - $objectArray = $object->toArray(); + $fcSetArray = $object->toArray(); $constraint_field = $object->get('constraint_field'); $constraint = $object->get('constraint'); @@ -91,16 +99,14 @@ public function prepareRow(xPDOObject $object) if ($constraint === '') { $constraint = "'{$constraint}'"; } - $objectArray['constraint_data'] = $object->get('constraint_class') . '.' . $constraint_field . ' = ' . $constraint; - } - $objectArray['perm'] = []; - if ($this->canEdit) { - $objectArray['perm'][] = 'pedit'; - } - if ($this->canRemove) { - $objectArray['perm'][] = 'premove'; + $fcSetArray['constraint_data'] = $object->get('constraint_class') . '.' . $constraint_field . ' = ' . $constraint; } + $fcSetArray['permissions'] = [ + 'create' => $this->canCreate, + 'update' => $this->canEdit, + 'delete' => $this->canRemove + ]; - return $objectArray; + return $fcSetArray; } } diff --git a/core/src/Revolution/Processors/Security/Group/GetList.php b/core/src/Revolution/Processors/Security/Group/GetList.php index cb2e4e7f3b8..4405ec86887 100644 --- a/core/src/Revolution/Processors/Security/Group/GetList.php +++ b/core/src/Revolution/Processors/Security/Group/GetList.php @@ -1,4 +1,5 @@ false, 'combo' => false, ]); + $this->canEditGroups = $this->modx->hasPermission('usergroup_edit'); + $this->canEditRoles = $this->modx->hasPermission('edit_role'); return $initialized; } @@ -111,4 +118,17 @@ public function prepareQueryBeforeCount(xPDOQuery $c) return $c; } + + /** + * @param xPDOObject $object + * @return array + */ + public function prepareRow(xPDOObject $object) + { + $userGroupData = $object->toArray('', false, true); + $userGroupData['canEditGroups'] = $this->canEditGroups; + $userGroupData['canEditRoles'] = $this->canEditRoles; + + return $userGroupData; + } } diff --git a/core/src/Revolution/Processors/Security/Group/User/GetList.php b/core/src/Revolution/Processors/Security/Group/User/GetList.php index 628b8cf32d6..20920c2e896 100644 --- a/core/src/Revolution/Processors/Security/Group/User/GetList.php +++ b/core/src/Revolution/Processors/Security/Group/User/GetList.php @@ -35,6 +35,11 @@ class GetList extends GetListProcessor public $permission = 'usergroup_user_list'; public $languageTopics = ['user']; + protected $canEditGroups = false; + protected $canEditGroupUsers = false; + protected $canEditRoles = false; + protected $canEditUsers = false; + /** * @return bool */ @@ -44,6 +49,10 @@ public function initialize() 'usergroup' => false, 'query' => '' ]); + $this->canEditGroups = $this->modx->hasPermission('usergroup_edit') && $this->modx->hasPermission('usergroup_save'); + $this->canEditGroupUsers = $this->modx->hasPermission('usergroup_user_edit'); + $this->canEditRoles = $this->modx->hasPermission('edit_role') && $this->modx->hasPermission('save_role'); + $this->canEditUsers = $this->modx->hasPermission('edit_user') && $this->modx->hasPermission('save_user'); return parent::initialize(); } @@ -99,9 +108,15 @@ public function prepareQueryAfterCount(xPDOQuery $c) */ public function prepareRow(xPDOObject $object) { - $objectArray = $object->toArray('', false, true); - $objectArray['role_name'] .= ' - ' . $objectArray['authority']; + $groupUserData = $object->toArray('', false, true); + $groupUserData['role_name'] .= ' - ' . $groupUserData['authority']; + $groupUserData['permissions'] = [ + 'updateGroups' => $this->canEditGroups, + 'updateGroupUsers' => $this->canEditGroupUsers, + 'updateRoles' => $this->canEditRoles, + 'updateUsers' => $this->canEditUsers + ]; - return $objectArray; + return $groupUserData; } } diff --git a/core/src/Revolution/Processors/Security/Role/GetList.php b/core/src/Revolution/Processors/Security/Role/GetList.php index 69693afbed5..fc857e393a2 100644 --- a/core/src/Revolution/Processors/Security/Role/GetList.php +++ b/core/src/Revolution/Processors/Security/Role/GetList.php @@ -33,7 +33,11 @@ class GetList extends GetListProcessor public $languageTopics = ['user']; public $permission = 'view_role'; public $defaultSortField = 'authority'; + + public $canCreate = false; + public $canEdit = false; public $canRemove = false; + protected $coreRoles; /** * {@inheritDoc} @@ -49,7 +53,10 @@ public function initialize() $this->setProperty('sort', 'name'); } + $this->canCreate = $this->modx->hasPermission('new_role') && $this->modx->hasPermission('save_role'); + $this->canEdit = $this->modx->hasPermission('edit_role') && $this->modx->hasPermission('save_role'); $this->canRemove = $this->modx->hasPermission('delete_role'); + $this->coreRoles = $this->classKey::getCoreRoles(); return $initialized; } @@ -98,30 +105,32 @@ public function isAssigned(int $id) /** * {@inheritDoc} - * @param xPDOObject $object + * @param xPDOObject|modUserGroupRole $object * @return array */ public function prepareRow(xPDOObject $object) { - $objectArray = $object->toArray(); - $objectId = $object->get('id'); + // Note: Role does not have a checkPolicy() method + $permissions = [ + 'create' => $this->canCreate, + 'update' => $this->canEdit, + 'delete' => $this->canRemove + ]; + + $roleData = $object->toArray(); + $roleId = $object->get('id'); $roleName = $object->get('name'); - $isCoreRole = in_array($objectId, [1, 2]) || in_array($roleName, ['Super User', 'Member']); - - $perm = []; - if (!$isCoreRole) { - $perm[] = 'edit'; - if ($this->isAssigned($objectId)) { - $objectArray['isAssigned'] = 1; - } - if ($this->canRemove) { - $perm[] = 'remove'; - } - } else { - $objectArray['isProtected'] = 1; + $isCoreRole = $object->isCoreRole($roleName); + + if ($this->isAssigned($roleId)) { + $roleData['isAssigned'] = 1; } - $objectArray['perm'] = implode(' ', $perm); - return $objectArray; + $roleData['reserved'] = ['name' => $this->coreRoles]; + $roleData['isProtected'] = $isCoreRole; + $roleData['creator'] = $isCoreRole ? 'modx' : strtolower($this->modx->lexicon('user')) ; + $roleData['permissions'] = !$isCoreRole ? $permissions : [] ; + + return $roleData; } } diff --git a/core/src/Revolution/Processors/Security/User/Get.php b/core/src/Revolution/Processors/Security/User/Get.php index 98e86362546..ce891c4fd06 100644 --- a/core/src/Revolution/Processors/Security/User/Get.php +++ b/core/src/Revolution/Processors/Security/User/Get.php @@ -85,6 +85,9 @@ public function getGroups() $this->object->get('primary_group') === $member->get('user_group'), $member->get('rank'), $member->get('user_group_desc'), + $this->modx->hasPermission('usergroup_edit'), + $this->modx->hasPermission('usergroup_user_edit'), + $this->modx->hasPermission('edit_role') ]; } $this->object->set('groups', '(' . $this->modx->toJSON($data) . ')'); diff --git a/core/src/Revolution/Processors/Security/User/GetList.php b/core/src/Revolution/Processors/Security/User/GetList.php index a138ff2fd8b..af324b86afa 100644 --- a/core/src/Revolution/Processors/Security/User/GetList.php +++ b/core/src/Revolution/Processors/Security/User/GetList.php @@ -1,4 +1,5 @@ getProperty('sort') === 'id') { $this->setProperty('sort', $this->modx->getAlias($this->classKey) . '.id'); } + + $this->canCreate = $this->modx->hasPermission('new_user') && $this->modx->hasPermission('save_user'); + $this->canEdit = $this->modx->hasPermission('edit_user') && $this->modx->hasPermission('save_user'); + $this->canRemove = $this->modx->hasPermission('delete_user'); + return $initialized; } @@ -115,11 +125,16 @@ public function prepareQueryAfterCount(xPDOQuery $c) */ public function prepareRow(xPDOObject $object) { - $objectArray = $object->toArray(); - $objectArray['blocked'] = $object->get('blocked') ? true : false; - $objectArray['cls'] = 'pupdate premove pcopy'; - unset($objectArray['password'], $objectArray['cachepwd'], $objectArray['salt']); + $userData = $object->toArray(); + $userData['blocked'] = $object->get('blocked') ? true : false; + $userData['permissions'] = [ + 'create' => $this->canCreate, + 'duplicate' => $this->canCreate, + 'update' => $this->canEdit, + 'delete' => $this->canRemove + ]; + unset($userData['password'], $userData['cachepwd'], $userData['salt']); - return $objectArray; + return $userData; } } diff --git a/core/src/Revolution/Processors/Security/User/GetRecentlyEditedResources.php b/core/src/Revolution/Processors/Security/User/GetRecentlyEditedResources.php index f2a8955cb4e..ca047f0cb5b 100644 --- a/core/src/Revolution/Processors/Security/User/GetRecentlyEditedResources.php +++ b/core/src/Revolution/Processors/Security/User/GetRecentlyEditedResources.php @@ -81,7 +81,6 @@ public function prepareQueryBeforeCount(xPDOQuery $c) return $c; } - /** * Prepare the row for iteration * @param xPDOObject $object @@ -110,6 +109,7 @@ public function prepareRow(xPDOObject $object) /** @var modUser $user */ if ($user = $object->getOne('User')) { + /** @disregard P1013 Intelephense can not find this User instance method (getPhoto), but it does exist and is available here */ $row = array_merge( $row, $user->get(['username']), @@ -119,33 +119,6 @@ public function prepareRow(xPDOObject $object) /** @var modUserGroup $group */ $row['group'] = ($group = $user->getOne('PrimaryGroup')) ? $group->get('name') : ''; } - - $row['menu'] = []; - $row['menu'][] = [ - 'text' => $this->modx->lexicon('resource_overview'), - 'params' => [ - 'a' => 'resource/data', - 'id' => $resource->get('id'), - 'type' => 'view', - ], - ]; - if ($this->modx->hasPermission('edit_document')) { - $row['menu'][] = [ - 'text' => $this->modx->lexicon('resource_edit'), - 'params' => [ - 'a' => 'resource/update', - 'id' => $resource->get('id'), - 'type' => 'edit', - ], - ]; - } - - $row['menu'][] = '-'; - $row['menu'][] = [ - 'text' => $this->modx->lexicon('resource_view'), - 'handler' => 'this.preview', - ]; - $row['link'] = $this->modx->makeUrl($resource->get('id'), $resource->get('context_key')); return $row; diff --git a/core/src/Revolution/Processors/Source/GetList.php b/core/src/Revolution/Processors/Source/GetList.php index 33cd1fbf571..2413aaf111b 100644 --- a/core/src/Revolution/Processors/Source/GetList.php +++ b/core/src/Revolution/Processors/Source/GetList.php @@ -33,9 +33,15 @@ class GetList extends GetListProcessor public $languageTopics = ['source']; public $permission = 'source_view'; - /** @param boolean $isGridFilter Indicates the target of this list data is a filter field */ + /** @var bool $isGridFilter Indicates the target of this list data is a filter field */ protected $isGridFilter = false; + public $canCreate = false; + public $canEdit = false; + public $canRemove = false; + + protected $coreSources; + /** * {@inheritDoc} * @return boolean @@ -47,8 +53,15 @@ public function initialize() 'showNone' => false, 'query' => '', 'streamsOnly' => false, + 'exclude' => 'creator' ]); $this->isGridFilter = $this->getProperty('isGridFilter', false); + + $this->canCreate = $this->modx->hasPermission('source_save'); + $this->canEdit = $this->modx->hasPermission('source_edit'); + $this->canRemove = $this->modx->hasPermission('source_delete'); + $this->coreSources = $this->classKey::getCoreSources(); + return $initialized; } @@ -143,31 +156,32 @@ public function getSortClassKey() */ public function prepareRow(xPDOObject $object) { - $canEdit = $this->modx->hasPermission('source_edit'); - $canSave = $this->modx->hasPermission('source_save'); - $canRemove = $this->modx->hasPermission('source_delete'); + $permissions = [ + 'create' => $this->canCreate && $object->checkPolicy('save'), + 'duplicate' => $this->canCreate && $object->checkPolicy('copy'), + 'update' => $this->canEdit && $object->checkPolicy('save'), + 'delete' => $this->canRemove && $object->checkPolicy('remove') + ]; + + $sourceData = $object->toArray(); + $sourceName = $object->get('name'); + $isCoreSource = $object->isCoreSource($sourceName); + + $sourceData['reserved'] = ['name' => $this->coreSources]; + $sourceData['isProtected'] = $isCoreSource; + $sourceData['creator'] = $isCoreSource ? 'modx' : strtolower($this->modx->lexicon('user')) ; + if ($isCoreSource) { + unset($permissions['delete']); + } + $sourceData['permissions'] = $permissions; - $objectArray = $object->toArray(); - $objectArray['iconCls'] = $this->modx->getOption('mgr_source_icon', null, 'icon-folder-open-o'); + $sourceData['iconCls'] = $this->modx->getOption('mgr_source_icon', null, 'icon-folder-open-o'); $props = $object->getPropertyList(); if (isset($props['iconCls']) && !empty($props['iconCls'])) { - $objectArray['iconCls'] = $props['iconCls']; + $sourceData['iconCls'] = $props['iconCls']; } - $cls = []; - if ($canSave && $canEdit && $object->checkPolicy('save')) { - $cls[] = 'pupdate'; - } - if ($canRemove && $object->checkPolicy('remove')) { - $cls[] = 'premove'; - } - if ($canSave && $object->checkPolicy('copy')) { - $cls[] = 'pduplicate'; - } - - $objectArray['cls'] = implode(' ', $cls); - - return $objectArray; + return $sourceData; } } diff --git a/core/src/Revolution/Processors/Source/Update.php b/core/src/Revolution/Processors/Source/Update.php index 0b49c6944dc..e2066161995 100644 --- a/core/src/Revolution/Processors/Source/Update.php +++ b/core/src/Revolution/Processors/Source/Update.php @@ -1,4 +1,5 @@ object->get('name'); + $id = $this->object->get('id'); + + if (empty($name)) { + $this->addFieldError('name', $this->modx->lexicon('source_err_ns_name')); + } elseif ($this->alreadyExists($name, $id)) { + $this->addFieldError('name', $this->modx->lexicon('source_err_ae_name', [ + 'name' => $name, + ])); + } $this->setSourceProperties(); + return parent::beforeSave(); } + /** + * Check to see if a Media Source with the specified name already exists + * @param string $name + * @return boolean + */ + public function alreadyExists($name, $id) + { + return $this->modx->getCount(modMediaSource::class, [ + 'name' => $name, + 'id:!=' => $id + ]) > 0; + } + /** * Sets the properties on the source * @return void diff --git a/core/src/Revolution/Processors/System/ContentType/GetList.php b/core/src/Revolution/Processors/System/ContentType/GetList.php index 33dc6a825a0..1179a03c94f 100644 --- a/core/src/Revolution/Processors/System/ContentType/GetList.php +++ b/core/src/Revolution/Processors/System/ContentType/GetList.php @@ -1,4 +1,5 @@ modx->hasPermission('content_types'); + $this->canCreate = $canManage; + $this->canEdit = $canManage; + $this->canRemove = $canManage; + $this->coreContentTypes = $this->classKey::getCoreContentTypes(); + + return $initialized; + } + /** * Filter the query by the valueField of MODx.combo.ContentType to get the initially value displayed right * @param xPDOQuery $c @@ -42,4 +65,30 @@ public function prepareQueryAfterCount(xPDOQuery $c) } return $c; } + + /** + * @param xPDOObject|modContentType $object + * @return array + */ + public function prepareRow(xPDOObject $object) + { + $permissions = [ + 'create' => $this->canCreate, + 'duplicate' => $this->canCreate, + 'update' => $this->canEdit, + 'delete' => $this->canRemove + ]; + $contentTypeData = $object->toArray(); + $dashboardName = $object->get('name'); + $isCoreContentType = $object->isCoreContentType($dashboardName); + + $contentTypeData['isProtected'] = $isCoreContentType; + $contentTypeData['creator'] = $isCoreContentType ? 'modx' : strtolower($this->modx->lexicon('user')) ; + if ($isCoreContentType) { + unset($permissions['delete']); + } + $contentTypeData['permissions'] = $permissions; + + return $contentTypeData; + } } diff --git a/core/src/Revolution/Processors/System/Dashboard/GetList.php b/core/src/Revolution/Processors/System/Dashboard/GetList.php index 199b1b00913..7f24bb9164b 100644 --- a/core/src/Revolution/Processors/System/Dashboard/GetList.php +++ b/core/src/Revolution/Processors/System/Dashboard/GetList.php @@ -1,4 +1,5 @@ setDefaultProperties([ + 'query' => '', + 'exclude' => 'creator' + ]); + $canManage = $this->modx->hasPermission('dashboards'); + $this->canCreate = $canManage; + $this->canEdit = $canManage; + $this->canRemove = $canManage; + $this->coreDashboards = $this->classKey::getCoreDashboards(); + + return $initialized; + } + /** * @param xPDOQuery $c * @return xPDOQuery @@ -61,13 +87,29 @@ public function prepareQueryAfterCount(xPDOQuery $c) } /** - * @param xPDOObject $object + * @param xPDOObject|modDashboard $object * @return array */ public function prepareRow(xPDOObject $object) { - $objectArray = $object->toArray(); - $objectArray['cls'] = 'pupdate premove pduplicate'; - return $objectArray; + $permissions = [ + 'create' => $this->canCreate, + 'duplicate' => $this->canCreate, + 'update' => $this->canEdit, + 'delete' => $this->canRemove + ]; + $dashboardData = $object->toArray(); + $dashboardName = $object->get('name'); + $isCoreDashboard = $object->isCoreDashboard($dashboardName); + + $dashboardData['reserved'] = ['name' => $this->coreDashboards]; + $dashboardData['isProtected'] = $isCoreDashboard; + $dashboardData['creator'] = $isCoreDashboard ? 'modx' : strtolower($this->modx->lexicon('user')) ; + if ($isCoreDashboard) { + unset($permissions['delete']); + } + $dashboardData['permissions'] = $permissions; + + return $dashboardData; } } diff --git a/core/src/Revolution/Processors/System/Dashboard/Update.php b/core/src/Revolution/Processors/System/Dashboard/Update.php index baa62021335..7ce6ee217eb 100644 --- a/core/src/Revolution/Processors/System/Dashboard/Update.php +++ b/core/src/Revolution/Processors/System/Dashboard/Update.php @@ -1,4 +1,5 @@ object->get('name'); + $id = $this->object->get('id'); + + if (empty($name)) { + $this->addFieldError('name', $this->modx->lexicon('dashboard_err_ns_name')); + } elseif ($this->alreadyExists($name, $id)) { + $this->addFieldError('name', $this->modx->lexicon('dashboard_err_ae_name', [ + 'name' => $name, + ])); + } + + return parent::beforeSave(); + } + + /** + * Check to see if a Dashboard with the specified name already exists + * @param string $name + * @return boolean + */ + public function alreadyExists($name, $id) + { + return $this->modx->getCount(modDashboard::class, [ + 'name' => $name, + 'id:!=' => $id + ]) > 0; + } + /** * @return bool */ @@ -45,8 +76,11 @@ public function afterSave() public function setWidgets() { /** @var modDashboardWidgetPlacement[] $previousWidgets */ - $previousWidgets = $this->modx->getCollection(modDashboardWidgetPlacement::class, ['dashboard' => $this->object->id, 'user' => 0]); - $previousWidgets = array_map(function($item){ + $previousWidgets = $this->modx->getCollection(modDashboardWidgetPlacement::class, [ + 'dashboard' => $this->object->id, + 'user' => 0 + ]); + $previousWidgets = array_map(function ($item) { return $item->widget; }, $previousWidgets); @@ -63,7 +97,6 @@ public function setWidgets() ]); foreach ($widgets as $data) { $newWidgets[] = $data['widget']; - $key = [ 'dashboard' => $this->object->get('id'), 'user' => 0, @@ -79,7 +112,6 @@ public function setWidgets() $widget->set('rank', $data['rank']); $widget->save(); } - $addedWidgets = array_values(array_diff($newWidgets, $previousWidgets)); $removedWidgets = array_values(array_diff($previousWidgets, $newWidgets)); @@ -88,9 +120,7 @@ public function setWidgets() $userDashboardsQuery->distinct(true); $userDashboardsQuery->select('user'); $userDashboardsQuery->prepare(); - $userDashboardsQuery->stmt->execute(); - $userDashboards = $userDashboardsQuery->stmt->fetchAll(\PDO::FETCH_COLUMN, 0); $userDashboards = array_map('intval', $userDashboards); @@ -108,11 +138,9 @@ public function setWidgets() } } } - if (!empty($removedWidgets)) { $this->modx->removeCollection(modDashboardWidgetPlacement::class, ['dashboard' => $this->object->id, 'widget:IN' => $removedWidgets]); } - $this->object->sortWidgets(); } } diff --git a/core/src/Revolution/Processors/System/Dashboard/Widget/GetList.php b/core/src/Revolution/Processors/System/Dashboard/Widget/GetList.php index 63f300c9dbb..22b1923f772 100644 --- a/core/src/Revolution/Processors/System/Dashboard/Widget/GetList.php +++ b/core/src/Revolution/Processors/System/Dashboard/Widget/GetList.php @@ -1,4 +1,5 @@ setDefaultProperties([ + 'query' => '', + 'exclude' => 'creator' + ]); + $canManage = $this->modx->hasPermission('dashboards'); + $this->canCreate = $canManage; + $this->canEdit = $canManage; + $this->canRemove = $canManage; + + return $initialized; + } + /** * {@inheritDoc} * @param xPDOQuery $c @@ -70,8 +93,24 @@ public function prepareQueryAfterCount(xPDOQuery $c) */ public function prepareRow(xPDOObject $object) { - $objectArray = $object->toArray(); - $objectArray['cls'] = 'pupdate premove'; - return $objectArray; + $permissions = [ + 'create' => $this->canCreate, + 'duplicate' => $this->canCreate, + 'update' => $this->canEdit, + 'delete' => $this->canRemove + ]; + $widgetData = $object->toArray(); + $isCoreWidget = strpos($widgetData['content'], '[[++manager_path]]') === 0; + $widgetData['isProtected'] = $isCoreWidget + ? true + : false + ; + + if ($isCoreWidget) { + unset($permissions['delete']); + } + $widgetData['permissions'] = $permissions; + + return $widgetData; } } diff --git a/core/src/Revolution/Processors/Workspace/Lexicon/GetList.php b/core/src/Revolution/Processors/Workspace/Lexicon/GetList.php index 39ac2efb410..ceca4fadd26 100644 --- a/core/src/Revolution/Processors/Workspace/Lexicon/GetList.php +++ b/core/src/Revolution/Processors/Workspace/Lexicon/GetList.php @@ -138,7 +138,7 @@ function parseArray($needle, array $haystack = []) ksort($entries); $entries = array_slice($entries, $this->getProperty('start'), $this->getProperty('limit'), true); - /* loop through */ + // Note that for Lexicons, the 'edit' permission correlates with the ability to revert a customized entry $list = []; foreach ($entries as $name => $value) { $editedOn = null; @@ -151,6 +151,9 @@ function parseArray($needle, array $haystack = []) 'createdon' => null, 'editedon' => null, 'overridden' => 0, + 'permissions' => [ + 'edit' => false + ] ]; /* if override in db, load */ if (array_key_exists($name, $dbEntries)) { @@ -159,6 +162,9 @@ function parseArray($needle, array $haystack = []) } $editedOn = $entryArray['editedon'] ?: $entryArray['createdon'] ; $entryArray['overridden'] = 1; + $entryArray['permissions'] = [ + 'edit' => true + ]; } $entryArray['editedon'] = $this->formatter->formatDateTime($editedOn); $list[] = $entryArray; diff --git a/core/src/Revolution/Processors/Workspace/PackageNamespace/GetList.php b/core/src/Revolution/Processors/Workspace/PackageNamespace/GetList.php index 9768b824362..aadbb764982 100644 --- a/core/src/Revolution/Processors/Workspace/PackageNamespace/GetList.php +++ b/core/src/Revolution/Processors/Workspace/PackageNamespace/GetList.php @@ -37,9 +37,15 @@ class GetList extends GetListProcessor public $languageTopics = ['namespace', 'workspace']; public $permission = 'namespaces'; + public $canCreate = false; + public $canEdit = false; + public $canRemove = false; + /** @param boolean $isGridFilter Indicates the target of this list data is a filter field */ protected $isGridFilter = false; + protected $coreNamespaces; + /** * {@inheritDoc} * @return boolean @@ -47,10 +53,26 @@ class GetList extends GetListProcessor public function initialize() { $initialized = parent::initialize(); + $this->isGridFilter = $this->getProperty('isGridFilter', false); $this->setDefaultProperties([ - 'query' => '' + 'query' => '', + 'exclude' => 'creator' ]); - $this->isGridFilter = $this->getProperty('isGridFilter', false); + + /* + Normally these would access permission like this: + $this->canCreate = $this->modx->hasPermission('[object type]_save'); + Namespaces do not currently have changeable policy permissions, so + setting each to true; consider adding new permissions settings for + - namespace_save + - namespace_edit + - namespace_delete + */ + $this->canCreate = $this->modx->hasPermission('namespaces'); + $this->canEdit = $this->modx->hasPermission('namespaces'); + $this->canRemove = $this->modx->hasPermission('namespaces'); + $this->coreNamespaces = $this->classKey::getCoreNamespaces(); + return $initialized; } @@ -170,16 +192,43 @@ public function prepareQueryAfterCount(xPDOQuery $c) /** * Prepare the Namespace for listing - * @param xPDOObject $object + * @param xPDOObject|modNamespace $object * @return array */ public function prepareRow(xPDOObject $object) { - $objectArray = $object->toArray(); - $objectArray['perm'] = []; - $objectArray['perm'][] = 'pedit'; - $objectArray['perm'][] = 'premove'; + /* + If policy permissions get added for namespaces, change to: + $permissions = [ + 'create' => $this->canCreate && $object->checkPolicy('save'), + 'duplicate' => $this->canCreate && $object->checkPolicy('copy'), + 'update' => $this->canEdit && $object->checkPolicy('save'), + 'delete' => $this->canRemove && $object->checkPolicy('remove') + ]; + */ + $permissions = [ + 'create' => $this->canCreate, + 'duplicate' => $this->canCreate, + 'update' => $this->canEdit, + 'delete' => $this->canRemove + ]; + + $namespaceData = $object->toArray(); + $namespaceName = $object->get('name'); + $isCoreNamespace = $object->isCoreNamespace($namespaceName); + + $namespaceData['reserved'] = ['name' => $this->coreNamespaces]; + $namespaceData['isProtected'] = $isCoreNamespace + ? true + : false + ; + + // Core paths should only be editable via the installation process + if ($isCoreNamespace) { + $permissions = []; + } + $namespaceData['permissions'] = $permissions; - return $objectArray; + return $namespaceData; } } diff --git a/core/src/Revolution/Processors/Workspace/Packages/Version/GetList.php b/core/src/Revolution/Processors/Workspace/Packages/Version/GetList.php index b32b184dff6..fa97a6119f2 100644 --- a/core/src/Revolution/Processors/Workspace/Packages/Version/GetList.php +++ b/core/src/Revolution/Processors/Workspace/Packages/Version/GetList.php @@ -31,6 +31,7 @@ class GetList extends GetListProcessor public $languageTopics = ['workspace']; private modManagerDateFormatter $formatter; + public $canRemove = false; /** * @return bool @@ -45,6 +46,8 @@ public function initialize() 'workspace' => 1, 'signature' => false, ]); + $this->canRemove = $this->modx->hasPermission('packages'); + return parent::initialize(); } @@ -77,9 +80,10 @@ public function getData() */ public function prepareRow(xPDOObject $object) { - if ($object->get('installed') === '0000-00-00 00:00:00') { - $object->set('installed', null); - } + $permissions = [ + 'delete' => $this->canRemove + ]; + $installed = !in_array($object->get('installed'), [null, '0000-00-00 00:00:00']); $packageArray = $object->toArray(); $packageArray = $this->parseVersion($object, $packageArray); @@ -88,9 +92,14 @@ public function prepareRow(xPDOObject $object) $packageArray = $this->prepareMenu($object, $packageArray); /* setup description, using either metadata or readme */ - if ($object->get('installed') === null) { + if (!$installed) { $this->currentIndex--; } + if ($this->currentIndex === 0) { + $permissions['delete'] = false; + } + $packageArray['permissions'] = $permissions; + return $packageArray; } @@ -144,8 +153,8 @@ public function getMetaData(modTransportPackage $package, array $packageArray) foreach ($metadata as $row) { if (!empty($row['name']) && $row['name'] === 'description') { $packageArray['readme'] = str_replace( - [PHP_EOL, '

'], - ['', '
'], + [PHP_EOL, '

'], + ['', '
'], nl2br($row['text']) ); break; @@ -157,8 +166,8 @@ public function getMetaData(modTransportPackage $package, array $packageArray) if ($transport) { $packageArray['readme'] = $transport->getAttribute('readme'); $packageArray['readme'] = str_replace( - [PHP_EOL, '

'], - ['', '
'], + [PHP_EOL, '

'], + ['', '
'], nl2br($packageArray['readme']) ); } @@ -175,11 +184,11 @@ public function getMetaData(modTransportPackage $package, array $packageArray) */ public function prepareMenu(modTransportPackage $package, array $packageArray) { - $notInstalled = $package->get('installed') === null || $package->get('installed') === '0000-00-00 00:00:00'; - $packageArray['iconaction'] = $notInstalled ? 'icon-install' : 'icon-uninstall'; - $packageArray['textaction'] = $notInstalled ? $this->modx->lexicon('install') : $this->modx->lexicon('uninstall'); + $installed = !in_array($package->get('installed'), [null, '0000-00-00 00:00:00']); + $packageArray['iconaction'] = !$installed ? 'icon-install' : 'icon-uninstall'; + $packageArray['textaction'] = !$installed ? $this->modx->lexicon('install') : $this->modx->lexicon('uninstall'); - if ($this->currentIndex > 0 || !$package->get('installed')) { + if ($this->currentIndex > 0 || !$installed) { $packageArray['menu'] = []; $packageArray['menu'][] = [ 'text' => $this->modx->lexicon('package_version_remove'), diff --git a/core/src/Revolution/Sources/modMediaSource.php b/core/src/Revolution/Sources/modMediaSource.php index 4b61fa2fe07..05b1cc32f9b 100644 --- a/core/src/Revolution/Sources/modMediaSource.php +++ b/core/src/Revolution/Sources/modMediaSource.php @@ -70,6 +70,7 @@ abstract class modMediaSource extends modAccessibleSimpleObject implements modMe /** @var Filesystem */ protected $filesystem; + public const SOURCE_FILESYSTEM = 'Filesystem'; /** * Get the default MODX filesystem source @@ -441,7 +442,6 @@ public function getContainerList($path) foreach ($directories as $dir) { $ls[] = $dir; } - array_multisort($fileNames, SORT_ASC, SORT_STRING, $files); foreach ($files as $file) { $ls[] = $file; @@ -1255,7 +1255,6 @@ public function setVisibility($path, $visibility) return false; } - /** * @param string $object * @@ -1749,10 +1748,26 @@ public function clearCache(array $options = []) $c->select($this->xpdo->escape('key')); $options[xPDO::OPT_CACHE_KEY] = $this->getOption('cache_media_sources_key', $options, 'media_sources'); - $options[xPDO::OPT_CACHE_HANDLER] = $this->getOption('cache_media_sources_handler', $options, $this->getOption(xPDO::OPT_CACHE_HANDLER, $options)); - $options[xPDO::OPT_CACHE_FORMAT] = (int)$this->getOption('cache_media_sources_format', $options, $this->getOption(xPDO::OPT_CACHE_FORMAT, $options, xPDOCacheManager::CACHE_PHP)); - $options[xPDO::OPT_CACHE_ATTEMPTS] = (int)$this->getOption('cache_media_sources_attempts', $options, $this->getOption(xPDO::OPT_CACHE_ATTEMPTS, $options, 10)); - $options[xPDO::OPT_CACHE_ATTEMPT_DELAY] = (int)$this->getOption('cache_media_sources_attempt_delay', $options, $this->getOption(xPDO::OPT_CACHE_ATTEMPT_DELAY, $options, 1000)); + $options[xPDO::OPT_CACHE_HANDLER] = $this->getOption( + 'cache_media_sources_handler', + $options, + $this->getOption(xPDO::OPT_CACHE_HANDLER, $options) + ); + $options[xPDO::OPT_CACHE_FORMAT] = (int)$this->getOption( + 'cache_media_sources_format', + $options, + $this->getOption(xPDO::OPT_CACHE_FORMAT, $options, xPDOCacheManager::CACHE_PHP) + ); + $options[xPDO::OPT_CACHE_ATTEMPTS] = (int)$this->getOption( + 'cache_media_sources_attempts', + $options, + $this->getOption(xPDO::OPT_CACHE_ATTEMPTS, $options, 10) + ); + $options[xPDO::OPT_CACHE_ATTEMPT_DELAY] = (int)$this->getOption( + 'cache_media_sources_attempt_delay', + $options, + $this->getOption(xPDO::OPT_CACHE_ATTEMPT_DELAY, $options, 1000) + ); if ($c->prepare() && $c->stmt->execute()) { while ($row = $c->stmt->fetch(PDO::FETCH_ASSOC)) { @@ -2062,7 +2077,7 @@ protected function getAllowedExtensionsArray($properties = []) /** * @param array $properties * - * @return array|mixed|string + * @return array */ protected function getSkipExtensionsArray($properties = []) { @@ -2451,4 +2466,26 @@ protected function isFileImage($file, $image_extensions = []) return false; } + + /** + * Returns a list of core Media Sources + * + * @return array + */ + public static function getCoreSources() + { + return [ + self::SOURCE_FILESYSTEM + ]; + } + + /** + * @param string $name The name of the Media Source + * + * @return bool + */ + public function isCoreSource($name) + { + return in_array($name, static::getCoreSources(), true); + } } diff --git a/core/src/Revolution/modAccessPolicyTemplate.php b/core/src/Revolution/modAccessPolicyTemplate.php index 426706093fb..d4fc1359663 100644 --- a/core/src/Revolution/modAccessPolicyTemplate.php +++ b/core/src/Revolution/modAccessPolicyTemplate.php @@ -3,30 +3,33 @@ namespace MODX\Revolution; use xPDO\Om\xPDOSimpleObject; +use xPDO\xPDO; /** * A collection of modAccessPermission records that are used as a Template for custom modAccessPolicy objects. Is * grouped into Access Policy Template Groups to provide targeted policy access implementations. * - * @property int $template_group The group that this template is a part of, used for targeting usage of applied Policies - * @property string $name The name of the Policy Template - * @property string $description A description of the Policy Template - * @property string $lexicon Optional. A lexicon that may be loaded to provide translations for all included Permissions + * @property int $template_group The group that this template is a part of, used for targeting usage of applied Policies + * @property string $name The name of the Policy Template + * @property string $description A description of the Policy Template + * @property string $lexicon Optional. A lexicon that may be loaded to provide translations for all included Permissions * * @property modAccessPermission[] $Permissions - * @property modAccessPolicy[] $Policies + * @property modAccessPolicy[] $Policies + * + * @property modX|xPDO $xpdo * * @package MODX\Revolution */ class modAccessPolicyTemplate extends xPDOSimpleObject { - const TEMPLATE_ADMINISTRATOR = 'AdministratorTemplate'; - const TEMPLATE_CONTEXT = 'ContextTemplate'; - const TEMPLATE_ELEMENT = 'ElementTemplate'; - const TEMPLATE_MEDIA_SOURCE = 'MediaSourceTemplate'; - const TEMPLATE_NAMESPACE = 'NamespaceTemplate'; - const TEMPLATE_OBJECT = 'ObjectTemplate'; - const TEMPLATE_RESOURCE = 'ResourceTemplate'; + public const TEMPLATE_ADMINISTRATOR = 'AdministratorTemplate'; + public const TEMPLATE_CONTEXT = 'ContextTemplate'; + public const TEMPLATE_ELEMENT = 'ElementTemplate'; + public const TEMPLATE_MEDIA_SOURCE = 'MediaSourceTemplate'; + public const TEMPLATE_NAMESPACE = 'NamespaceTemplate'; + public const TEMPLATE_OBJECT = 'ObjectTemplate'; + public const TEMPLATE_RESOURCE = 'ResourceTemplate'; /** * Returns list of core Policy Templates diff --git a/core/src/Revolution/modContentType.php b/core/src/Revolution/modContentType.php index 4109e80c416..43ddf01e988 100644 --- a/core/src/Revolution/modContentType.php +++ b/core/src/Revolution/modContentType.php @@ -18,6 +18,17 @@ */ class modContentType extends xPDOSimpleObject { + public const CORE_TYPES = [ + 'HTML', + 'XML', + 'Text', + 'CSS', + 'JavaScript', + 'RSS', + 'JSON', + 'PDF' + ]; + /** * Returns the first extension of this Content Type. * @@ -33,4 +44,24 @@ public function getExtension() return $extension; } + + /** + * Returns a list of core Dashboards + * + * @return array + */ + public static function getCoreContentTypes(): array + { + return self::CORE_TYPES; + } + + /** + * @param string $name The name of the Dashboard + * + * @return bool + */ + public function isCoreContentType($name): bool + { + return in_array($name, static::getCoreContentTypes(), true); + } } diff --git a/core/src/Revolution/modContext.php b/core/src/Revolution/modContext.php index cf16cce2a6c..27eceef2cb3 100644 --- a/core/src/Revolution/modContext.php +++ b/core/src/Revolution/modContext.php @@ -29,6 +29,9 @@ class modContext extends modAccessibleObject * @var array RESERVED_KEYS */ public const RESERVED_KEYS = ['mgr', 'web', 'root']; + public const CONTEXT_MANAGER = 'mgr'; + public const CONTEXT_DEFAULT = 'web'; + public const CONTEXT_DEFAULT_NAME = 'Website'; /** * An array of configuration options for this context @@ -125,14 +128,26 @@ public function prepare($regenerate = false, array $options = []) if ($this->config === null || $regenerate) { if ($this->xpdo->getCacheManager()) { $context = []; - if ($regenerate || !($context = $this->xpdo->cacheManager->get($this->getCacheKey(), [ - xPDO::OPT_CACHE_KEY => $this->xpdo->getOption('cache_context_settings_key', null, - 'context_settings'), - xPDO::OPT_CACHE_HANDLER => $this->xpdo->getOption('cache_context_settings_handler', null, - $this->xpdo->getOption(xPDO::OPT_CACHE_HANDLER, null, 'xPDO\Cache\xPDOFileCache')), - xPDO::OPT_CACHE_FORMAT => (int)$this->xpdo->getOption('cache_context_settings_format', null, - $this->xpdo->getOption(xPDO::OPT_CACHE_FORMAT, null, xPDOCacheManager::CACHE_PHP)), - ]))) { + if ( + $regenerate || !($context = $this->xpdo->cacheManager->get($this->getCacheKey(), [ + xPDO::OPT_CACHE_KEY => $this->xpdo->getOption( + 'cache_context_settings_key', + null, + 'context_settings' + ), + xPDO::OPT_CACHE_HANDLER => $this->xpdo->getOption( + 'cache_context_settings_handler', + null, + $this->xpdo->getOption(xPDO::OPT_CACHE_HANDLER, null, 'xPDO\Cache\xPDOFileCache') + ), + xPDO::OPT_CACHE_FORMAT => (int)$this->xpdo->getOption( + 'cache_context_settings_format', + null, + $this->xpdo->getOption(xPDO::OPT_CACHE_FORMAT, null, xPDOCacheManager::CACHE_PHP) + ) + ])) + ) { + /** @disregard P1013 Intelephense can not find this modCacheManager instance method, but it does exist and is available here */ $context = $this->xpdo->cacheManager->generateContext($this->get('key'), $options); } if (!empty($context)) { @@ -480,4 +495,27 @@ public function getResourceURI($id) return $uri; } + + /** + * Returns a list of core Contexts + * + * @return array + */ + public static function getCoreContexts() + { + return [ + self::CONTEXT_MANAGER, + self::CONTEXT_DEFAULT + ]; + } + + /** + * @param string $key The key of the Context + * + * @return bool + */ + public function isCoreContext($key) + { + return in_array($key, static::getCoreContexts(), true); + } } diff --git a/core/src/Revolution/modDashboard.php b/core/src/Revolution/modDashboard.php index 4949054f1fa..d0fbd7243e1 100644 --- a/core/src/Revolution/modDashboard.php +++ b/core/src/Revolution/modDashboard.php @@ -19,6 +19,8 @@ */ class modDashboard extends xPDOSimpleObject { + public const DASHBOARD_DEFAULT = 'Default'; + /** * Get the default MODX dashboard * @@ -73,7 +75,6 @@ public function remove(array $ancestors = []) return $removed; } - /** * Render the Dashboard * @@ -129,7 +130,6 @@ public function render(modManagerController $controller, $user = null) return implode("\n", $output); } - /** * @param int $user * @param bool $force @@ -168,7 +168,6 @@ public function sortWidgets($user = 0, $force = false) } } - /** * @param modUser $user */ @@ -188,4 +187,26 @@ protected function addUserWidgets(modUser $user) $new->save(); } } + + /** + * Returns a list of core Dashboards + * + * @return array + */ + public static function getCoreDashboards(): array + { + return [ + self::DASHBOARD_DEFAULT + ]; + } + + /** + * @param string $name The name of the Dashboard + * + * @return bool + */ + public function isCoreDashboard($name): bool + { + return in_array($name, static::getCoreDashboards(), true); + } } diff --git a/core/src/Revolution/modNamespace.php b/core/src/Revolution/modNamespace.php index e1c9cbe5d44..408bdc4e8e4 100644 --- a/core/src/Revolution/modNamespace.php +++ b/core/src/Revolution/modNamespace.php @@ -2,6 +2,7 @@ namespace MODX\Revolution; +use MODX\Revolution\Transport\modTransportPackage; use PDO; use xPDO\Cache\xPDOCacheManager; use xPDO\Om\xPDOCriteria; @@ -27,6 +28,8 @@ */ class modNamespace extends modAccessibleObject { + public const NAMESPACE_CORE = 'core'; + public function save($cacheFlag = null) { $saved = parent::save(); @@ -54,7 +57,11 @@ public static function loadCache(modX $modx) } $cacheKey = 'namespaces'; $cache = $modx->cacheManager->get($cacheKey, [ - xPDO::OPT_CACHE_KEY => $modx->getOption('cache_namespaces_key', null, 'namespaces'), + xPDO::OPT_CACHE_KEY => $modx->getOption( + 'cache_namespaces_key', + null, + 'namespaces' + ), xPDO::OPT_CACHE_HANDLER => $modx->getOption( 'cache_namespaces_handler', null, @@ -64,7 +71,7 @@ public static function loadCache(modX $modx) 'cache_namespaces_format', null, $modx->getOption(xPDO::OPT_CACHE_FORMAT, null, xPDOCacheManager::CACHE_PHP) - ), + ) ]); if (empty($cache)) { $cache = $modx->cacheManager->generateNamespacesCache($cacheKey); @@ -77,7 +84,11 @@ public static function clearCache(modX $modx) { $cacheKey = 'namespaces'; $cleared = $modx->cacheManager->delete($cacheKey, [ - xPDO::OPT_CACHE_KEY => $modx->getOption('cache_namespaces_key', null, 'namespaces'), + xPDO::OPT_CACHE_KEY => $modx->getOption( + 'cache_namespaces_key', + null, + 'namespaces' + ), xPDO::OPT_CACHE_HANDLER => $modx->getOption( 'cache_namespaces_handler', null, @@ -87,7 +98,7 @@ public static function clearCache(modX $modx) 'cache_namespaces_format', null, $modx->getOption(xPDO::OPT_CACHE_FORMAT, null, xPDOCacheManager::CACHE_PHP) - ), + ) ]); return $cleared; @@ -172,4 +183,26 @@ public function findPolicy($context = '') return $policy; } + + /** + * Returns a list of core Namespaces + * + * @return array + */ + public static function getCoreNamespaces() + { + return [ + self::NAMESPACE_CORE + ]; + } + + /** + * @param string $key The key of the Context + * + * @return bool + */ + public function isCoreNamespace($key) + { + return in_array($key, static::getCoreNamespaces(), true); + } } diff --git a/core/src/Revolution/modUserGroupRole.php b/core/src/Revolution/modUserGroupRole.php index b08c5a10317..81d139b5a82 100644 --- a/core/src/Revolution/modUserGroupRole.php +++ b/core/src/Revolution/modUserGroupRole.php @@ -11,13 +11,39 @@ * For example, an Administrator with authority of 1 will automatically inherit any Permissions assigned to a Member * role with authority 9999, since 1 is less than 9999. However, the reverse will not be true. * - * @property string $name The name of the Role + * @property string $name The name of the Role * @property string $description A user-provided description of this Role - * @property int $authority The authority of the role. Lower authority numbers have more power than higher ones, and - * lower numbers will inherit the Permissions of higher numbers. + * @property int $authority The authority of the role. Lower authority numbers + * have more power than higher ones, and lower numbers will inherit + * the Permissions of higher numbers. * * @package MODX\Revolution */ class modUserGroupRole extends xPDOSimpleObject { + public const ROLE_SUPERUSER = 'Super User'; + public const ROLE_MEMBER = 'Member'; + + /** + * Returns a list of core Roles + * + * @return array + */ + public static function getCoreRoles() + { + return [ + self::ROLE_SUPERUSER, + self::ROLE_MEMBER + ]; + } + + /** + * @param string $name The name of the Role + * + * @return bool + */ + public function isCoreRole($name) + { + return in_array($name, static::getCoreRoles(), true); + } } diff --git a/manager/assets/modext/modx.jsgrps-min.js b/manager/assets/modext/modx.jsgrps-min.js index a14ba2984e0..20a2a354052 100644 --- a/manager/assets/modext/modx.jsgrps-min.js +++ b/manager/assets/modext/modx.jsgrps-min.js @@ -16,21 +16,21 @@ * */ -Ext.onReady((function(){if("en"==MODx.config.cultureKey)return!1;Date.dayNames=[_("sunday"),_("monday"),_("tuesday"),_("wednesday"),_("thursday"),_("friday"),_("saturday")],Date.monthNames=[_("january"),_("february"),_("march"),_("april"),_("may"),_("june"),_("july"),_("august"),_("september"),_("october"),_("november"),_("december")],Ext.apply(Ext.grid.GridView.prototype,{sortAscText:_("ext_sortasc"),sortDescText:_("ext_sortdesc"),lockText:_("ext_column_lock"),unlockText:_("ext_column_unlock"),columnsText:_("ext_columns"),emptyText:_("ext_emptymsg")}),Ext.apply(Ext.DatePicker.prototype,{todayText:_("today"),todayTip:_("ext_today_tip"),minText:_("ext_mindate"),maxText:_("ext_maxdate"),monthNames:Date.monthNames,dayNames:Date.dayNames,nextText:_("ext_nextmonth"),prevText:_("ext_prevmonth"),monthYearText:_("ext_choosemonth")}),Ext.MessageBox.buttonText={yes:_("yes"),no:_("no"),ok:_("ok"),cancel:_("cancel")},Ext.apply(Ext.PagingToolbar.prototype,{afterPageText:_("ext_afterpage"),beforePageText:_("ext_beforepage"),displayMsg:_("ext_displaying"),emptyMsg:_("ext_emptymsg"),firstText:_("ext_first"),prevText:_("ext_prev"),nextText:_("ext_next"),lastText:_("ext_last"),refreshText:_("ext_refresh")}),Ext.apply(Ext.Updater.prototype,{text:_("loading")}),Ext.apply(Ext.LoadMask.prototype,{msg:_("loading")}),Ext.apply(Ext.layout.BorderLayout.SplitRegion.prototype,{splitTip:_("ext_splittip")}),Ext.apply(Ext.form.BasicForm.prototype,{waitTitle:_("please_wait")}),Ext.apply(Ext.form.ComboBox.prototype,{loadingText:_("loading")}),Ext.apply(Ext.form.Field.prototype,{invalidText:_("ext_invalidfield")}),Ext.apply(Ext.form.TextField.prototype,{minLengthText:_("ext_minlenfield"),maxLengthText:_("ext_maxlenfield"),invalidText:_("ext_invalidfield"),blankText:_("field_required")}),Ext.apply(Ext.form.NumberField.prototype,{minText:_("ext_minvalfield"),maxText:_("ext_maxvalfield"),nanText:_("ext_nanfield")}),Ext.apply(Ext.form.DateField.prototype,{disabledDaysText:_("disabled"),disabledDatesText:_("disabled"),minText:_("ext_datemin"),maxText:_("ext_datemax"),invalidText:_("ext_dateinv")}),Ext.apply(Ext.form.VTypes,{emailText:_("ext_inv_email"),urlText:_("ext_inv_url"),alphaText:_("ext_inv_alpha"),alphanumText:_("ext_inv_alphanum")}),Ext.apply(Ext.grid.GroupingView.prototype,{emptyGroupText:_("ext_emptygroup"),groupByText:_("ext_groupby"),showGroupsText:_("ext_showgroups")}),Ext.apply(Ext.grid.PropertyColumnModel.prototype,{nameText:_("name"),valueText:_("value")}),Ext.apply(Ext.form.CheckboxGroup.prototype,{blankText:_("ext_checkboxinv")}),Ext.apply(Ext.form.RadioGroup.prototype,{blankText:_("ext_checkboxinv")}),Ext.apply(Ext.form.TimeField.prototype,{minText:_("ext_timemin"),maxText:_("ext_timemax"),invalidText:_("ext_timeinv")})})),Ext.namespace("MODx.util.Progress"),Ext.namespace("MODx.util.Format"),MODx.util.JSONReader=function(config){config=config||{},Ext.applyIf(config,{successProperty:"success",totalProperty:"total",root:"data"}),MODx.util.JSONReader.superclass.constructor.call(this,config,["id","msg"])},Ext.extend(MODx.util.JSONReader,Ext.data.JsonReader),Ext.reg("modx-json-reader",MODx.util.JSONReader),MODx.util.Progress={id:0,time:function(v,id,msg){msg=msg||_("saving"),MODx.util.Progress.id===id&&v<11&&Ext.MessageBox.updateProgress(v/10,msg)},reset:function(){MODx.util.Progress.id=MODx.util.Progress.id+1}},MODx.util.UrlParams={get(){return this.parse(window.location.search)},set(data){const params=decodeURIComponent(new URLSearchParams(data).toString());params.length?window.history.pushState(params,"",document.location.pathname+"?"+params):window.history.pushState("","",document.location.pathname)},add(key,val){const params=this.get();params[key]=val,this.set(params)},remove(key){const params=this.get();delete params[key],this.set(params)},clear(){this.set({})},parse(str){const params=new URLSearchParams(str);return Object.fromEntries(params.entries())}},MODx.LockMask=function(config){config=config||{},Ext.applyIf(config,{msg:_("locked"),msgCls:"modx-lockmask"}),MODx.LockMask.superclass.constructor.call(this,config.el,config)},Ext.extend(MODx.LockMask,Ext.LoadMask,{locked:!1,toggle:function(){this.locked?(this.hide(),this.locked=!1):(this.show(),this.locked=!0)},lock:function(){this.locked=!0,this.show()},unlock:function(){this.locked=!1,this.hide()}}),Ext.reg("modx-lockmask",MODx.LockMask),Ext.override(Ext.form.NumberField,{strictDecimalPrecision:!1,fixPrecision:function(value){var nan=isNaN(value);return this.allowDecimals&&-1!=this.decimalPrecision&&!nan&&value?this.allowDecimals&&this.strictDecimalPrecision?parseFloat(value).toFixed(this.decimalPrecision):parseFloat(parseFloat(value).toFixed(this.decimalPrecision)):nan?"":value}}),Ext.override(Ext.form.BasicForm,{clearDirty:function(nodeToRecurse){(nodeToRecurse=nodeToRecurse||this)?.items?.each?.((function(f){f.getValue&&(f.items?this.clearDirty(f):f.originalValue!=f.getValue()&&(f.originalValue=f.getValue()))}),this)}}),MODx.StaticTextField=Ext.extend(Ext.form.TextField,{fieldClass:"x-static-text-field",onRender:function(){this.readOnly=!0,this.disabled=!this.initialConfig.submitValue,MODx.StaticTextField.superclass.onRender.apply(this,arguments)}}),Ext.reg("statictextfield",MODx.StaticTextField),MODx.StaticBoolean=Ext.extend(Ext.form.TextField,{fieldClass:"x-static-text-field",onRender:function(tf){this.readOnly=!0,this.disabled=!this.initialConfig.submitValue,MODx.StaticBoolean.superclass.onRender.apply(this,arguments),this.on("change",this.onChange,this)},setValue:function(v){1===v?(this.addClass("green"),v=_("yes")):(this.addClass("red"),v=_("no")),MODx.StaticBoolean.superclass.setValue.apply(this,arguments)}}),Ext.reg("staticboolean",MODx.StaticBoolean),MODx.util.safeHtml=function(input,allowedTags,allowedAttributes){var strip=function(input,allowedTags,allowedAttributes){return input.replace(tags,(function($0,$1){return allowedTags.indexOf("<"+$1.toLowerCase()+">")>-1?$0:""})).replace(attributes,(function($0,$1){return allowedAttributes.indexOf($1.toLowerCase()+",")>-1?$0:""}))};allowedTags=(((allowedTags||"
")+"").toLowerCase().match(/<[a-z][a-z0-9]*>/g)||[]).join(""),allowedAttributes=(((allowedAttributes||"href,class")+"").toLowerCase().match(/[a-z\-,]*/g)||[]).join("").concat(",");var length,tags=/<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,attributes=/([a-z][a-z0-9]*)\s*=\s*".*?"/gi;input=input.replace(/|<\?(?:php)?[\s\S]*?\?>/gi,"").replace(/href(\s*?=\s*?(["'])javascript:.*?\2|\s*?=\s*?javascript:.*?(?![^> ]))/gi,'href="javascript:void(0)"');do{length=input.length,input=strip(input,allowedTags,allowedAttributes)}while(length!==input.length);return input.replace(/on([a-z][a-z0-9]*\s*=)/gi,"on​$1")},Ext.override(Ext.form.Checkbox,{setBoxLabel:function(boxLabel){this.boxLabel=boxLabel,this.rendered&&this.wrap.child(".x-form-cb-label").update(boxLabel)}});var FieldSetonRender=Ext.form.FieldSet.prototype.onRender;Ext.override(Ext.form.FieldSet,{onRender:function(ct,position){if(FieldSetonRender.call(this,ct,position),this.checkboxToggle){var trigger=this.el.dom.getElementsByClassName(this.headerTextCls)[0],elem=this;trigger&&trigger.addEventListener("click",(function(e){elem.checkbox.dom.click(e)}),!1)}}}),Array.prototype.in_array=function(p_val){for(var i=0,l=this.length;i0){this.items.addAll(fields);for(var f=0;f',elbowMarkup=n.attributes.pseudoroot?'':'',buf=['
  • ",'',"
  • "].join("");!0!==bulkRender&&n.nextSibling&&(nel=n.nextSibling.ui.getEl())?this.wrap=Ext.DomHelper.insertHtml("beforeBegin",nel,buf):this.wrap=Ext.DomHelper.insertHtml("beforeEnd",targetNode,buf),this.elNode=this.wrap.childNodes[0],this.ctNode=this.wrap.childNodes[1];var cs=this.elNode.childNodes;this.indentNode=cs[0],this.ecNode=cs[1],this.iconNode=cs[2];var index=3;cb&&(this.checkbox=cs[3],this.checkbox.defaultChecked=this.checkbox.checked,index++),this.anchor=cs[index],this.textNode=cs[index].firstChild},renderItemText:function(item){return Ext.util.Format.htmlEncode(item.text)},getChildIndent:function(){if(!this.childIndent){for(var buf=[],p=this.node;p;)(!p.isRoot||p.isRoot&&p.ownerTree.rootVisible)&&!p.attributes.pseudoroot&&(p.isLast()?buf.unshift(''):buf.unshift('')),p=p.parentNode;this.childIndent=buf.join("")}return this.childIndent}}),Ext.override(Ext.form.Action.Submit,{handleResponse:function(response){var m=Ext.decode(response.responseText);if(this.form.errorReader){var rs=this.form.errorReader.read(response),errors=[];if(rs.records)for(var i=0,len=rs.records.length;i0))return defaultValue;10===timestamp.toString().length&&(timestamp*=1e3);var format=[];return!0===date&&format.push(MODx.config.manager_date_format),!0===time&&format.push(MODx.config.manager_time_format),0===format.length?defaultValue:(format=format.join(" "),new Date(timestamp).format(format))},trimCharacters:function(string,charList="",direction="both"){if(charList.length){const trimLeft={find:new RegExp(`^([${charList}]+)([^${charList}]?)(.*)`,"g"),replace:"$2$3"},trimRight={find:new RegExp(`(.*)([^${charList}]+)([${charList}]+)$`,"g"),replace:"$1$2"};switch(direction){case"both":return string.replace(trimLeft.find,trimLeft.replace).replace(trimRight.find,trimRight.replace);case"left":return string.replace(trimLeft.find,trimLeft.replace);case"right":return string.replace(trimRight.find,trimRight.replace)}}return string},trimAndCollapseSpace:function(value){return"string"!=typeof value||Ext.isEmpty(value)?value:value.trim().replace(/\s{2,}/," ")},trimCharSeparatedList:function(list,separator=",",padListItems=!0){let formattedList=this.trimCharacters(list,`${separator}\\s`);return formattedList=this.trimAndCollapseSpace(formattedList),formattedList=formattedList.replace(new RegExp(`\\s*${separator}\\s*`,"g"),separator).replace(new RegExp(`[${separator}]{2,}`,"g"),separator),padListItems?formattedList.replaceAll(separator,`${separator} `):formattedList}},MODx.util.getHeaderBreadCrumbs=function(header,trail){return"string"==typeof header&&(header={id:header,xtype:"modx-header"}),void 0===trail&&(trail=[]),Array.isArray(trail)||(trail=[trail]),{xtype:"modx-breadcrumbs-panel",id:"modx-header-breadcrumbs",cls:"modx-header-breadcrumbs",desc:"",bdMarkup:'',init:function(){this.tpl=new Ext.XTemplate(this.bdMarkup,{compiled:!0})},trail,listeners:{afterrender:function(){this.renderTrail()}},renderTrail:function(){this.tpl.overwrite(this.body.dom.lastElementChild,{trail:this.trail})},updateTrail:function(trail,replace){if(void 0===replace&&(replace=!1),!0===replace)return this.trail=Array.isArray(trail)?trail:[trail],this.renderTrail(),!0;if(Array.isArray(trail)){for(var i=0;i{params.set(param,value)}));const newUrl=url.toString().replace(/%2F/g,"/");window.history.replaceState(stateData,document.title,newUrl)}},clearAllParams:function(stateData={}){if(void 0!==window.history.replaceState){const preserve=["a","id","key","namespace"],preserved=[],urlParts=window.location.href.split("?");urlParts[1].split("&").forEach((param=>{const paramName=param.split("=")[0];preserve.includes(paramName)&&preserved.push(param)}));let newUrl=new URL(`${urlParts[0]}?${preserved.join("&")}`);newUrl=newUrl.toString().replace(/%2F/g,"/"),window.history.replaceState(stateData,document.title,newUrl)}},clearParam:function(reference,referenceIsComponent=!0,stateData={}){if(void 0!==window.history.replaceState){let removeParamName,url=new URL(window.location.href);referenceIsComponent?(removeParamName=this.getParamNameFromCmp(reference),removeParamName="namespace"===removeParamName?"ns":removeParamName):removeParamName=reference.trim(),url.searchParams.delete(removeParamName),url=url.toString().replace(/%2F/g,"/"),window.history.replaceState(stateData,document.title,url)}},getParamNameFromCmp:function(cmp){const param=cmp.itemId.split("-")[1];return"ns"===param?"namespace":param},getParamValue:function(param,setEmptyToString=!1){const key="namespace"===param?"ns":param,emptyValue=setEmptyToString?"":null;return MODx.request[key]?this.decodeParamValue(MODx.request[key]):emptyValue},decodeParamValue:function(value){return value=value.replace(/\+/g," "),decodeURIComponent(value)}},MODx.util.tree={getGroupIdFromNode:function(node){return node.id?node.id.split("_").pop():0}},Ext.util.Format.trimCommas=function(s){var len=(s=s.replace(",,",",")).length;return","==s.substr(len-1,1)&&(s=s.substring(0,len-1)),","==s.substr(0,1)&&(s=s.substring(1)),","==s&&(s=""),s},Ext.ns("Ext.ux.grid"),"function"!=typeof RegExp.escape&&(RegExp.escape=function(s){return"string"!=typeof s?s:s.replace(/([.*+?\^=!:${}()|\[\]\/\\])/g,"\\$1")}),Ext.ux.grid.RowActions=function(a){Ext.apply(this,a),this.addEvents("beforeaction","action","beforegroupaction","groupaction"),Ext.ux.grid.RowActions.superclass.constructor.call(this)},Ext.extend(Ext.ux.grid.RowActions,Ext.util.Observable,{actionEvent:"click",autoWidth:!0,dataIndex:"",editable:!1,header:"",isColumn:!0,keepSelection:!1,menuDisabled:!0,sortable:!1,tplGroup:'
    ux-action-right {cls}" style="{style}" qtip="{qtip}">{text}
    ',tplRow:'
    ux-row-action-text" style="{hide}{style}" qtip="{qtip}">{text}
    ',hideMode:"visibility",widthIntercept:4,widthSlope:21,init:function(g){this.grid=g,this.id=this.id||Ext.id();var h=g.getColumnModel().lookup;delete h[void 0],h[this.id]=this,this.tpl||(this.tpl=this.processActions(this.actions)),this.autoWidth&&(this.width=this.widthSlope*this.actions.length+this.widthIntercept,this.fixed=!0);var i=g.getView(),j={scope:this};j[this.actionEvent]=this.onClick,g.afterRender=g.afterRender.createSequence((function(){i.mainBody.on(j),g.on("destroy",this.purgeListeners,this)}),this),this.renderer||(this.renderer=function(a,b,c,d,e,f){return b.css+=(b.css?" ":"")+"ux-row-action-cell",this.tpl.apply(this.getData(a,b,c,d,e,f))}.createDelegate(this)),i.groupTextTpl&&this.groupActions&&(i.interceptMouse=i.interceptMouse.createInterceptor((function(e){if(e.getTarget(".ux-grow-action-item"))return!1})),i.groupTextTpl='
    '+i.groupTextTpl+"
    "+this.processActions(this.groupActions,this.tplGroup).apply()),!0===this.keepSelection&&(g.processEvent=g.processEvent.createInterceptor((function(a,e){if("mousedown"===a)return!this.getAction(e)}),this))},getData:function(a,b,c,d,e,f){return c.data||{}},processActions:function(b,c){var d=[];Ext.each(b,(function(a,i){a.iconCls&&"function"==typeof(a.callback||a.cb)&&(this.callbacks=this.callbacks||{},this.callbacks[a.iconCls]=a.callback||a.cb);var o={cls:a.iconIndex?"{"+a.iconIndex+"}":a.iconCls?a.iconCls:"",qtip:a.qtipIndex?"{"+a.qtipIndex+"}":a.tooltip||a.qtip?a.tooltip||a.qtip:"",text:a.textIndex?"{"+a.textIndex+"}":a.text?a.text:"",hide:a.hideIndex?''+("display"===this.hideMode?"display:none":"visibility:hidden")+";":a.hide?"display"===this.hideMode?"display:none":"visibility:hidden;":"",align:a.align||"right",style:a.style?a.style:""};d.push(o)}),this);var e=new Ext.XTemplate(c||this.tplRow);return new Ext.XTemplate(e.apply({actions:d}))},getAction:function(e){var a=!1,t=e.getTarget(".ux-row-action-item");return t&&(a=t.className.replace(/ux-row-action-item /,""))&&(a=(a=a.replace(/ ux-row-action-text/,"")).trim()),a},onClick:function(e,a){var b=this.grid.getView(),c=e.getTarget(".x-grid3-row"),d=b.findCellIndex(a.parentNode.parentNode),f=this.getAction(e);if(!1!==c&&!1!==d&&!1!==f){var g=this.grid.store.getAt(c.rowIndex);if(this.callbacks&&"function"==typeof this.callbacks[f]&&this.callbacks[f](this.grid,g,f,c.rowIndex,d),!0!==this.eventsSuspended&&!1===this.fireEvent("beforeaction",this.grid,g,f,c.rowIndex,d))return;!0!==this.eventsSuspended&&this.fireEvent("action",this.grid,g,f,c.rowIndex,d)}if(t=e.getTarget(".ux-grow-action-item"),t){var j,h=b.findGroup(a),i=h?h.id.replace(/ext-gen[0-9]+-gp-/,""):null;if(i){var k=new RegExp(RegExp.escape(i));j=(j=this.grid.store.queryBy((function(r){return r._groupId.match(k)})))?j.items:[]}if(f=t.className.replace(/ux-grow-action-item (ux-action-right )*/,""),"function"==typeof this.callbacks[f]&&this.callbacks[f](this.grid,j,f,i),!0!==this.eventsSuspended&&!1===this.fireEvent("beforegroupaction",this.grid,j,f,i))return!1;this.fireEvent("groupaction",this.grid,j,f,i)}}}),Ext.reg("rowactions",Ext.ux.grid.RowActions),Ext.SwitchButton=Ext.extend(Ext.Component,{initComponent:function(){Ext.SwitchButton.superclass.initComponent.call(this);var mc=new Ext.util.MixedCollection;mc.addAll(this.items),this.items=mc,this.addEvents("change"),this.handler&&this.on("change",this.handler,this.scope||this)},onRender:function(ct,position){var el=document.createElement("table");el.cellSpacing=0,el.className="x-rbtn",el.id=this.id;var row=document.createElement("tr");el.appendChild(document.createElement("tbody")).appendChild(row);var count=this.items.length,last=count-1;this.activeItem=this.items.get(this.activeItem);for(var i=0;idata.rowIndex&&this.rowPosition<0&&rindex--,rindex0&&rindex++,rindex>data.rowIndex&&data.selections.length>1&&(rindex-=data.selections.length-1),rindex==data.rowIndex)return!1;if(!self.copy)for(i=0;i=0;i--){var insertIndex=rindex;ds.insert(insertIndex,selections[i])}var sm=this.grid.getSelectionModel();return sm&&sm.selectRecords(data.selections),this.gridDropTarget.fireEvent(self.copy?"afterrowcopy":"afterrowmove",this.gridDropTarget,data.rowIndex,rindex,data.selections),!0},notifyOver:function(dd,e,data){var t=Ext.lib.Event.getTarget(e),rindex=this.grid.getView().findRowIndex(t),keys=this.grid.getStore().data.keys;for(var key in keys)for(var i=0;i0)this.currentRowEl=new Ext.Element(currentRow),this.currentRowEl.addClass("grid-row-insert-below");else if(rindex-1>=0){var previousRow=this.grid.getView().getRow(rindex-1);this.currentRowEl=new Ext.Element(previousRow),this.currentRowEl.addClass("grid-row-insert-below")}else this.currentRowEl.addClass("grid-row-insert-above")}catch(err){console.warn(err),rindex=!1}return!1===rindex?this.dropNotAllowed:this.dropAllowed},notifyOut:function(dd,e,data){this.currentRowEl&&(this.currentRowEl.removeClass("grid-row-insert-above"),this.currentRowEl.removeClass("grid-row-insert-below"))}}),this.targetCfg&&Ext.apply(this.target,this.targetCfg),this.scrollable&&(Ext.dd.ScrollManager.register(grid.getView().getEditorParent()),grid.on({beforedestroy:this.onBeforeDestroy,scope:this,single:!0}))},getTarget:function(){return this.target},getGrid:function(){return this.grid},getCopy:function(){return!!this.copy},setCopy:function(b){this.copy=!!b},onBeforeDestroy:function(grid){Ext.dd.ScrollManager.unregister(grid.getView().getEditorParent())}}),Ext.grid.GridView.prototype.templates||(Ext.grid.GridView.prototype.templates={}),Ext.grid.GridView.prototype.templates.cell=new Ext.Template('','
    {value}
    ',""),MODx.grid||(MODx.grid={}),MODx.grid.ComboColumn=Ext.extend(Ext.grid.Column,{gridId:void 0,constructor:function(cfg){MODx.grid.ComboColumn.superclass.constructor.call(this,cfg),this.renderer=this.editor&&this.editor.triggerAction?MODx.grid.ComboBoxRenderer(this.editor,this.gridId,cfg.renderer):function(value){return value}}}),Ext.grid.Column.types.combocolumn=MODx.grid.ComboColumn,MODx.grid.ComboBoxRenderer=function(combo,gridId,currentRenderer){return function(value,metaData,record,rowIndex,colIndex,store){if(currentRenderer){if("function"==typeof currentRenderer.fn){var scope=!!currentRenderer.scope&¤tRenderer.scope;currentRenderer=currentRenderer.fn.bind(scope)}"function"==typeof currentRenderer&&(value=currentRenderer(value,metaData,record,rowIndex,colIndex,store))}return 0==combo.store.getCount()&&gridId?(combo.store.on("load",(function(){var grid=Ext.getCmp(gridId);grid&&grid.getView().refresh()}),this,{single:!0}),value):function(value){var idx=combo.store.find(combo.valueField,value),rec=combo.store.getAt(idx);return rec?rec.get(combo.displayField):value}(value)}},Ext.Button.buttonTemplate=new Ext.Template(''),Ext.Button.buttonTemplate.compile(),Ext.TabPanel.prototype.itemTpl=new Ext.Template('
  • ','{text}
  • '),Ext.TabPanel.prototype.itemTpl.disableFormats=!0,Ext.TabPanel.prototype.itemTpl.compile(),Ext.namespace("Ext.ux.form"),Ext.ux.form.CheckboxGroup=Ext.extend(Ext.form.CheckboxGroup,{aggregateSubmitField:{},initComponent:function(){const me=this,ct=this.ownerCt;"string"==typeof this.name&&this.name.length>0?(this.aggregateSubmitField=new Ext.form.Hidden({name:this.name}),Ext.ux.form.CheckboxGroup.superclass.initComponent.call(this),this.cls="string"==typeof this.cls&&this.cls.length>0?"aggregated-group "+this.cls:"aggregated-group",Ext.each(this.items,(function(item){if("string"==typeof me.value&&me.value.length>0){me.value.split(",").find((function(v){return v==item.inputValue}))==item.inputValue&&(item.checked=!0),me.aggregateSubmitField.setValue(me.value)}item.listeners={check:{fn:me.setHiddenSubmit,scope:me}},item.submitValue=!1})),ct.add(this.aggregateSubmitField)):console.warning("Ext.ux.form.CheckboxGroup: A name must be specified in this component’s config for its values to be saved.",this)},setHiddenSubmit:function(){const groupOpts=this.items.items;let vals=[];Ext.each(groupOpts,(function(item){item.checked&&vals.push(item.inputValue)})),this.aggregateSubmitField.setValue(vals.join(","))}}),Ext.reg("xcheckboxgroup",Ext.ux.form.CheckboxGroup),Ext.define("AddFieldUtilities.plugin.Class",{alias:"plugin.fieldutilities",init:function(cmp){cmp.on("afterrender",this.afterRender,cmp)},afterRender:function(){const me=this;this.label.createChild({tag:"a",title:_("field_reset"),cls:"modx-field-utils modx-field-reset"}).on("click",(function(){me.reset()}),me),this.label.createChild({tag:"a",title:_("field_clear"),cls:"modx-field-utils modx-field-clear"}).on("click",(function(){switch(this.xtype){case"xcheckboxgroup":case"checkboxgroup":Ext.isArray(this.items.items)&&(Ext.each(this.items.items,(function(item){item.setValue(!1)})),this.doLayout());break;case"checkbox":case"radio":me.setValue(!1);break;default:me.setValue("")}}),me)}}),MODx.util.FileDownload=function(fields){if(Ext.isObject(fields)){var me=this;me.clearCookie=function(){Ext.util.Cookies.set(cookieName,null,new Date("January 1, 1970"),"/"),Ext.util.Cookies.clear(cookieName,"/")},me.randomHex=function(len){const hex="0123456789ABCDEF";let output="";for(let i=0;i0){var result=Ext.decode(frame.dom.contentDocument.body.innerHTML);return result=result||{success:!1,message:_("file_msg_download_error")},me.clearCookie(),failureCallback&&failureCallback(result),void(frame.dom.contentDocument.body.innerHTML="")}}catch(e){console.log(e)}polling?(debug&&console.log("polling "+polling),window.setTimeout((function(){polling--,me.isFinished(successCallback,failureCallback)}),100)):(me.clearCookie(),failureCallback&&failureCallback({success:!1,message:_("file_err_download_timeout")}))};var cookieName="fileDownload"+me.randomHex(16),polling=10*fields.timeout||300,ident=fields.ident||"filedownload-"+Ext.id(),url=fields.url||MODx.config.connector_url,params=fields.params||{},debug=fields.debug||!1,successCallback=fields.success||null,failureCallback=fields.failure||null,body=Ext.getBody(),frame=body.createChild({tag:"iframe",cls:"x-hidden",id:ident+"-iframe",name:ident+"-iframe"}),form=body.createChild({tag:"form",cls:"x-hidden",id:ident+"-form",action:url,target:ident+"-iframe",method:"post"});params.HTTP_MODAUTH=MODx.siteId,"function"==typeof successCallback&&(params.cookieName=cookieName),Ext.iterate(params,(function(name,value){form.createChild({tag:"input",type:"text",cls:"x-hidden",id:ident+"-"+name,name,value})})),form.dom.submit(),(successCallback||failureCallback)&&me.isFinished(successCallback,failureCallback)}},Ext.override(Ext.form.TimeField,{initDate:"2/1/2008"}),Ext.ns("Ext.ux.form"),Ext.ux.form.DateTime=Ext.extend(Ext.form.Field,{dateValidator:null,defaultAutoCreate:{tag:"input",type:"hidden"},dtSeparator:" ",hiddenFormat:"Y-m-d H:i:s",otherToNow:!0,timePosition:"right",timeValidator:null,timeWidth:100,dateFormat:"m/d/y",timeFormat:"g:i A",maxDateValue:"",minDateValue:"",timeIncrement:15,maxTimeValue:null,minTimeValue:null,disabledDates:null,hideTime:!1,initComponent:function(){Ext.ux.form.DateTime.superclass.initComponent.call(this),this.hasOwnProperty("offset_time")&&!isNaN(this.offset_time)||(this.offset_time=0);var dateConfig=Ext.apply({},{id:this.id+"-date",format:this.dateFormat||Ext.form.DateField.prototype.format,width:this.timeWidth,selectOnFocus:this.selectOnFocus,validator:this.dateValidator,disabledDates:this.disabledDates||null,disabledDays:this.disabledDays||[],showToday:this.showToday||!0,maxValue:this.maxDateValue||"",minValue:this.minDateValue||"",startDay:this.startDay||0,allowBlank:this.allowBlank,msgTarget:this.msgTarget,listeners:{blur:{scope:this,fn:this.onBlur},focus:{scope:this,fn:this.onFocus}}},this.dateConfig);this.df=new Ext.form.DateField(dateConfig),this.df.ownerCt=this,delete this.dateFormat,delete this.disabledDates,delete this.disabledDays,delete this.maxDateValue,delete this.minDateValue,delete this.startDay;var timeConfig=Ext.apply({},{id:this.id+"-time",format:this.timeFormat||Ext.form.TimeField.prototype.format,width:this.timeWidth,selectOnFocus:this.selectOnFocus,validator:this.timeValidator,increment:this.timeIncrement||15,maxValue:this.maxTimeValue||null,minValue:this.minTimeValue||null,hidden:this.hideTime,allowBlank:this.allowBlank,msgTarget:this.msgTarget,listeners:{blur:{scope:this,fn:this.onBlur},focus:{scope:this,fn:this.onFocus}}},this.timeConfig);this.tf=new Ext.form.TimeField(timeConfig),this.tf.ownerCt=this,delete this.timeFormat,delete this.maxTimeValue,delete this.minTimeValue,delete this.timeIncrement,this.relayEvents(this.df,["focus","specialkey","invalid","valid"]),this.relayEvents(this.tf,["focus","specialkey","invalid","valid"]),this.on("specialkey",this.onSpecialKey,this)},onRender:function(ct,position){if(!this.isRendered){var t;switch(Ext.ux.form.DateTime.superclass.onRender.call(this,ct,position),t="below"===this.timePosition||"bellow"===this.timePosition?Ext.DomHelper.append(ct,{tag:"table",style:"border-collapse:collapse",children:[{tag:"tr",children:[{tag:"td",style:"padding-bottom:1px",cls:"ux-datetime-date"}]},{tag:"tr",children:[{tag:"td",cls:"ux-datetime-time"}]}]},!0):Ext.DomHelper.append(ct,{tag:"table",style:"border-collapse:collapse",children:[{tag:"tr",children:[{tag:"td",style:"padding-right:4px",cls:"ux-datetime-date"},{tag:"td",cls:"ux-datetime-time"}]}]},!0),this.tableEl=t,this.wrap=t.wrap({cls:"x-form-field-wrap x-datetime-wrap"}),this.wrap.on("mousedown",this.onMouseDown,this,{delay:10}),this.df.render(t.child("td.ux-datetime-date")),this.tf.render(t.child("td.ux-datetime-time")),this.df.el.swallowEvent(["keydown","keypress"]),this.tf.el.swallowEvent(["keydown","keypress"]),this.msgTarget){case"side":const elp=this.el.findParent(".x-form-element",10,!0);elp&&(this.errorIcon=elp.createChild({cls:"x-form-invalid-icon"}));const o={errorIcon:this.errorIcon,msgTarget:"side",alignErrorIcon:this.alignErrorIcon.createDelegate(this)};Ext.apply(this.df,o),Ext.apply(this.tf,o);break;case"under":const dateMsgElId=`ux-datetime-date-msg-${this.itemId}`,dateMsgWidth=Math.ceil(this.dateWidth-30),dateMsgEl=Ext.DomHelper.append(this.df.container,{tag:"div",cls:"x-form-invalid-msg",style:`display: none; width: ${dateMsgWidth}px;`,id:dateMsgElId}),timeMsgElId=`ux-datetime-time-msg-${this.itemId}`,timeMsgWidth=Math.ceil(this.timeWidth-30),timeMsgEl=Ext.DomHelper.append(this.tf.container,{tag:"div",cls:"x-form-invalid-msg",style:`display: none; width: ${timeMsgWidth}px;`,id:timeMsgElId});this.df.container.appendChild(dateMsgEl),this.tf.container.appendChild(timeMsgEl),this.df.msgTarget=dateMsgElId,this.tf.msgTarget=timeMsgElId}this.el.dom.name=this.hiddenName||this.name||this.id,this.df.el.dom.removeAttribute("name"),this.tf.el.dom.removeAttribute("name"),this.isRendered=!0,this.updateHidden()}},adjustSize:Ext.BoxComponent.prototype.adjustSize,alignErrorIcon:function(){this.errorIcon.alignTo(this.tableEl,"tl-tr",[2,0])},initDateValue:function(){this.dateValue=this.otherToNow?new Date:new Date(1970,0,1,0,0,0)},clearInvalid:function(){this.df.clearInvalid(),this.tf.clearInvalid()},markInvalid:function(msg){this.df.markInvalid(msg),this.tf.markInvalid(msg)},beforeDestroy:function(){this.isRendered&&(this.wrap.removeAllListeners(),this.wrap.remove(),this.tableEl.remove(),this.df.destroy(),this.tf.destroy())},disable:function(){return this.isRendered&&(this.df.disabled=this.disabled,this.df.onDisable(),this.tf.onDisable()),this.disabled=!0,this.df.disabled=!0,this.tf.disabled=!0,this.fireEvent("disable",this),this},enable:function(){return this.rendered&&(this.df.onEnable(),this.tf.onEnable()),this.disabled=!1,this.df.disabled=!1,this.tf.disabled=!1,this.fireEvent("enable",this),this},focus:function(){this.df.focus()},getPositionEl:function(){return this.wrap},getResizeEl:function(){return this.wrap},getValue:function(){return this.dateValue?new Date(this.dateValue):""},isValid:function(){return this.df.isValid()&&this.tf.isValid()},isVisible:function(){return this.df.rendered&&this.df.getActionEl().isVisible()},onBlur:function(f){this.wrapClick&&(f.focus(),this.wrapClick=!1),f===this.df?this.updateDate():this.updateTime(),this.updateHidden(),this.validate(),function(){if(!this.df.hasFocus&&!this.tf.hasFocus){var v=this.getValue();String(v)!==String(this.startValue)&&this.fireEvent("change",this,v,this.startValue),this.hasFocus=!1,this.fireEvent("blur",this)}}.defer(100,this)},onFocus:function(){this.hasFocus||(this.hasFocus=!0,this.startValue=this.getValue(),this.fireEvent("focus",this))},onMouseDown:function(e){this.disabled||(this.wrapClick="td"===e.target.nodeName.toLowerCase())},onSpecialKey:function(t,e){var key=e.getKey();key===e.TAB&&(t!==this.df||e.shiftKey||(this.onBlur(t),e.stopEvent(),this.tf.focus()),t===this.tf&&e.shiftKey&&(this.onBlur(t),e.stopEvent(),this.df.focus()),this.updateValue()),key===e.ENTER&&this.updateValue()},reset:function(){this.df.setValue(this.originalValue),this.tf.setValue(this.originalValue)},setDate:function(date){date&&0!=this.offset_time&&(date=date.add(Date.MINUTE,60*new Number(this.offset_time))),this.df.setValue(date)},setTime:function(date){date&&0!=this.offset_time&&(date=date.add(Date.MINUTE,60*new Number(this.offset_time))),this.tf.setValue(date)},setSize:function(w,h){w&&("below"===this.timePosition?(this.df.setSize(w,h),this.tf.setSize(w,h),Ext.isIE&&(this.df.el.up("td").setWidth(w),this.tf.el.up("td").setWidth(w))):(this.df.setSize(w-this.timeWidth-4,h),this.tf.setSize(this.timeWidth,h),Ext.isIE&&(this.df.el.up("td").setWidth(w-this.timeWidth-4),this.tf.el.up("td").setWidth(this.timeWidth))))},setValue:function(val){if(val||!0!==this.emptyToNow){if(!val)return this.setDate(""),this.setTime(""),void this.updateValue();var da;"number"==typeof val?val=new Date(val):"string"==typeof val&&this.hiddenFormat&&(val=Date.parseDate(val,this.hiddenFormat)),(val=val||new Date(1970,0,1,0,0,0))instanceof Date?(this.setDate(val),this.setTime(val),this.dateValue=new Date(Ext.isIE?val.getTime():val)):(da=val.split(this.dtSeparator),this.setDate(da[0]),da[1]&&(da[2]&&(da[1]+=da[2]),this.setTime(da[1]))),this.updateValue()}else this.setValue(new Date)},setVisible:function(visible){return visible?(this.df.show(),this.tf.show()):(this.df.hide(),this.tf.hide()),this},show:function(){return this.setVisible(!0)},hide:function(){return this.setVisible(!1)},updateDate:function(){var d=this.df.getValue();d?(this.dateValue instanceof Date||(this.initDateValue(),this.tf.getValue()||this.setTime(this.dateValue)),this.dateValue.setMonth(0),this.dateValue.setFullYear(d.getFullYear()),this.dateValue.setMonth(d.getMonth(),d.getDate())):(this.dateValue="",this.setTime(""))},updateTime:function(){let t=this.tf.getValue();!t||t instanceof Date||(t=Date.parseDate(t,this.tf.format)),t&&!this.df.getValue()&&(this.initDateValue(),this.setDate(this.dateValue)),this.dateValue instanceof Date&&(t&&!this.hideTime?(this.dateValue.setHours(t.getHours()),this.dateValue.setMinutes(t.getMinutes()),this.dateValue.setSeconds(t.getSeconds())):(this.dateValue.setHours(0),this.dateValue.setMinutes(0),this.dateValue.setSeconds(0)))},updateHidden:function(){if(this.isRendered){var value="";this.dateValue instanceof Date&&(value=this.dateValue.add(Date.MINUTE,0-60*new Number(this.offset_time)).format(this.hiddenFormat)),this.el.dom.value=value}},updateValue:function(){this.updateDate(),this.updateTime(),this.updateHidden()},validate:function(){return this.df.validate()&&this.tf.validate()},renderer:function(field){var format=field.editor.dateFormat||Ext.ux.form.DateTime.prototype.dateFormat;return format+=" "+(field.editor.timeFormat||Ext.ux.form.DateTime.prototype.timeFormat),function(val){return Ext.util.Format.date(val,format)}}}),Ext.reg("xdatetime",Ext.ux.form.DateTime),Ext.namespace("Ext.ux.Utils"),Ext.ux.Utils.EventQueue=function(handler,scope){if(!handler)throw"Handler is required.";this.handler=handler,this.scope=scope||window,this.queue=[],this.is_processing=!1,this.postEvent=function(event,data){data=data||null,this.queue.push({event,data}),this.is_processing||this.process()},this.flushEventQueue=function(){this.queue=[]},this.process=function(){for(;this.queue.length>0;){this.is_processing=!0;var event_data=this.queue.shift();this.handler.call(this.scope,event_data.event,event_data.data)}this.is_processing=!1}},Ext.ux.Utils.FSA=function(initial_state,trans_table,trans_table_scope){this.current_state=initial_state,this.trans_table=trans_table||{},this.trans_table_scope=trans_table_scope||window,Ext.ux.Utils.FSA.superclass.constructor.call(this,this.processEvent,this)},Ext.extend(Ext.ux.Utils.FSA,Ext.ux.Utils.EventQueue,{current_state:null,trans_table:null,trans_table_scope:null,state:function(){return this.current_state},processEvent:function(event,data){var transitions=this.currentStateEventTransitions(event);if(!transitions)throw"State '"+this.current_state+"' has no transition for event '"+event+"'.";for(var i=0,len=transitions.length;i ").compile()},createForm:function(){this.form=Ext.DomHelper.append(this.body,{tag:"form",method:"post",action:this.url,style:"position: absolute; left: -100px; top: -100px; width: 100px; height: 100px; clear: both;"})},createProgressBar:function(){this.progress_bar=this.add(new Ext.ProgressBar({x:0,y:0,anchor:"0",value:0,text:this.i18n.progress_waiting_text}))},createGrid:function(){var store=new Ext.data.Store({proxy:new Ext.data.MemoryProxy([]),reader:new Ext.data.JsonReader({},Ext.ux.UploadDialog.FileRecord),sortInfo:{field:"state",direction:"DESC"},pruneModifiedRecords:!0}),cm=new Ext.grid.ColumnModel([{header:this.i18n.state_col_title,width:this.i18n.state_col_width,resizable:!1,dataIndex:"state",sortable:!0,renderer:this.renderStateCell.createDelegate(this)},{header:this.i18n.filename_col_title,width:this.i18n.filename_col_width,dataIndex:"filename",sortable:!0,renderer:this.renderFilenameCell.createDelegate(this)},{header:this.i18n.note_col_title,width:this.i18n.note_col_width,dataIndex:"note",sortable:!0,renderer:this.renderNoteCell.createDelegate(this)}]);this.grid_panel=new Ext.grid.GridPanel({ds:store,cm,layout:"fit",height:this.height-100,region:"center",x:0,y:22,border:!0,viewConfig:{autoFill:!0,forceFit:!0},bbar:new Ext.Toolbar}),this.grid_panel.on("render",this.onGridRender,this),this.add(this.grid_panel),this.grid_panel.getSelectionModel().on("selectionchange",this.onGridSelectionChange,this)},fillToolbar:function(){var tb=this.grid_panel.getBottomToolbar();tb.x_buttons={},tb.x_buttons.add=tb.addItem(new Ext.ux.UploadDialog.TBBrowseButton({input_name:this.post_var_name,text:this.i18n.add_btn_text,tooltip:this.i18n.add_btn_tip,iconCls:"ext-ux-uploaddialog-addbtn",handler:this.onAddButtonFileSelected,scope:this})),tb.x_buttons.remove=tb.addButton({text:this.i18n.remove_btn_text,tooltip:this.i18n.remove_btn_tip,iconCls:"ext-ux-uploaddialog-removebtn",handler:this.onRemoveButtonClick,scope:this}),tb.x_buttons.reset=tb.addButton({text:this.i18n.reset_btn_text,tooltip:this.i18n.reset_btn_tip,iconCls:"ext-ux-uploaddialog-resetbtn",handler:this.onResetButtonClick,scope:this}),tb.x_buttons.upload=tb.addButton({text:this.i18n.upload_btn_start_text,tooltip:this.i18n.upload_btn_start_tip,iconCls:"ext-ux-uploaddialog-uploadstartbtn",handler:this.onUploadButtonClick,scope:this}),tb.x_buttons.close=tb.addButton({text:this.i18n.close_btn_text,tooltip:this.i18n.close_btn_tip,handler:this.onCloseButtonClick,scope:this})},renderStateCell:function(data,cell,record,row_index,column_index,store){return this.state_tpl.apply({state:data})},renderFilenameCell:function(data,cell,record,row_index,column_index,store){var view=this.grid_panel.getView();return function(){try{Ext.fly(view.getCell(row_index,column_index)).child(".x-grid3-cell-inner").dom.qtip=data}catch(e){}}.defer(1e3),data},renderNoteCell:function(data,cell,record,row_index,column_index,store){var view=this.grid_panel.getView();return function(){try{Ext.fly(view.getCell(row_index,column_index)).child(".x-grid3-cell-inner").dom.qtip=data}catch(e){}}.defer(1e3),data},getFileExtension:function(filename){var result=null,parts=filename.split(".");return parts.length>1&&(result=parts.pop()),result},isPermittedFileType:function(filename){var result=!0;return this.permitted_extensions.length>0&&(result=-1!=this.permitted_extensions.indexOf(this.getFileExtension(filename))),result},isPermittedFile:function(browse_btn){var result=!1,filename=browse_btn.getInputFile().dom.value;return this.isPermittedFileType(filename)?result=!0:(Ext.Msg.alert(this.i18n.error_msgbox_title,String.format(this.i18n.err_file_type_not_permitted,filename,this.permitted_extensions.join(this.i18n.permitted_extensions_join_str))),result=!1),result},fireFileTestEvent:function(browse_btn){return!1!==this.fireEvent("filetest",this,browse_btn.getInputFile().dom.value)},addFileToUploadQueue:function(browse_btn){var input_file=browse_btn.detachInputFile();input_file.appendTo(this.form),input_file.setStyle("width","100px"),input_file.dom.disabled=!0;var store=this.grid_panel.getStore(),fileApi=input_file.dom.files,filename=void 0!==fileApi?fileApi[0].name:input_file.dom.value.replace("C:\\fakepath\\","");store.add(new Ext.ux.UploadDialog.FileRecord({state:Ext.ux.UploadDialog.FileRecord.STATE_QUEUE,filename,note:this.i18n.note_queued_to_upload,input_element:input_file})),this.fsa.postEvent("file-added",input_file.dom.value)},fireFileAddEvent:function(filename){this.fireEvent("fileadd",this,filename)},updateProgressBar:function(){if(this.is_uploading){var queued=this.getQueuedCount(!0),value=1-queued/this.initial_queued_count;this.progress_bar.updateProgress(value,String.format(this.i18n.progress_uploading_text,this.initial_queued_count-queued,this.initial_queued_count))}else this.progress_bar.updateProgress(0,this.i18n.progress_waiting_text)},updateToolbar:function(){var tb=this.grid_panel.getBottomToolbar();this.is_uploading?(tb.x_buttons.remove.disable(),tb.x_buttons.reset.disable(),tb.x_buttons.upload.enable(),this.getAllowCloseOnUpload()||tb.x_buttons.close.disable(),tb.x_buttons.upload.setIconClass("ext-ux-uploaddialog-uploadstopbtn"),tb.x_buttons.upload.setText(this.i18n.upload_btn_stop_text),tb.x_buttons.upload.getEl().child(tb.x_buttons.upload.buttonSelector).dom[tb.x_buttons.upload.tooltipType]=this.i18n.upload_btn_stop_tip):(tb.x_buttons.remove.enable(),tb.x_buttons.reset.enable(),tb.x_buttons.close.enable(),tb.x_buttons.upload.setIconClass("ext-ux-uploaddialog-uploadstartbtn"),tb.x_buttons.upload.setText(this.i18n.upload_btn_start_text),this.getQueuedCount()>0?tb.x_buttons.upload.enable():tb.x_buttons.upload.disable(),this.grid_panel.getSelectionModel().hasSelection()?tb.x_buttons.remove.enable():tb.x_buttons.remove.disable(),this.grid_panel.getStore().getCount()>0?tb.x_buttons.reset.enable():tb.x_buttons.reset.disable())},saveInitialQueuedCount:function(){this.initial_queued_count=this.getQueuedCount()},incInitialQueuedCount:function(){this.initial_queued_count++},setUploadingFlag:function(){this.is_uploading=!0},resetUploadingFlag:function(){this.is_uploading=!1},prepareNextUploadTask:function(){var store=this.grid_panel.getStore(),record=null;store.each((function(r){record||r.get("state")!=Ext.ux.UploadDialog.FileRecord.STATE_QUEUE?r.get("input_element").dom.disabled=!0:record=r})),record.get("input_element").dom.disabled=!1,record.set("state",Ext.ux.UploadDialog.FileRecord.STATE_PROCESSING),record.set("note",this.i18n.note_processing),record.commit(),this.fsa.postEvent("file-upload-start",record)},fireUploadStartEvent:function(){this.fireEvent("uploadstart",this)},removeFiles:function(file_records){for(var store=this.grid_panel.getStore(),i=0,len=file_records.length;i((?:.|\n)*)<\/pre>$/i);filter&&(rt=filter[1]),json_response=Ext.util.JSON.decode(rt)}catch(e){}var data={record:options.record,response:json_response};"success"in json_response&&json_response.success?this.fsa.postEvent("file-upload-success",data):this.fsa.postEvent("file-upload-error",data)},onAjaxFailure:function(response,options){var data={record:options.record,response:{success:!1,error:this.i18n.note_upload_failed}};this.fsa.postEvent("file-upload-failed",data)},startUpload:function(){this.fsa.postEvent("start-upload")},stopUpload:function(){this.fsa.postEvent("stop-upload")},getUrl:function(){return this.url},setUrl:function(url){this.url=url},getBaseParams:function(){return this.base_params},setBaseParams:function(params){this.base_params=params},getUploadAutostart:function(){return this.upload_autostart},setUploadAutostart:function(value){this.upload_autostart=value},getMakeReload:function(){return this.Make_Reload},setMakeReload:function(value){this.Make_Reload=value},getAllowCloseOnUpload:function(){return this.allow_close_on_upload},setAllowCloseOnUpload:function(value){this.allow_close_on_upload},getResetOnHide:function(){return this.reset_on_hide},setResetOnHide:function(value){this.reset_on_hide=value},getPermittedExtensions:function(){return this.permitted_extensions},setPermittedExtensions:function(value){this.permitted_extensions=value},isUploading:function(){return this.is_uploading},isNotEmptyQueue:function(){return this.grid_panel.getStore().getCount()>0},getQueuedCount:function(count_processing){var count=0;return this.grid_panel.getStore().each((function(r){r.get("state")==Ext.ux.UploadDialog.FileRecord.STATE_QUEUE&&count++,count_processing&&r.get("state")==Ext.ux.UploadDialog.FileRecord.STATE_PROCESSING&&count++})),count},hasUnuploadedFiles:function(){return this.getQueuedCount()>0}});var p=Ext.ux.UploadDialog.Dialog.prototype;p.i18n={title:_("upload_files"),state_col_title:_("upf_state"),state_col_width:70,filename_col_title:_("upf_filename"),filename_col_width:230,note_col_title:_("upf_note"),note_col_width:150,add_btn_text:_("upf_add"),add_btn_tip:_("upf_add_desc"),remove_btn_text:_("upf_remove"),remove_btn_tip:_("upf_remove_desc"),reset_btn_text:_("upf_reset"),reset_btn_tip:_("upf_reset_desc"),upload_btn_start_text:_("upf_upload"),upload_btn_start_tip:_("upf_upload_desc"),upload_btn_stop_text:_("upf_abort"),upload_btn_stop_tip:_("upf_abort_desc"),close_btn_text:_("upf_close"),close_btn_tip:_("upf_close_desc"),progress_waiting_text:_("upf_progress_wait"),progress_uploading_text:_("upf_uploading_desc"),error_msgbox_title:_("upf_error"),permitted_extensions_join_str:",",err_file_type_not_permitted:_("upf_err_filetype"),note_queued_to_upload:_("upf_queued"),note_processing:_("upf_uploading"),note_upload_failed:_("upf_err_failed"),note_upload_success:_("upf_success"),note_upload_error:_("upf_upload_err"),note_aborted:_("upf_aborted")}, +Ext.onReady((function(){if("en"==MODx.config.cultureKey)return!1;Date.dayNames=[_("sunday"),_("monday"),_("tuesday"),_("wednesday"),_("thursday"),_("friday"),_("saturday")],Date.monthNames=[_("january"),_("february"),_("march"),_("april"),_("may"),_("june"),_("july"),_("august"),_("september"),_("october"),_("november"),_("december")],Ext.apply(Ext.grid.GridView.prototype,{sortAscText:_("ext_sortasc"),sortDescText:_("ext_sortdesc"),lockText:_("ext_column_lock"),unlockText:_("ext_column_unlock"),columnsText:_("ext_columns"),emptyText:_("ext_emptymsg")}),Ext.apply(Ext.DatePicker.prototype,{todayText:_("today"),todayTip:_("ext_today_tip"),minText:_("ext_mindate"),maxText:_("ext_maxdate"),monthNames:Date.monthNames,dayNames:Date.dayNames,nextText:_("ext_nextmonth"),prevText:_("ext_prevmonth"),monthYearText:_("ext_choosemonth")}),Ext.MessageBox.buttonText={yes:_("yes"),no:_("no"),ok:_("ok"),cancel:_("cancel")},Ext.apply(Ext.PagingToolbar.prototype,{afterPageText:_("ext_afterpage"),beforePageText:_("ext_beforepage"),displayMsg:_("ext_displaying"),emptyMsg:_("ext_emptymsg"),firstText:_("ext_first"),prevText:_("ext_prev"),nextText:_("ext_next"),lastText:_("ext_last"),refreshText:_("ext_refresh")}),Ext.apply(Ext.Updater.prototype,{text:_("loading")}),Ext.apply(Ext.LoadMask.prototype,{msg:_("loading")}),Ext.apply(Ext.layout.BorderLayout.SplitRegion.prototype,{splitTip:_("ext_splittip")}),Ext.apply(Ext.form.BasicForm.prototype,{waitTitle:_("please_wait")}),Ext.apply(Ext.form.ComboBox.prototype,{loadingText:_("loading")}),Ext.apply(Ext.form.Field.prototype,{invalidText:_("ext_invalidfield")}),Ext.apply(Ext.form.TextField.prototype,{minLengthText:_("ext_minlenfield"),maxLengthText:_("ext_maxlenfield"),invalidText:_("ext_invalidfield"),blankText:_("field_required")}),Ext.apply(Ext.form.NumberField.prototype,{minText:_("ext_minvalfield"),maxText:_("ext_maxvalfield"),nanText:_("ext_nanfield")}),Ext.apply(Ext.form.DateField.prototype,{disabledDaysText:_("disabled"),disabledDatesText:_("disabled"),minText:_("ext_datemin"),maxText:_("ext_datemax"),invalidText:_("ext_dateinv")}),Ext.apply(Ext.form.VTypes,{emailText:_("ext_inv_email"),urlText:_("ext_inv_url"),alphaText:_("ext_inv_alpha"),alphanumText:_("ext_inv_alphanum")}),Ext.apply(Ext.grid.GroupingView.prototype,{emptyGroupText:_("ext_emptygroup"),groupByText:_("ext_groupby"),showGroupsText:_("ext_showgroups")}),Ext.apply(Ext.grid.PropertyColumnModel.prototype,{nameText:_("name"),valueText:_("value")}),Ext.apply(Ext.form.CheckboxGroup.prototype,{blankText:_("ext_checkboxinv")}),Ext.apply(Ext.form.RadioGroup.prototype,{blankText:_("ext_checkboxinv")}),Ext.apply(Ext.form.TimeField.prototype,{minText:_("ext_timemin"),maxText:_("ext_timemax"),invalidText:_("ext_timeinv")})})),Ext.namespace("MODx.util.Progress"),Ext.namespace("MODx.util.Format"),MODx.util.JSONReader=function(config={}){Ext.applyIf(config,{successProperty:"success",totalProperty:"total",root:"data"}),MODx.util.JSONReader.superclass.constructor.call(this,config,["id","msg"])},Ext.extend(MODx.util.JSONReader,Ext.data.JsonReader),Ext.reg("modx-json-reader",MODx.util.JSONReader),MODx.util.Progress={id:0,time:function(v,id,msg){msg=msg||_("saving"),MODx.util.Progress.id===id&&v<11&&Ext.MessageBox.updateProgress(v/10,msg)},reset:function(){MODx.util.Progress.id+=1}},MODx.util.UrlParams={get(){return this.parse(window.location.search)},set(data){const params=decodeURIComponent(new URLSearchParams(data).toString());params.length?window.history.pushState(params,"",`${document.location.pathname}?${params}`):window.history.pushState("","",document.location.pathname)},add(key,val){const params=this.get();params[key]=val,this.set(params)},remove(key){const params=this.get();delete params[key],this.set(params)},clear(){this.set({})},parse(str){const params=new URLSearchParams(str);return Object.fromEntries(params.entries())}},MODx.LockMask=function(config={}){Ext.applyIf(config,{msg:_("locked"),msgCls:"modx-lockmask"}),MODx.LockMask.superclass.constructor.call(this,config.el,config)},Ext.extend(MODx.LockMask,Ext.LoadMask,{locked:!1,toggle:function(){this.locked?(this.hide(),this.locked=!1):(this.show(),this.locked=!0)},lock:function(){this.locked=!0,this.show()},unlock:function(){this.locked=!1,this.hide()}}),Ext.reg("modx-lockmask",MODx.LockMask),Ext.override(Ext.form.NumberField,{strictDecimalPrecision:!1,fixPrecision:function(value){const nan=Number.isNaN(value);return this.allowDecimals&&-1!==this.decimalPrecision&&!nan&&value?this.allowDecimals&&this.strictDecimalPrecision?parseFloat(value).toFixed(this.decimalPrecision):parseFloat(parseFloat(value).toFixed(this.decimalPrecision)):nan?"":value}}),Ext.override(Ext.form.BasicForm,{clearDirty:function(nodeToRecurse){(nodeToRecurse=nodeToRecurse||this)?.items?.each?.((function(field){field.getValue&&(field.items?this.clearDirty(field):field.originalValue!==field.getValue()&&(field.originalValue=field.getValue()))}),this)}}),MODx.StaticTextField=Ext.extend(Ext.form.TextField,{fieldClass:"x-static-text-field",onRender:function(){this.readOnly=!0,this.disabled=!this.initialConfig.submitValue,MODx.StaticTextField.superclass.onRender.apply(this,arguments)}}),Ext.reg("statictextfield",MODx.StaticTextField),MODx.StaticTextArea=Ext.extend(Ext.form.TextArea,{fieldClass:"x-static-text-field",onRender:function(){this.readOnly=!0,this.disabled=!this.initialConfig.submitValue,MODx.StaticTextArea.superclass.onRender.apply(this,arguments)}}),Ext.reg("statictextarea",MODx.StaticTextArea),MODx.StaticBoolean=Ext.extend(Ext.form.TextField,{fieldClass:"x-static-text-field",onRender:function(tf){this.readOnly=!0,this.disabled=!this.initialConfig.submitValue,MODx.StaticBoolean.superclass.onRender.apply(this,arguments),this.on("change",this.onChange,this)},setValue:function(v){1===v?(this.addClass("green"),v=_("yes")):(this.addClass("red"),v=_("no")),MODx.StaticBoolean.superclass.setValue.apply(this,arguments)}}),Ext.reg("staticboolean",MODx.StaticBoolean),MODx.util.safeHtml=(input,allowedTags,allowedAttributes)=>{const tags=/<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,attributes=/([a-z][a-z0-9]*)\s*=\s*".*?"/gi,strip=(string,allowedTagsDef,allowedAttrDef)=>string.replace(tags,((match,group1)=>allowedTagsDef.indexOf(`<${group1.toLowerCase()}>`)>-1?match:"")).replace(attributes,((match,group1)=>allowedAttrDef.indexOf(`${group1.toLowerCase()},`)>-1?match:""));let length;allowedTags=(`${allowedTags||"
    "}`.toLowerCase().match(/<[a-z][a-z0-9]*>/g)||[]).join(""),allowedAttributes=(`${allowedAttributes||"href,class"}`.toLowerCase().match(/[a-z\-,]*/g)||[]).join("").concat(","),input=input.replace(/|<\?(?:php)?[\s\S]*?\?>/gi,"").replace(/href(\s*?=\s*?(["'])javascript:.*?\2|\s*?=\s*?javascript:.*?(?![^> ]))/gi,'href="javascript:void(0)"');do{length=input.length,input=strip(input,allowedTags,allowedAttributes)}while(length!==input.length);return input.replace(/on([a-z][a-z0-9]*\s*=)/gi,"on​$1")},Ext.override(Ext.form.Checkbox,{setBoxLabel:function(boxLabel){this.boxLabel=boxLabel,this.rendered&&this.wrap.child(".x-form-cb-label").update(boxLabel)}});const FieldSetOnRender=Ext.form.FieldSet.prototype.onRender;Ext.override(Ext.form.FieldSet,{onRender:function(ct,position){if(FieldSetOnRender.call(this,ct,position),this.checkboxToggle){const trigger=this.el.dom.getElementsByClassName(this.headerTextCls)[0],elem=this;trigger&&trigger.addEventListener("click",(e=>{elem.checkbox.dom.click(e)}),!1)}}}),Array.prototype.in_array=function(value){for(let i=0,l=this.length;i0){this.items.addAll(fields);for(let f=0;f`,elbowMarkup=n.attributes.pseudoroot?'':'',checkboxMarkup=hasCheckbox?'':">"):"",targetMarkup=a.hrefTarget?`target="${a.hrefTarget}"`:"",buf=['
  • ',`",'',"
  • "].join("");let nel;!0!==bulkRender&&n.nextSibling&&(nel=n.nextSibling.ui.getEl())?this.wrap=Ext.DomHelper.insertHtml("beforeBegin",nel,buf):this.wrap=Ext.DomHelper.insertHtml("beforeEnd",targetNode,buf),this.elNode=this.wrap.childNodes[0],this.ctNode=this.wrap.childNodes[1];const cs=this.elNode.childNodes;this.indentNode=cs[0],this.ecNode=cs[1],this.iconNode=cs[2];let index=3;hasCheckbox&&(this.checkbox=cs[3],index++),this.anchor=cs[index],this.textNode=cs[index].firstChild},renderItemText:function(item){return Ext.util.Format.htmlEncode(item.text)},getChildIndent:function(){if(!this.childIndent){const buf=[];let p=this.node;for(;p;)(!p.isRoot||p.isRoot&&p.ownerTree.rootVisible)&&!p.attributes.pseudoroot&&(p.isLast()?buf.unshift(``):buf.unshift(``)),p=p.parentNode;this.childIndent=buf.join("")}return this.childIndent}}),Ext.override(Ext.form.Action.Submit,{handleResponse:function(response){const messageData=Ext.decode(response.responseText);if(this.form.errorReader){const responseData=this.form.errorReader.read(response),errors=[];if(responseData.records)for(let i=0,len=responseData.records.length;i0))return defaultValue;10===timestamp.toString().length&&(timestamp*=1e3);let format=[];return!0===date&&format.push(MODx.config.manager_date_format),!0===time&&format.push(MODx.config.manager_time_format),0===format.length?defaultValue:(format=format.join(" "),new Date(timestamp).format(format))},trimCharacters:function(string,charList="",direction="both"){if(charList.length){const trimLeft={find:new RegExp(`^([${charList}]+)([^${charList}]?)(.*)`,"g"),replace:"$2$3"},trimRight={find:new RegExp(`(.*)([^${charList}]+)([${charList}]+)$`,"g"),replace:"$1$2"};switch(direction){case"both":return string.replace(trimLeft.find,trimLeft.replace).replace(trimRight.find,trimRight.replace);case"left":return string.replace(trimLeft.find,trimLeft.replace);case"right":return string.replace(trimRight.find,trimRight.replace)}}return string},trimAndCollapseSpace:function(value){return"string"!=typeof value||Ext.isEmpty(value)?value:value.trim().replace(/\s{2,}/," ")},trimCharSeparatedList:function(list,separator=",",padListItems=!0){let formattedList=this.trimCharacters(list,`${separator}\\s`);return formattedList=this.trimAndCollapseSpace(formattedList),formattedList=formattedList.replace(new RegExp(`\\s*${separator}\\s*`,"g"),separator).replace(new RegExp(`[${separator}]{2,}`,"g"),separator),padListItems?formattedList.replaceAll(separator,`${separator} `):formattedList},firstToUpperCase:function(string){return"string"==typeof string&&string.length>0?string.charAt(0).toUpperCase()+string.substring(1):string}},MODx.util.getHeaderBreadCrumbs=function(header,trail){return"string"==typeof header&&(header={id:header,xtype:"modx-header"}),void 0===trail&&(trail=[]),Array.isArray(trail)||(trail=[trail]),{xtype:"modx-breadcrumbs-panel",id:"modx-header-breadcrumbs",cls:"modx-header-breadcrumbs",desc:"",bdMarkup:'',init:function(){this.tpl=new Ext.XTemplate(this.bdMarkup,{compiled:!0})},trail,listeners:{afterrender:function(){this.renderTrail()}},renderTrail:function(){this.tpl.overwrite(this.body.dom.lastElementChild,{trail:this.trail})},updateTrail:function(trail,replace){if(void 0===replace&&(replace=!1),!0===replace)return this.trail=Array.isArray(trail)?trail:[trail],this.renderTrail(),!0;if(Array.isArray(trail)){for(let i=0;i{params.set(param,value)}));const newUrl=url.toString().replace(/%2F/g,"/");window.history.replaceState(stateData,document.title,newUrl)}},clearAllParams:function(stateData={}){if(void 0!==window.history.replaceState){const preserve=["a","id","key","namespace"],preserved=[],urlParts=window.location.href.split("?");urlParts[1].split("&").forEach((param=>{const paramName=param.split("=")[0];preserve.includes(paramName)&&preserved.push(param)}));let newUrl=new URL(`${urlParts[0]}?${preserved.join("&")}`);newUrl=newUrl.toString().replace(/%2F/g,"/"),window.history.replaceState(stateData,document.title,newUrl)}},clearParam:function(reference,referenceIsComponent=!0,stateData={}){if(void 0!==window.history.replaceState){let removeParamName,url=new URL(window.location.href);referenceIsComponent?(removeParamName=this.getParamNameFromCmp(reference),removeParamName="namespace"===removeParamName?"ns":removeParamName):removeParamName=reference.trim(),url.searchParams.delete(removeParamName),url=url.toString().replace(/%2F/g,"/"),window.history.replaceState(stateData,document.title,url)}},getParamNameFromCmp:function(cmp){const param=cmp.itemId.split("-")[1];return"ns"===param?"namespace":param},getParamValue:function(param,setEmptyToString=!1){const key="namespace"===param?"ns":param,emptyValue=setEmptyToString?"":null;return MODx.request[key]?this.decodeParamValue(MODx.request[key]):emptyValue},decodeParamValue:function(value){return value=value.replace(/\+/g," "),decodeURIComponent(value)}},MODx.util.tree={getGroupIdFromNode:function(node){return node.id?node.id.split("_").pop():0}},Ext.util.Format.trimCommas=function(s){const len=(s=s.replace(",,",",")).length;return","===s.substr(len-1,1)&&(s=s.substring(0,len-1)),","===s.substr(0,1)&&(s=s.substring(1)),","===s&&(s=""),s},Ext.ns("Ext.ux.grid"),"function"!=typeof RegExp.escape&&(RegExp.escape=function(s){return"string"!=typeof s?s:s.replace(/([.*+?\^=!:${}()|\[\]\/\\])/g,"\\$1")}),Ext.ux.grid.RowActions=function(a){Ext.apply(this,a),this.addEvents("beforeaction","action","beforegroupaction","groupaction"),Ext.ux.grid.RowActions.superclass.constructor.call(this)},Ext.extend(Ext.ux.grid.RowActions,Ext.util.Observable,{actionEvent:"click",autoWidth:!0,dataIndex:"",editable:!1,header:"",isColumn:!0,keepSelection:!1,menuDisabled:!0,sortable:!1,tplGroup:'
    ux-action-right {cls}" style="{style}" qtip="{qtip}">{text}
    ',tplRow:'
    ux-row-action-text" style="{hide}{style}" qtip="{qtip}">{text}
    ',hideMode:"visibility",widthIntercept:4,widthSlope:21,init:function(g){this.grid=g,this.id=this.id||Ext.id();const h=g.getColumnModel().lookup;delete h[void 0],h[this.id]=this,this.tpl||(this.tpl=this.processActions(this.actions)),this.autoWidth&&(this.width=this.widthSlope*this.actions.length+this.widthIntercept,this.fixed=!0);const i=g.getView(),j={scope:this};j[this.actionEvent]=this.onClick,g.afterRender=g.afterRender.createSequence((function(){i.mainBody.on(j),g.on("destroy",this.purgeListeners,this)}),this),this.renderer||(this.renderer=function(a,b,c,d,e,f){return b.css+=(b.css?" ":"")+"ux-row-action-cell",this.tpl.apply(this.getData(a,b,c,d,e,f))}.createDelegate(this)),i.groupTextTpl&&this.groupActions&&(i.interceptMouse=i.interceptMouse.createInterceptor((function(e){if(e.getTarget(".ux-grow-action-item"))return!1})),i.groupTextTpl=`
    ${i.groupTextTpl}
    ${this.processActions(this.groupActions,this.tplGroup).apply()}`),!0===this.keepSelection&&(g.processEvent=g.processEvent.createInterceptor((function(a,e){if("mousedown"===a)return!this.getAction(e)}),this))},getData:function(a,b,c,d,e,f){return c.data||{}},processActions:function(b,c){const d=[];Ext.each(b,(function(a,i){a.iconCls&&"function"==typeof(a.callback||a.cb)&&(this.callbacks=this.callbacks||{},this.callbacks[a.iconCls]=a.callback||a.cb);const o={cls:a.iconIndex?`{${a.iconIndex}}`:a.iconCls?a.iconCls:"",qtip:a.qtipIndex?`{${a.qtipIndex}}`:a.tooltip||a.qtip?a.tooltip||a.qtip:"",text:a.textIndex?`{${a.textIndex}}`:a.text?a.text:"",hide:a.hideIndex?`${"display"===this.hideMode?"display:none":"visibility:hidden"};`:a.hide?"display"===this.hideMode?"display:none":"visibility:hidden;":"",align:a.align||"right",style:a.style?a.style:""};d.push(o)}),this);const e=new Ext.XTemplate(c||this.tplRow);return new Ext.XTemplate(e.apply({actions:d}))},getAction:function(e){let a=!1;const t=e.getTarget(".ux-row-action-item");return t&&(a=t.className.replace(/ux-row-action-item /,""),a&&(a=a.replace(/ ux-row-action-text/,""),a=a.trim())),a},onClick:function(e,a){const b=this.grid.getView(),c=e.getTarget(".x-grid3-row"),d=b.findCellIndex(a.parentNode.parentNode);let f=this.getAction(e);if(!1!==c&&!1!==d&&!1!==f){const g=this.grid.store.getAt(c.rowIndex);if(this.callbacks&&"function"==typeof this.callbacks[f]&&this.callbacks[f](this.grid,g,f,c.rowIndex,d),!0!==this.eventsSuspended&&!1===this.fireEvent("beforeaction",this.grid,g,f,c.rowIndex,d))return;!0!==this.eventsSuspended&&this.fireEvent("action",this.grid,g,f,c.rowIndex,d)}const t=e.getTarget(".ux-grow-action-item");if(t){const h=b.findGroup(a),i=h?h.id.replace(/ext-gen[0-9]+-gp-/,""):null;let j;if(i){const k=new RegExp(RegExp.escape(i));j=this.grid.store.queryBy((function(r){return r._groupId.match(k)})),j=j?j.items:[]}if(f=t.className.replace(/ux-grow-action-item (ux-action-right )*/,""),"function"==typeof this.callbacks[f]&&this.callbacks[f](this.grid,j,f,i),!0!==this.eventsSuspended&&!1===this.fireEvent("beforegroupaction",this.grid,j,f,i))return!1;this.fireEvent("groupaction",this.grid,j,f,i)}}}),Ext.reg("rowactions",Ext.ux.grid.RowActions),Ext.SwitchButton=Ext.extend(Ext.Component,{initComponent:function(){Ext.SwitchButton.superclass.initComponent.call(this);const mc=new Ext.util.MixedCollection;mc.addAll(this.items),this.items=mc,this.addEvents("change"),this.handler&&this.on("change",this.handler,this.scope||this)},onRender:function(ct,position){const el=document.createElement("table");el.cellSpacing=0,el.className="x-rbtn",el.id=this.id;const row=document.createElement("tr");el.appendChild(document.createElement("tbody")).appendChild(row);const count=this.items.length,last=count-1;this.activeItem=this.items.get(this.activeItem);for(let i=0;idata.rowIndex&&this.rowPosition<0&&rindex--,rindex0&&rindex++,rindex>data.rowIndex&&data.selections.length>1&&(rindex-=data.selections.length-1),rindex===data.rowIndex)return!1;if(!self.copy)for(let i=0;i=0;i--){const insertIndex=rindex;ds.insert(insertIndex,selections[i])}const sm=this.grid.getSelectionModel();return sm&&sm.selectRecords(data.selections),this.gridDropTarget.fireEvent(self.copy?"afterrowcopy":"afterrowmove",this.gridDropTarget,data.rowIndex,rindex,data.selections),!0},notifyOver:function(dd,e,data){const target=Ext.lib.Event.getTarget(e),ds=this.grid.getStore(),{keys}=ds.data;let rindex=this.grid.getView().findRowIndex(target);for(const key in keys)for(let i=0;i0)this.currentRowEl=new Ext.Element(currentRow),this.currentRowEl.addClass("grid-row-insert-below");else if(rindex-1>=0){const previousRow=this.grid.getView().getRow(rindex-1);this.currentRowEl=new Ext.Element(previousRow),this.currentRowEl.addClass("grid-row-insert-below")}else this.currentRowEl.addClass("grid-row-insert-above")}catch(err){console.warn(err),rindex=!1}return!1===rindex?this.dropNotAllowed:this.dropAllowed},notifyOut:function(dd,e,data){this.currentRowEl&&(this.currentRowEl.removeClass("grid-row-insert-above"),this.currentRowEl.removeClass("grid-row-insert-below"))}}),this.targetCfg&&Ext.apply(this.target,this.targetCfg),this.scrollable&&(Ext.dd.ScrollManager.register(grid.getView().getEditorParent()),grid.on({beforedestroy:this.onBeforeDestroy,scope:this,single:!0}))},getTarget:function(){return this.target},getGrid:function(){return this.grid},getCopy:function(){return this.copy},setCopy:function(copy){this.copy=copy},onBeforeDestroy:function(grid){Ext.dd.ScrollManager.unregister(grid.getView().getEditorParent())}}),Ext.grid.GridView.prototype.templates||(Ext.grid.GridView.prototype.templates={}),Ext.grid.GridView.prototype.templates.cell=new Ext.Template('','
    {value}
    ',""),MODx.grid||(MODx.grid={}),MODx.grid.ComboColumn=Ext.extend(Ext.grid.Column,{gridId:void 0,constructor:function(cfg){MODx.grid.ComboColumn.superclass.constructor.call(this,cfg),this.renderer=this.editor&&this.editor.triggerAction?MODx.grid.ComboBoxRenderer(this.editor,this.gridId,cfg.renderer):function(value){return value}}}),Ext.grid.Column.types.combocolumn=MODx.grid.ComboColumn,MODx.grid.ComboBoxRenderer=function(combo,gridId,currentRenderer){return function(value,metaData,record,rowIndex,colIndex,store){if(currentRenderer){if("function"==typeof currentRenderer.fn){const scope=!!currentRenderer.scope&¤tRenderer.scope;currentRenderer=currentRenderer.fn.bind(scope)}"function"==typeof currentRenderer&&(value=currentRenderer(value,metaData,record,rowIndex,colIndex,store))}return 0===combo.store.getCount()&&gridId?(combo.store.on("load",(function(){const grid=Ext.getCmp(gridId);grid&&grid.getView().refresh()}),this,{single:!0}),value):(value=>{const idx=combo.store.find(combo.valueField,value),record=combo.store.getAt(idx);return record?record.get(combo.displayField):value})(value)}},Ext.Button.buttonTemplate=new Ext.Template(''),Ext.Button.buttonTemplate.compile(),Ext.TabPanel.prototype.itemTpl=new Ext.Template('
  • ','{text}
  • '),Ext.TabPanel.prototype.itemTpl.disableFormats=!0,Ext.TabPanel.prototype.itemTpl.compile(),Ext.namespace("Ext.ux.form"),Ext.ux.form.CheckboxGroup=Ext.extend(Ext.form.CheckboxGroup,{aggregateSubmitField:{},initComponent:function(){const me=this,ct=this.ownerCt;"string"==typeof this.name&&this.name.length>0?(this.aggregateSubmitField=new Ext.form.Hidden({name:this.name}),Ext.ux.form.CheckboxGroup.superclass.initComponent.call(this),this.cls="string"==typeof this.cls&&this.cls.length>0?`aggregated-group ${this.cls}`:"aggregated-group",Ext.each(this.items,(function(item){if("string"==typeof me.value&&me.value.length>0){me.value.split(",").find((function(v){return v===item.inputValue}))===item.inputValue&&(item.checked=!0),me.aggregateSubmitField.setValue(me.value)}item.listeners={check:{fn:me.setHiddenSubmit,scope:me}},item.submitValue=!1})),ct.add(this.aggregateSubmitField)):console.warning("Ext.ux.form.CheckboxGroup: A name must be specified in this component’s config for its values to be saved.",this)},setHiddenSubmit:function(){const groupOpts=this.items.items,vals=[];Ext.each(groupOpts,(function(item){item.checked&&vals.push(item.inputValue)})),this.aggregateSubmitField.setValue(vals.join(","))}}),Ext.reg("xcheckboxgroup",Ext.ux.form.CheckboxGroup),Ext.define("AddFieldUtilities.plugin.Class",{alias:"plugin.fieldutilities",init:function(cmp){cmp.on("afterrender",this.afterRender,cmp)},afterRender:function(){const me=this;this.label.createChild({tag:"a",title:_("field_reset"),cls:"modx-field-utils modx-field-reset"}).on("click",(function(){me.reset()}),me),this.label.createChild({tag:"a",title:_("field_clear"),cls:"modx-field-utils modx-field-clear"}).on("click",(function(){switch(this.xtype){case"xcheckboxgroup":case"checkboxgroup":Ext.isArray(this.items.items)&&(Ext.each(this.items.items,(function(item){item.setValue(!1)})),this.doLayout());break;case"checkbox":case"radio":me.setValue(!1);break;default:me.setValue("")}}),me)}}),MODx.util.FileDownload=function(fields){if(!Ext.isObject(fields))return;let polling=10*fields.timeout||300;const me=this,cookieName=`fileDownload${me.randomHex(16)}`,ident=fields.ident||`filedownload-${Ext.id()}`,url=fields.url||MODx.config.connector_url,params=fields.params||{},debug=fields.debug||!1,successCallback=fields.success||null,failureCallback=fields.failure||null,body=Ext.getBody(),frame=body.createChild({tag:"iframe",cls:"x-hidden",id:`${ident}-iframe`,name:`${ident}-iframe`}),form=body.createChild({tag:"form",cls:"x-hidden",id:`${ident}-form`,action:url,target:`${ident}-iframe`,method:"post"});me.clearCookie=function(){Ext.util.Cookies.set(cookieName,null,new Date("January 1, 1970"),"/"),Ext.util.Cookies.clear(cookieName,"/")},me.randomHex=function(len){const hex="0123456789ABCDEF";let output="";for(let i=0;i0){let result=Ext.decode(frame.dom.contentDocument.body.innerHTML);return result=result||{success:!1,message:_("file_msg_download_error")},me.clearCookie(),failureCallback&&failureCallback(result),void(frame.dom.contentDocument.body.innerHTML="")}}catch(e){console.log(e)}polling?(debug&&console.log(`polling ${polling}`),window.setTimeout((function(){polling--,me.isFinished(successCallback,failureCallback)}),100)):(me.clearCookie(),failureCallback&&failureCallback({success:!1,message:_("file_err_download_timeout")}))},params.HTTP_MODAUTH=MODx.siteId,"function"==typeof successCallback&&(params.cookieName=cookieName),Ext.iterate(params,(function(name,value){form.createChild({tag:"input",type:"text",cls:"x-hidden",id:`${ident}-${name}`,name,value})})),form.dom.submit(),(successCallback||failureCallback)&&me.isFinished(successCallback,failureCallback)},Ext.override(Ext.form.TimeField,{initDate:"2/1/2008"}),Ext.ns("Ext.ux.form"),Ext.ux.form.DateTime=Ext.extend(Ext.form.Field,{dateValidator:null,defaultAutoCreate:{tag:"input",type:"hidden"},dtSeparator:" ",hiddenFormat:"Y-m-d H:i:s",otherToNow:!0,timePosition:"right",timeValidator:null,timeWidth:100,dateFormat:"m/d/y",timeFormat:"g:i A",maxDateValue:"",minDateValue:"",timeIncrement:15,maxTimeValue:null,minTimeValue:null,disabledDates:null,hideTime:!1,initComponent:function(){Ext.ux.form.DateTime.superclass.initComponent.call(this),this.hasOwnProperty("offset_time")&&!isNaN(this.offset_time)||(this.offset_time=0);var dateConfig=Ext.apply({},{id:this.id+"-date",format:this.dateFormat||Ext.form.DateField.prototype.format,width:this.timeWidth,selectOnFocus:this.selectOnFocus,validator:this.dateValidator,disabledDates:this.disabledDates||null,disabledDays:this.disabledDays||[],showToday:this.showToday||!0,maxValue:this.maxDateValue||"",minValue:this.minDateValue||"",startDay:this.startDay||0,allowBlank:this.allowBlank,msgTarget:this.msgTarget,listeners:{blur:{scope:this,fn:this.onBlur},focus:{scope:this,fn:this.onFocus}}},this.dateConfig);this.df=new Ext.form.DateField(dateConfig),this.df.ownerCt=this,delete this.dateFormat,delete this.disabledDates,delete this.disabledDays,delete this.maxDateValue,delete this.minDateValue,delete this.startDay;var timeConfig=Ext.apply({},{id:this.id+"-time",format:this.timeFormat||Ext.form.TimeField.prototype.format,width:this.timeWidth,selectOnFocus:this.selectOnFocus,validator:this.timeValidator,increment:this.timeIncrement||15,maxValue:this.maxTimeValue||null,minValue:this.minTimeValue||null,hidden:this.hideTime,allowBlank:this.allowBlank,msgTarget:this.msgTarget,listeners:{blur:{scope:this,fn:this.onBlur},focus:{scope:this,fn:this.onFocus}}},this.timeConfig);this.tf=new Ext.form.TimeField(timeConfig),this.tf.ownerCt=this,delete this.timeFormat,delete this.maxTimeValue,delete this.minTimeValue,delete this.timeIncrement,this.relayEvents(this.df,["focus","specialkey","invalid","valid"]),this.relayEvents(this.tf,["focus","specialkey","invalid","valid"]),this.on("specialkey",this.onSpecialKey,this)},onRender:function(ct,position){if(!this.isRendered){var t;switch(Ext.ux.form.DateTime.superclass.onRender.call(this,ct,position),t="below"===this.timePosition||"bellow"===this.timePosition?Ext.DomHelper.append(ct,{tag:"table",style:"border-collapse:collapse",children:[{tag:"tr",children:[{tag:"td",style:"padding-bottom:1px",cls:"ux-datetime-date"}]},{tag:"tr",children:[{tag:"td",cls:"ux-datetime-time"}]}]},!0):Ext.DomHelper.append(ct,{tag:"table",style:"border-collapse:collapse",children:[{tag:"tr",children:[{tag:"td",style:"padding-right:4px",cls:"ux-datetime-date"},{tag:"td",cls:"ux-datetime-time"}]}]},!0),this.tableEl=t,this.wrap=t.wrap({cls:"x-form-field-wrap x-datetime-wrap"}),this.wrap.on("mousedown",this.onMouseDown,this,{delay:10}),this.df.render(t.child("td.ux-datetime-date")),this.tf.render(t.child("td.ux-datetime-time")),this.df.el.swallowEvent(["keydown","keypress"]),this.tf.el.swallowEvent(["keydown","keypress"]),this.msgTarget){case"side":const elp=this.el.findParent(".x-form-element",10,!0);elp&&(this.errorIcon=elp.createChild({cls:"x-form-invalid-icon"}));const o={errorIcon:this.errorIcon,msgTarget:"side",alignErrorIcon:this.alignErrorIcon.createDelegate(this)};Ext.apply(this.df,o),Ext.apply(this.tf,o);break;case"under":const dateMsgElId=`ux-datetime-date-msg-${this.itemId}`,dateMsgWidth=Math.ceil(this.dateWidth-30),dateMsgEl=Ext.DomHelper.append(this.df.container,{tag:"div",cls:"x-form-invalid-msg",style:`display: none; width: ${dateMsgWidth}px;`,id:dateMsgElId}),timeMsgElId=`ux-datetime-time-msg-${this.itemId}`,timeMsgWidth=Math.ceil(this.timeWidth-30),timeMsgEl=Ext.DomHelper.append(this.tf.container,{tag:"div",cls:"x-form-invalid-msg",style:`display: none; width: ${timeMsgWidth}px;`,id:timeMsgElId});this.df.container.appendChild(dateMsgEl),this.tf.container.appendChild(timeMsgEl),this.df.msgTarget=dateMsgElId,this.tf.msgTarget=timeMsgElId}this.el.dom.name=this.hiddenName||this.name||this.id,this.df.el.dom.removeAttribute("name"),this.tf.el.dom.removeAttribute("name"),this.isRendered=!0,this.updateHidden()}},adjustSize:Ext.BoxComponent.prototype.adjustSize,alignErrorIcon:function(){this.errorIcon.alignTo(this.tableEl,"tl-tr",[2,0])},initDateValue:function(){this.dateValue=this.otherToNow?new Date:new Date(1970,0,1,0,0,0)},clearInvalid:function(){this.df.clearInvalid(),this.tf.clearInvalid()},markInvalid:function(msg){this.df.markInvalid(msg),this.tf.markInvalid(msg)},beforeDestroy:function(){this.isRendered&&(this.wrap.removeAllListeners(),this.wrap.remove(),this.tableEl.remove(),this.df.destroy(),this.tf.destroy())},disable:function(){return this.isRendered&&(this.df.disabled=this.disabled,this.df.onDisable(),this.tf.onDisable()),this.disabled=!0,this.df.disabled=!0,this.tf.disabled=!0,this.fireEvent("disable",this),this},enable:function(){return this.rendered&&(this.df.onEnable(),this.tf.onEnable()),this.disabled=!1,this.df.disabled=!1,this.tf.disabled=!1,this.fireEvent("enable",this),this},focus:function(){this.df.focus()},getPositionEl:function(){return this.wrap},getResizeEl:function(){return this.wrap},getValue:function(){return this.dateValue?new Date(this.dateValue):""},isValid:function(){return this.df.isValid()&&this.tf.isValid()},isVisible:function(){return this.df.rendered&&this.df.getActionEl().isVisible()},onBlur:function(f){this.wrapClick&&(f.focus(),this.wrapClick=!1),f===this.df?this.updateDate():this.updateTime(),this.updateHidden(),this.validate(),function(){if(!this.df.hasFocus&&!this.tf.hasFocus){var v=this.getValue();String(v)!==String(this.startValue)&&this.fireEvent("change",this,v,this.startValue),this.hasFocus=!1,this.fireEvent("blur",this)}}.defer(100,this)},onFocus:function(){this.hasFocus||(this.hasFocus=!0,this.startValue=this.getValue(),this.fireEvent("focus",this))},onMouseDown:function(e){this.disabled||(this.wrapClick="td"===e.target.nodeName.toLowerCase())},onSpecialKey:function(t,e){var key=e.getKey();key===e.TAB&&(t!==this.df||e.shiftKey||(this.onBlur(t),e.stopEvent(),this.tf.focus()),t===this.tf&&e.shiftKey&&(this.onBlur(t),e.stopEvent(),this.df.focus()),this.updateValue()),key===e.ENTER&&this.updateValue()},reset:function(){this.df.setValue(this.originalValue),this.tf.setValue(this.originalValue)},setDate:function(date){date&&0!=this.offset_time&&(date=date.add(Date.MINUTE,60*new Number(this.offset_time))),this.df.setValue(date)},setTime:function(date){date&&0!=this.offset_time&&(date=date.add(Date.MINUTE,60*new Number(this.offset_time))),this.tf.setValue(date)},setSize:function(w,h){w&&("below"===this.timePosition?(this.df.setSize(w,h),this.tf.setSize(w,h),Ext.isIE&&(this.df.el.up("td").setWidth(w),this.tf.el.up("td").setWidth(w))):(this.df.setSize(w-this.timeWidth-4,h),this.tf.setSize(this.timeWidth,h),Ext.isIE&&(this.df.el.up("td").setWidth(w-this.timeWidth-4),this.tf.el.up("td").setWidth(this.timeWidth))))},setValue:function(val){if(val||!0!==this.emptyToNow){if(!val)return this.setDate(""),this.setTime(""),void this.updateValue();var da;"number"==typeof val?val=new Date(val):"string"==typeof val&&this.hiddenFormat&&(val=Date.parseDate(val,this.hiddenFormat)),(val=val||new Date(1970,0,1,0,0,0))instanceof Date?(this.setDate(val),this.setTime(val),this.dateValue=new Date(Ext.isIE?val.getTime():val)):(da=val.split(this.dtSeparator),this.setDate(da[0]),da[1]&&(da[2]&&(da[1]+=da[2]),this.setTime(da[1]))),this.updateValue()}else this.setValue(new Date)},setVisible:function(visible){return visible?(this.df.show(),this.tf.show()):(this.df.hide(),this.tf.hide()),this},show:function(){return this.setVisible(!0)},hide:function(){return this.setVisible(!1)},updateDate:function(){var d=this.df.getValue();d?(this.dateValue instanceof Date||(this.initDateValue(),this.tf.getValue()||this.setTime(this.dateValue)),this.dateValue.setMonth(0),this.dateValue.setFullYear(d.getFullYear()),this.dateValue.setMonth(d.getMonth(),d.getDate())):(this.dateValue="",this.setTime(""))},updateTime:function(){let t=this.tf.getValue();!t||t instanceof Date||(t=Date.parseDate(t,this.tf.format)),t&&!this.df.getValue()&&(this.initDateValue(),this.setDate(this.dateValue)),this.dateValue instanceof Date&&(t&&!this.hideTime?(this.dateValue.setHours(t.getHours()),this.dateValue.setMinutes(t.getMinutes()),this.dateValue.setSeconds(t.getSeconds())):(this.dateValue.setHours(0),this.dateValue.setMinutes(0),this.dateValue.setSeconds(0)))},updateHidden:function(){if(this.isRendered){var value="";this.dateValue instanceof Date&&(value=this.dateValue.add(Date.MINUTE,0-60*new Number(this.offset_time)).format(this.hiddenFormat)),this.el.dom.value=value}},updateValue:function(){this.updateDate(),this.updateTime(),this.updateHidden()},validate:function(){return this.df.validate()&&this.tf.validate()},renderer:function(field){var format=field.editor.dateFormat||Ext.ux.form.DateTime.prototype.dateFormat;return format+=" "+(field.editor.timeFormat||Ext.ux.form.DateTime.prototype.timeFormat),function(val){return Ext.util.Format.date(val,format)}}}),Ext.reg("xdatetime",Ext.ux.form.DateTime),Ext.namespace("Ext.ux.Utils"),Ext.ux.Utils.EventQueue=function(handler,scope){if(!handler)throw"Handler is required.";this.handler=handler,this.scope=scope||window,this.queue=[],this.is_processing=!1,this.postEvent=function(event,data){data=data||null,this.queue.push({event,data}),this.is_processing||this.process()},this.flushEventQueue=function(){this.queue=[]},this.process=function(){for(;this.queue.length>0;){this.is_processing=!0;var event_data=this.queue.shift();this.handler.call(this.scope,event_data.event,event_data.data)}this.is_processing=!1}},Ext.ux.Utils.FSA=function(initial_state,trans_table,trans_table_scope){this.current_state=initial_state,this.trans_table=trans_table||{},this.trans_table_scope=trans_table_scope||window,Ext.ux.Utils.FSA.superclass.constructor.call(this,this.processEvent,this)},Ext.extend(Ext.ux.Utils.FSA,Ext.ux.Utils.EventQueue,{current_state:null,trans_table:null,trans_table_scope:null,state:function(){return this.current_state},processEvent:function(event,data){var transitions=this.currentStateEventTransitions(event);if(!transitions)throw"State '"+this.current_state+"' has no transition for event '"+event+"'.";for(var i=0,len=transitions.length;i ").compile()},createForm:function(){this.form=Ext.DomHelper.append(this.body,{tag:"form",method:"post",action:this.url,style:"position: absolute; left: -100px; top: -100px; width: 100px; height: 100px; clear: both;"})},createProgressBar:function(){this.progress_bar=this.add(new Ext.ProgressBar({x:0,y:0,anchor:"0",value:0,text:this.i18n.progress_waiting_text}))},createGrid:function(){var store=new Ext.data.Store({proxy:new Ext.data.MemoryProxy([]),reader:new Ext.data.JsonReader({},Ext.ux.UploadDialog.FileRecord),sortInfo:{field:"state",direction:"DESC"},pruneModifiedRecords:!0}),cm=new Ext.grid.ColumnModel([{header:this.i18n.state_col_title,width:this.i18n.state_col_width,resizable:!1,dataIndex:"state",sortable:!0,renderer:this.renderStateCell.createDelegate(this)},{header:this.i18n.filename_col_title,width:this.i18n.filename_col_width,dataIndex:"filename",sortable:!0,renderer:this.renderFilenameCell.createDelegate(this)},{header:this.i18n.note_col_title,width:this.i18n.note_col_width,dataIndex:"note",sortable:!0,renderer:this.renderNoteCell.createDelegate(this)}]);this.grid_panel=new Ext.grid.GridPanel({ds:store,cm,layout:"fit",height:this.height-100,region:"center",x:0,y:22,border:!0,viewConfig:{autoFill:!0,forceFit:!0},bbar:new Ext.Toolbar}),this.grid_panel.on("render",this.onGridRender,this),this.add(this.grid_panel),this.grid_panel.getSelectionModel().on("selectionchange",this.onGridSelectionChange,this)},fillToolbar:function(){var tb=this.grid_panel.getBottomToolbar();tb.x_buttons={},tb.x_buttons.add=tb.addItem(new Ext.ux.UploadDialog.TBBrowseButton({input_name:this.post_var_name,text:this.i18n.add_btn_text,tooltip:this.i18n.add_btn_tip,iconCls:"ext-ux-uploaddialog-addbtn",handler:this.onAddButtonFileSelected,scope:this})),tb.x_buttons.remove=tb.addButton({text:this.i18n.remove_btn_text,tooltip:this.i18n.remove_btn_tip,iconCls:"ext-ux-uploaddialog-removebtn",handler:this.onRemoveButtonClick,scope:this}),tb.x_buttons.reset=tb.addButton({text:this.i18n.reset_btn_text,tooltip:this.i18n.reset_btn_tip,iconCls:"ext-ux-uploaddialog-resetbtn",handler:this.onResetButtonClick,scope:this}),tb.x_buttons.upload=tb.addButton({text:this.i18n.upload_btn_start_text,tooltip:this.i18n.upload_btn_start_tip,iconCls:"ext-ux-uploaddialog-uploadstartbtn",handler:this.onUploadButtonClick,scope:this}),tb.x_buttons.close=tb.addButton({text:this.i18n.close_btn_text,tooltip:this.i18n.close_btn_tip,handler:this.onCloseButtonClick,scope:this})},renderStateCell:function(data,cell,record,row_index,column_index,store){return this.state_tpl.apply({state:data})},renderFilenameCell:function(data,cell,record,row_index,column_index,store){var view=this.grid_panel.getView();return function(){try{Ext.fly(view.getCell(row_index,column_index)).child(".x-grid3-cell-inner").dom.qtip=data}catch(e){}}.defer(1e3),data},renderNoteCell:function(data,cell,record,row_index,column_index,store){var view=this.grid_panel.getView();return function(){try{Ext.fly(view.getCell(row_index,column_index)).child(".x-grid3-cell-inner").dom.qtip=data}catch(e){}}.defer(1e3),data},getFileExtension:function(filename){var result=null,parts=filename.split(".");return parts.length>1&&(result=parts.pop()),result},isPermittedFileType:function(filename){var result=!0;return this.permitted_extensions.length>0&&(result=-1!=this.permitted_extensions.indexOf(this.getFileExtension(filename))),result},isPermittedFile:function(browse_btn){var result=!1,filename=browse_btn.getInputFile().dom.value;return this.isPermittedFileType(filename)?result=!0:(Ext.Msg.alert(this.i18n.error_msgbox_title,String.format(this.i18n.err_file_type_not_permitted,filename,this.permitted_extensions.join(this.i18n.permitted_extensions_join_str))),result=!1),result},fireFileTestEvent:function(browse_btn){return!1!==this.fireEvent("filetest",this,browse_btn.getInputFile().dom.value)},addFileToUploadQueue:function(browse_btn){var input_file=browse_btn.detachInputFile();input_file.appendTo(this.form),input_file.setStyle("width","100px"),input_file.dom.disabled=!0;var store=this.grid_panel.getStore(),fileApi=input_file.dom.files,filename=void 0!==fileApi?fileApi[0].name:input_file.dom.value.replace("C:\\fakepath\\","");store.add(new Ext.ux.UploadDialog.FileRecord({state:Ext.ux.UploadDialog.FileRecord.STATE_QUEUE,filename,note:this.i18n.note_queued_to_upload,input_element:input_file})),this.fsa.postEvent("file-added",input_file.dom.value)},fireFileAddEvent:function(filename){this.fireEvent("fileadd",this,filename)},updateProgressBar:function(){if(this.is_uploading){var queued=this.getQueuedCount(!0),value=1-queued/this.initial_queued_count;this.progress_bar.updateProgress(value,String.format(this.i18n.progress_uploading_text,this.initial_queued_count-queued,this.initial_queued_count))}else this.progress_bar.updateProgress(0,this.i18n.progress_waiting_text)},updateToolbar:function(){var tb=this.grid_panel.getBottomToolbar();this.is_uploading?(tb.x_buttons.remove.disable(),tb.x_buttons.reset.disable(),tb.x_buttons.upload.enable(),this.getAllowCloseOnUpload()||tb.x_buttons.close.disable(),tb.x_buttons.upload.setIconClass("ext-ux-uploaddialog-uploadstopbtn"),tb.x_buttons.upload.setText(this.i18n.upload_btn_stop_text),tb.x_buttons.upload.getEl().child(tb.x_buttons.upload.buttonSelector).dom[tb.x_buttons.upload.tooltipType]=this.i18n.upload_btn_stop_tip):(tb.x_buttons.remove.enable(),tb.x_buttons.reset.enable(),tb.x_buttons.close.enable(),tb.x_buttons.upload.setIconClass("ext-ux-uploaddialog-uploadstartbtn"),tb.x_buttons.upload.setText(this.i18n.upload_btn_start_text),this.getQueuedCount()>0?tb.x_buttons.upload.enable():tb.x_buttons.upload.disable(),this.grid_panel.getSelectionModel().hasSelection()?tb.x_buttons.remove.enable():tb.x_buttons.remove.disable(),this.grid_panel.getStore().getCount()>0?tb.x_buttons.reset.enable():tb.x_buttons.reset.disable())},saveInitialQueuedCount:function(){this.initial_queued_count=this.getQueuedCount()},incInitialQueuedCount:function(){this.initial_queued_count++},setUploadingFlag:function(){this.is_uploading=!0},resetUploadingFlag:function(){this.is_uploading=!1},prepareNextUploadTask:function(){var store=this.grid_panel.getStore(),record=null;store.each((function(r){record||r.get("state")!=Ext.ux.UploadDialog.FileRecord.STATE_QUEUE?r.get("input_element").dom.disabled=!0:record=r})),record.get("input_element").dom.disabled=!1,record.set("state",Ext.ux.UploadDialog.FileRecord.STATE_PROCESSING),record.set("note",this.i18n.note_processing),record.commit(),this.fsa.postEvent("file-upload-start",record)},fireUploadStartEvent:function(){this.fireEvent("uploadstart",this)},removeFiles:function(file_records){for(var store=this.grid_panel.getStore(),i=0,len=file_records.length;i((?:.|\n)*)<\/pre>$/i);filter&&(rt=filter[1]),json_response=Ext.util.JSON.decode(rt)}catch(e){}var data={record:options.record,response:json_response};"success"in json_response&&json_response.success?this.fsa.postEvent("file-upload-success",data):this.fsa.postEvent("file-upload-error",data)},onAjaxFailure:function(response,options){var data={record:options.record,response:{success:!1,error:this.i18n.note_upload_failed}};this.fsa.postEvent("file-upload-failed",data)},startUpload:function(){this.fsa.postEvent("start-upload")},stopUpload:function(){this.fsa.postEvent("stop-upload")},getUrl:function(){return this.url},setUrl:function(url){this.url=url},getBaseParams:function(){return this.base_params},setBaseParams:function(params){this.base_params=params},getUploadAutostart:function(){return this.upload_autostart},setUploadAutostart:function(value){this.upload_autostart=value},getMakeReload:function(){return this.Make_Reload},setMakeReload:function(value){this.Make_Reload=value},getAllowCloseOnUpload:function(){return this.allow_close_on_upload},setAllowCloseOnUpload:function(value){this.allow_close_on_upload},getResetOnHide:function(){return this.reset_on_hide},setResetOnHide:function(value){this.reset_on_hide=value},getPermittedExtensions:function(){return this.permitted_extensions},setPermittedExtensions:function(value){this.permitted_extensions=value},isUploading:function(){return this.is_uploading},isNotEmptyQueue:function(){return this.grid_panel.getStore().getCount()>0},getQueuedCount:function(count_processing){var count=0;return this.grid_panel.getStore().each((function(r){r.get("state")==Ext.ux.UploadDialog.FileRecord.STATE_QUEUE&&count++,count_processing&&r.get("state")==Ext.ux.UploadDialog.FileRecord.STATE_PROCESSING&&count++})),count},hasUnuploadedFiles:function(){return this.getQueuedCount()>0}});var p=Ext.ux.UploadDialog.Dialog.prototype;p.i18n={title:_("upload_files"),state_col_title:_("upf_state"),state_col_width:70,filename_col_title:_("upf_filename"),filename_col_width:230,note_col_title:_("upf_note"),note_col_width:150,add_btn_text:_("upf_add"),add_btn_tip:_("upf_add_desc"),remove_btn_text:_("upf_remove"),remove_btn_tip:_("upf_remove_desc"),reset_btn_text:_("upf_reset"),reset_btn_tip:_("upf_reset_desc"),upload_btn_start_text:_("upf_upload"),upload_btn_start_tip:_("upf_upload_desc"),upload_btn_stop_text:_("upf_abort"),upload_btn_stop_tip:_("upf_abort_desc"),close_btn_text:_("upf_close"),close_btn_tip:_("upf_close_desc"),progress_waiting_text:_("upf_progress_wait"),progress_uploading_text:_("upf_uploading_desc"),error_msgbox_title:_("upf_error"),permitted_extensions_join_str:",",err_file_type_not_permitted:_("upf_err_filetype"),note_queued_to_upload:_("upf_queued"),note_processing:_("upf_uploading"),note_upload_failed:_("upf_err_failed"),note_upload_success:_("upf_success"),note_upload_error:_("upf_upload_err"),note_aborted:_("upf_aborted")}, /*! * Ext JS Library 3.4.0 * Copyright(c) 2006-2011 Sencha Inc. * licensing@sencha.com * http://www.sencha.com/license */ -Ext.ns("Ext.ux.form"),Ext.ux.form.FileUploadField=Ext.extend(Ext.form.TextField,{buttonText:"Browse...",buttonOnly:!1,buttonOffset:3,readOnly:!0,autoSize:Ext.emptyFn,initComponent:function(){Ext.ux.form.FileUploadField.superclass.initComponent.call(this),this.addEvents("fileselected")},onRender:function(ct,position){Ext.ux.form.FileUploadField.superclass.onRender.call(this,ct,position),this.wrap=this.el.wrap({cls:"x-form-field-wrap x-form-fileupload-wrap"}),this.el.addClass("x-form-file-text"),this.el.dom.removeAttribute("name"),this.createFileInput();var btnCfg=Ext.applyIf(this.buttonCfg||{},{text:this.buttonText});this.button=new Ext.Button(Ext.apply(btnCfg,{renderTo:this.wrap,cls:"x-form-file-btn"+(btnCfg.iconCls?" x-btn-icon":"")})),this.buttonOnly&&(this.el.hide(),this.wrap.setWidth(this.button.getEl().getWidth())),this.bindListeners(),this.resizeEl=this.positionEl=this.wrap},bindListeners:function(){this.fileInput.on({scope:this,mouseenter:function(){this.button.addClass(["x-btn-over","x-btn-focus"])},mouseleave:function(){this.button.removeClass(["x-btn-over","x-btn-focus","x-btn-click"])},mousedown:function(){this.button.addClass("x-btn-click")},mouseup:function(){this.button.removeClass(["x-btn-over","x-btn-focus","x-btn-click"])},change:function(){var v=this.fileInput.dom.value;this.setValue(v),this.fireEvent("fileselected",this,v)}})},createFileInput:function(){this.fileInput=this.wrap.createChild({id:this.getFileInputId(),name:this.name||this.getId(),cls:"x-form-file",tag:"input",type:"file",size:1})},reset:function(){this.rendered&&(this.fileInput.remove(),this.createFileInput(),this.bindListeners()),Ext.ux.form.FileUploadField.superclass.reset.call(this)},getFileInputId:function(){return this.id+"-file"},onResize:function(w,h){if(Ext.ux.form.FileUploadField.superclass.onResize.call(this,w,h),this.wrap.setWidth(w),!this.buttonOnly){w=this.wrap.getWidth()-this.button.getEl().getWidth()-this.buttonOffset;this.el.setWidth(w)}},onDestroy:function(){Ext.ux.form.FileUploadField.superclass.onDestroy.call(this),Ext.destroy(this.fileInput,this.button,this.wrap)},onDisable:function(){Ext.ux.form.FileUploadField.superclass.onDisable.call(this),this.doDisable(!0)},onEnable:function(){Ext.ux.form.FileUploadField.superclass.onEnable.call(this),this.doDisable(!1)},doDisable:function(disabled){this.fileInput.dom.disabled=disabled,this.button.setDisabled(disabled)},preFocus:Ext.emptyFn,alignErrorIcon:function(){this.errorIcon.alignTo(this.wrap,"tl-tr",[2,0])}}),Ext.reg("fileuploadfield",Ext.ux.form.FileUploadField),Ext.form.FileUploadField=Ext.ux.form.FileUploadField,Ext.namespace("Ext.ux.form"),Ext.ux.form.SuperBoxSelect=function(config){Ext.ux.form.SuperBoxSelect.superclass.constructor.call(this,config),this.addEvents("beforeadditem","additem","newitem","beforeremoveitem","removeitem","clear")},Ext.ux.form.SuperBoxSelect=Ext.extend(Ext.ux.form.SuperBoxSelect,Ext.form.ComboBox,{addNewDataOnBlur:!1,allowAddNewData:!1,allowQueryAll:!0,backspaceDeletesLastItem:!0,classField:null,clearBtnCls:"",clearLastQueryOnEscape:!1,clearOnEscape:!1,displayFieldTpl:null,extraItemCls:"",extraItemStyle:"",expandBtnCls:"",fixFocusOnTabSelect:!0,forceFormValue:!0,forceSameValueQuery:!1,itemDelimiterKey:Ext.EventObject.ENTER,navigateItemsWithTab:!0,pinList:!0,preventDuplicates:!0,queryFilterRe:"",queryValuesDelimiter:"|",queryValuesIndicator:"valuesqry",removeValuesFromStore:!0,renderFieldBtns:!0,stackItems:!1,styleField:null,supressClearValueRemoveEvents:!1,validationEvent:"blur",valueDelimiter:",",initComponent:function(){Ext.apply(this,{items:new Ext.util.MixedCollection(!1),usedRecords:new Ext.util.MixedCollection(!1),addedRecords:[],remoteLookup:[],hideTrigger:!0,grow:!1,resizable:!1,multiSelectMode:!1,preRenderValue:null,filteredQueryData:""}),this.queryFilterRe&&Ext.isString(this.queryFilterRe)&&(this.queryFilterRe=new RegExp(this.queryFilterRe)),this.transform&&this.doTransform(),this.forceFormValue&&this.items.on({add:this.manageNameAttribute,remove:this.manageNameAttribute,clear:this.manageNameAttribute,scope:this}),Ext.ux.form.SuperBoxSelect.superclass.initComponent.call(this),"remote"===this.mode&&this.store&&this.store.on("load",this.onStoreLoad,this)},onRender:function(ct,position){var h=this.hiddenName;this.hiddenName=null,Ext.ux.form.SuperBoxSelect.superclass.onRender.call(this,ct,position),this.hiddenName=h,this.manageNameAttribute();var extraClass=!0===this.stackItems?"x-superboxselect-stacked":"";this.renderFieldBtns&&(extraClass+=" x-superboxselect-display-btns"),this.el.removeClass("x-form-text").addClass("x-superboxselect-input-field"),this.wrapEl=this.el.wrap({tag:"ul"}),this.outerWrapEl=this.wrapEl.wrap({tag:"div",cls:"x-form-text x-superboxselect "+extraClass}),this.inputEl=this.el.wrap({tag:"li",cls:"x-superboxselect-input"}),this.renderFieldBtns&&this.setupFieldButtons().manageClearBtn(),this.setupFormInterception()},doTransform:function(){var s=Ext.getDom(this.transform),transformValues=[];if(!this.store){this.mode="local";for(var d=[],opts=s.options,i=0,len=opts.length;i0&&(this.collapse(),(it=this.items.get(0)).el.focus()),!0):e.getKey()===e.BACKSPACE?(e.stopEvent(),this.currentFocus?(toDestroy=this.currentFocus,this.on("expand",(function(){this.collapse()}),this,{single:!0}),idx=this.items.indexOfKey(toDestroy.key),this.clearCurrentFocus(),idx0?(this.el.removeClass(this.emptyClass),this.setRawValue(""),this):(this.rendered&&this.emptyText&&this.getRawValue().length<1&&(this.setRawValue(this.emptyText),this.el.addClass(this.emptyClass)),this)},removeAllItems:function(){return this.items.each((function(item){item.preDestroy(!0)}),this),this.manageClearBtn(),this},killItems:function(){return this.items.each((function(item){item.kill()}),this),this.resetStore(),this.items.clear(),this.manageClearBtn(),this},resetStore:function(){return this.store.clearFilter(),this.removeValuesFromStore?(this.usedRecords.each((function(rec){this.store.add(rec)}),this),this.usedRecords.clear(),this.store.remoteSort||this.store.sort(this.displayField,"ASC"),this):this},sortStore:function(){var ss=this.store.getSortState();return ss&&ss.field&&this.store.sort(ss.field,ss.direction),this},getCaption:function(dataObject){"string"==typeof this.displayFieldTpl&&(this.displayFieldTpl=new Ext.XTemplate(this.displayFieldTpl));var caption,recordData=dataObject instanceof Ext.data.Record?dataObject.data:dataObject;return this.displayFieldTpl?caption=this.displayFieldTpl.apply(recordData):this.displayField&&(caption=recordData[this.displayField]),caption},htmlEncode:function(string){return string.replace(/[\u00A0-\u9999<>&]/g,(function(i){return"&#"+i.charCodeAt(0)+";"}))},addRecord:function(record){var display=record.data[this.displayField],caption=this.getCaption(record),val=record.data[this.valueField],cls=this.classField?record.data[this.classField]:"",style=this.styleField?record.data[this.styleField]:"";this.removeValuesFromStore&&(this.usedRecords.add(val,record),this.store.remove(record)),this.addItemBox(val,display,caption,cls,style),this.fireEvent("additem",this,val,record)},createRecord:function(recordData){if(!this.recordConstructor){var recordFields=[{name:this.valueField},{name:this.displayField}];this.classField&&recordFields.push({name:this.classField}),this.styleField&&recordFields.push({name:this.styleField}),this.recordConstructor=Ext.data.Record.create(recordFields)}return new this.recordConstructor(recordData)},addItems:function(newItemObjects){Ext.isArray(newItemObjects)?Ext.each(newItemObjects,(function(item){this.addItem(item)}),this):this.addItem(newItemObjects)},addNewItem:function(newItemObject){this.addItem(newItemObject,!0)},addItem:function(newItemObject,forcedAdd){var val=newItemObject[this.valueField];if(this.disabled)return!1;if(!this.preventDuplicates||!this.hasValue(val)){var record=this.findRecord(this.valueField,val);if(record)this.addRecord(record);else if(this.allowAddNewData){if("remote"===this.mode)return this.remoteLookup.push(newItemObject),void this.doQuery(val,!1,!1,forcedAdd);var rec=this.createRecord(newItemObject);return this.store.add(rec),this.addRecord(rec),!0}}},addItemBox:function(itemVal,itemDisplay,itemCaption,itemClass,itemStyle){var hConfig,itemKey=Ext.id(null,"sbx-item"),box=new Ext.ux.form.SuperBoxSelectItem({owner:this,disabled:this.disabled,renderTo:this.wrapEl,cls:this.extraItemCls+" "+itemClass,style:function(s){var ret="";switch(typeof s){case"function":ret=s.call();break;case"object":for(var p in s)ret+=p+":"+s[p]+";";break;case"string":ret=s+";"}return ret}(this.extraItemStyle)+" "+itemStyle,caption:itemCaption,display:itemDisplay,value:itemVal,key:itemKey,listeners:{remove:function(item){if(!1===this.fireEvent("beforeremoveitem",this,item.value))return!1;this.items.removeKey(item.key),this.removeValuesFromStore&&this.usedRecords.containsKey(item.value)&&(this.store.add(this.usedRecords.get(item.value)),this.usedRecords.removeKey(item.value),this.sortStore(),this.view&&this.view.render()),this.preventMultipleRemoveEvents||this.fireEvent.defer(250,this,["removeitem",this,item.value,this.findInStore(item.value)])},destroy:function(){this.collapse(),this.autoSize().manageClearBtn().validateValue()},scope:this}});box.render(),hConfig={tag:"input",type:"hidden",value:itemVal,name:this.hiddenName||this.name},this.disabled&&Ext.apply(hConfig,{disabled:"disabled"}),box.hidden=this.el.insertSibling(hConfig,"before"),this.items.add(itemKey,box),this.applyEmptyText().autoSize().manageClearBtn().validateValue()},manageClearBtn:function(){if(!this.renderFieldBtns||!this.rendered)return this;var cls="x-superboxselect-btn-hide";return 0===this.items.getCount()?this.buttonClear.addClass(cls):this.buttonClear.removeClass(cls),this},findInStore:function(val){var index=this.store.find(this.valueField,val);return index>-1&&this.store.getAt(index)},getSelectedRecords:function(){var ret=[];if(this.removeValuesFromStore)ret=this.usedRecords.getRange();else{var vals=[];this.items.each((function(item){vals.push(item.value)})),Ext.each(vals,(function(val){ret.push(this.findInStore(val))}),this)}return ret},findSelectedItem:function(el){var ret;return this.items.each((function(item){if(item.el.dom===el)return ret=item,!1})),ret},findSelectedRecord:function(el){var ret,item=this.findSelectedItem(el);return item&&(ret=this.findSelectedRecordByValue(item.value)),ret},findSelectedRecordByValue:function(val){var ret;return this.removeValuesFromStore?this.usedRecords.each((function(rec){if(rec.get(this.valueField)==val)return ret=rec,!1}),this):ret=this.findInStore(val),ret},getValue:function(){var ret=[];return this.items.each((function(item){ret.push(item.value)})),ret.join(this.valueDelimiter)},getCount:function(){return this.items.getCount()},getValueEx:function(){var ret=[];return this.items.each((function(item){var newItem={};newItem[this.valueField]=item.value,newItem[this.displayField]=item.display,this.classField&&(newItem[this.classField]=item.cls||""),this.styleField&&(newItem[this.styleField]=item.style||""),ret.push(newItem)}),this),ret},initValue:function(){Ext.isObject(this.value)||Ext.isArray(this.value)?(this.setValueEx(this.value),this.originalValue=this.getValue()):Ext.ux.form.SuperBoxSelect.superclass.initValue.call(this),"remote"===this.mode&&(this.setOriginal=!0)},addValue:function(value){if(!Ext.isEmpty(value)){var values=value;if(Ext.isArray(value)||(values=(value=""+value).split(this.valueDelimiter)),Ext.each(values,(function(val){var record=this.findRecord(this.valueField,val);record?this.addRecord(record):"remote"===this.mode&&this.remoteLookup.push(val)}),this),"remote"===this.mode){var q=this.remoteLookup.join(this.queryValuesDelimiter);this.doQuery(q,!1,!0)}}},setValue:function(value){this.rendered?(this.removeAllItems().resetStore(),this.remoteLookup=[],this.addValue(value)):this.value=value},setValueEx:function(data){this.rendered?(this.removeAllItems().resetStore(),Ext.isArray(data)||(data=[data]),this.remoteLookup=[],this.allowAddNewData&&"remote"===this.mode?Ext.each(data,(function(d){var r=this.findRecord(this.valueField,d[this.valueField])||this.createRecord(d);this.addRecord(r)}),this):Ext.each(data,(function(item){this.addItem(item)}),this)):this.value=data},hasValue:function(val){var has=!1;return this.items.each((function(item){if(item.value==val)return has=!0,!1}),this),has},onSelect:function(record,index){if(!1!==this.fireEvent("beforeselect",this,record,index)){var val=record.data[this.valueField];if(this.preventDuplicates&&this.hasValue(val))return;this.setRawValue(""),this.lastSelectionText="",!1!==this.fireEvent("beforeadditem",this,val,record,this.filteredQueryData)&&this.addRecord(record),0!==this.store.getCount()&&this.multiSelectMode?this.restrictHeight():this.collapse()}},onDestroy:function(){this.items.purgeListeners(),this.killItems(),this.allowQueryAll&&Ext.destroy(this.buttonExpand),this.renderFieldBtns&&Ext.destroy(this.buttonClear,this.buttonWrap),Ext.destroy(this.inputEl,this.wrapEl,this.outerWrapEl),Ext.ux.form.SuperBoxSelect.superclass.onDestroy.call(this)},autoSize:function(){if(!this.rendered)return this;this.metrics||(this.metrics=Ext.util.TextMetrics.createInstance(this.el));var v=this.el.dom.value,d=document.createElement("div");""===v&&this.emptyText&&this.items.getCount()<1&&(v=this.emptyText),d.appendChild(document.createTextNode(v)),v=d.innerHTML,d=null,v+=" ";var w=Math.max(this.metrics.getWidth(v)+24,24);return void 0!==this._width&&(w=Math.min(this._width,w)),this.el.setWidth(w),Ext.isIE&&(this.el.dom.style.top="0"),this.fireEvent("autosize",this,w),this},shouldQuery:function(q){if(this.lastQuery){var m=q.match("^"+this.lastQuery);return!(m&&!this.store.getCount())||m[0]!==this.lastQuery}return!0},doQuery:function(q,forceAll,valuesQuery,forcedAdd){if(q=Ext.isEmpty(q)?"":q,this.queryFilterRe){this.filteredQueryData="";var m=q.match(this.queryFilterRe);if(m&&m.length&&(this.filteredQueryData=m[0]),!(q=q.replace(this.queryFilterRe,""))&&m)return}var qe={query:q,forceAll,combo:this,cancel:!1};if(!1===this.fireEvent("beforequery",qe)||qe.cancel)return!1;q=qe.query,(!0===(forceAll=qe.forceAll)||q.length>=this.minChars||valuesQuery&&!Ext.isEmpty(q))&&(forcedAdd||this.forceSameValueQuery||this.shouldQuery(q)?(this.lastQuery=q,"local"==this.mode?(this.selectedIndex=-1,forceAll?this.store.clearFilter():this.store.filter(this.displayField,q),this.onLoad()):(this.store.baseParams[this.queryParam]=q,this.store.baseParams[this.queryValuesIndicator]=valuesQuery,this.store.load({params:this.getParams(q)}),forcedAdd||this.expand())):(this.selectedIndex=-1,this.onLoad()))},onStoreLoad:function(store,records,options){var q=options.params[this.queryParam]||store.baseParams[this.queryParam]||"",isValuesQuery=options.params[this.queryValuesIndicator]||store.baseParams[this.queryValuesIndicator];if(this.removeValuesFromStore&&this.store.each((function(record){this.usedRecords.containsKey(record.get(this.valueField))&&this.store.remove(record)}),this),isValuesQuery){var params=q.split(this.queryValuesDelimiter);Ext.each(params,(function(p){this.remoteLookup.remove(p);var rec=this.findRecord(this.valueField,p);rec&&this.addRecord(rec)}),this),this.setOriginal&&(this.setOriginal=!1,this.originalValue=this.getValue())}""!==q&&this.allowAddNewData&&Ext.each(this.remoteLookup,(function(r){if("object"==typeof r&&r[this.valueField]===q){if(this.remoteLookup.remove(r),records.length&&records[0].get(this.valueField)===q)return void this.addRecord(records[0]);var rec=this.createRecord(r);return this.store.add(rec),this.addRecord(rec),this.addedRecords.push(rec),void function(){this.isExpanded()&&this.collapse()}.defer(10,this)}}),this);var toAdd=[];if(""===q)Ext.each(this.addedRecords,(function(rec){this.preventDuplicates&&this.usedRecords.containsKey(rec.get(this.valueField))||toAdd.push(rec)}),this);else{var re=new RegExp(Ext.escapeRe(q)+".*","i");Ext.each(this.addedRecords,(function(rec){this.preventDuplicates&&this.usedRecords.containsKey(rec.get(this.valueField))||re.test(rec.get(this.displayField))&&toAdd.push(rec)}),this)}this.store.add(toAdd),this.sortStore(),0===this.store.getCount()&&this.isExpanded()&&this.collapse()}}),Ext.reg("superboxselect",Ext.ux.form.SuperBoxSelect),Ext.ux.form.SuperBoxSelectItem=function(config){Ext.apply(this,config),Ext.ux.form.SuperBoxSelectItem.superclass.constructor.call(this)},Ext.ux.form.SuperBoxSelectItem=Ext.extend(Ext.ux.form.SuperBoxSelectItem,Ext.Component,{initComponent:function(){Ext.ux.form.SuperBoxSelectItem.superclass.initComponent.call(this)},onElClick:function(e){var o=this.owner;if(o.clearCurrentFocus().collapse(),o.navigateItemsWithTab)this.focus();else{o.el.dom.focus();(function(){this.onLnkFocus(),o.currentFocus=this}).defer(10,this)}},onLnkClick:function(e){e&&e.stopEvent(),this.preDestroy(),this.owner.navigateItemsWithTab||this.owner.el.focus()},onLnkFocus:function(){this.el.addClass("x-superboxselect-item-focus"),this.owner.outerWrapEl.addClass("x-form-focus")},onLnkBlur:function(){this.el.removeClass("x-superboxselect-item-focus"),this.owner.outerWrapEl.removeClass("x-form-focus")},enableElListeners:function(){this.el.on("click",this.onElClick,this,{stopEvent:!0}),this.el.addClassOnOver("x-superboxselect-item-hover")},enableLnkListeners:function(){this.lnk.on({click:this.onLnkClick,focus:this.onLnkFocus,blur:this.onLnkBlur,scope:this})},enableAllListeners:function(){this.enableElListeners(),this.enableLnkListeners()},disableAllListeners:function(){this.el.removeAllListeners(),this.lnk.un("click",this.onLnkClick,this),this.lnk.un("focus",this.onLnkFocus,this),this.lnk.un("blur",this.onLnkBlur,this)},onRender:function(ct,position){Ext.ux.form.SuperBoxSelectItem.superclass.onRender.call(this,ct,position);var el=this.el;el&&el.remove(),this.el=el=ct.createChild({tag:"li"},ct.last()),el.addClass("x-superboxselect-item");var btnEl=this.owner.navigateItemsWithTab?Ext.isSafari?"button":"a":"span";this.key;Ext.apply(el,{focus:function(){var c=this.down(btnEl+".x-superboxselect-item-close");c&&c.focus()},preDestroy:function(){this.preDestroy()}.createDelegate(this)}),this.enableElListeners(),el.update(this.caption);var cfg={tag:btnEl,class:"x-superboxselect-item-close",tabIndex:this.owner.navigateItemsWithTab?"0":"-1"};"a"===btnEl&&(cfg.href="#"),this.lnk=el.createChild(cfg),this.disabled?this.disableAllListeners():this.enableLnkListeners(),this.on({disable:this.disableAllListeners,enable:this.enableAllListeners,scope:this}),this.setupKeyMap()},setupKeyMap:function(){this.keyMap=new Ext.KeyMap(this.lnk,[{key:[Ext.EventObject.BACKSPACE,Ext.EventObject.DELETE,Ext.EventObject.SPACE],fn:this.preDestroy,scope:this},{key:[Ext.EventObject.RIGHT,Ext.EventObject.DOWN],fn:function(){this.moveFocus("right")},scope:this},{key:[Ext.EventObject.LEFT,Ext.EventObject.UP],fn:function(){this.moveFocus("left")},scope:this},{key:[Ext.EventObject.HOME],fn:function(){var l=this.owner.items.get(0).el.focus();l&&l.el.focus()},scope:this},{key:[Ext.EventObject.END],fn:function(){this.owner.el.focus()},scope:this},{key:Ext.EventObject.ENTER,fn:function(){}}]),this.keyMap.stopEvent=!0},moveFocus:function(dir){var el=this.el["left"==dir?"prev":"next"]()||this.owner.el;el.focus.defer(100,el)},preDestroy:function(supressEffect){if(!1!==this.fireEvent("remove",this)){var actionDestroy=function(){this.owner.navigateItemsWithTab&&this.moveFocus("right"),this.hidden.remove(),this.hidden=null,this.destroy()};return supressEffect?actionDestroy.call(this):this.el.hide({duration:.2,callback:actionDestroy,scope:this}),this}},kill:function(){this.hidden.remove(),this.hidden=null,this.purgeListeners(),this.destroy()},onDisable:function(){this.hidden&&this.hidden.dom.setAttribute("disabled","disabled"),this.keyMap.disable(),Ext.ux.form.SuperBoxSelectItem.superclass.onDisable.call(this)},onEnable:function(){this.hidden&&this.hidden.dom.removeAttribute("disabled"),this.keyMap.enable(),Ext.ux.form.SuperBoxSelectItem.superclass.onEnable.call(this)},onDestroy:function(){Ext.destroy(this.lnk,this.el),Ext.ux.form.SuperBoxSelectItem.superclass.onDestroy.call(this)}}),MODx.Component=function(config){config=config||{},MODx.Component.superclass.constructor.call(this,config),this.config=config,this._loadForm(),this.config.tabs&&this._loadTabs(),this._loadComponents(),this._loadActionButtons(),MODx.activePage=this},Ext.extend(MODx.Component,Ext.Component,{fields:{},form:null,action:!1,_loadForm:function(){if(!this.config.form)return!1;if(this.form=new Ext.form.BasicForm(Ext.get(this.config.form),{errorReader:MODx.util.JSONReader}),this.config.fields)for(var i in this.config.fields)if(this.config.fields.hasOwnProperty(i)){var f=this.config.fields[i];f.xtype&&(f=Ext.ComponentMgr.create(f)),this.fields[i]=f,this.form.add(f)}return this.form.render()},_loadActionButtons:function(){return!!this.config.buttons&&(this.ab=MODx.load({xtype:"modx-actionbuttons",form:this.form||null,formpanel:this.config.formpanel||null,actions:this.config.actions||null,items:this.config.buttons||[]}),this.ab)},_loadTabs:function(){if(!this.config.tabs)return!1;var o=this.config.tabOptions||{};return Ext.applyIf(o,{xtype:"modx-tabs",renderTo:this.config.tabs_div||"tabs_div",items:this.config.tabs}),MODx.load(o)},_loadComponents:function(){if(!this.config.components)return!1;for(var l=this.config.components.length,cp=Ext.getCmp("modx-content"),i=0;i","<-",""," "];if(-1!=ex.indexOf(el)||el.xtype&&"switch"==el.xtype)MODx.toolbar.ActionButtons.superclass.add.call(this,el);else{var id=el.id||Ext.id();if(Ext.applyIf(el,{xtype:"button",cls:el.icon?"x-btn-icon bmenu":"x-btn-text bmenu",scope:this,disabled:!!el.checkDirty,listeners:{},id}),el.button&&MODx.toolbar.ActionButtons.superclass.add.call(this,el),null===el.handler&&null===el.menu?el.handler=this.checkConfirm:el.confirm&&el.handler?el.handler=function(){Ext.Msg.confirm(_("warning"),el.confirm,(function(e){"yes"===e&&Ext.callback(el.handler,this)}),el.scope||this)}:el.handler||(el.handler=this.handleClick),el.javascript&&(el.listeners.click={fn:this.evalJS,scope:this}),"button"==el.xtype&&(el.listeners.render={fn:function(btn){el.checkDirty&&btn&&this.checkDirtyBtns.push(btn)},scope:this}),el.keys){el.keyMap=new Ext.KeyMap(Ext.get(document));for(var j=0;j{item&&item.validate&&!item.validate()&&(isv=!1)})),isv?(Ext.applyIf(o.params,{action:itm.process}),Ext.apply(f.baseParams,o.params),o.form.on("success",(function(r){if(o.form.clearDirty&&o.form.clearDirty(),MODx.msg.status({title:_("success"),message:r.result.message||_("save_successful"),dontHide:""!=r.result.message}),0!=itm.redirect){var redirect=this.redirect;"function"==typeof itm.redirect&&(redirect=itm.redirect),Ext.callback(redirect,this,[o,itm,r.result],1e3)}this.resetDirtyButtons(r.result)}),this),o.form.submit({headers:{"Powered-By":"MODx",modAuth:MODx.siteId}})):(o.form.fireEvent("failureSubmit"),Ext.Msg.alert(_("error"),_("correct_errors")))}else{var params=itm.params||{};Ext.applyIf(params,o.baseParams||{}),MODx.loadPage("?"+Ext.urlEncode(params))}return!1},resetDirtyButtons:function(r){for(var i=0;i0}},contextmenu:{fn:this._showContextMenu,scope:this}}),Ext.applyIf(config,{store:this.store,singleSelect:!0,overClass:"x-view-over",emptyText:'
    '+_("file_err_filter")+"
    ",closeAction:"hide"}),MODx.DataView.superclass.constructor.call(this,config),this.config=config,this.cm=new Ext.menu.Menu},Ext.extend(MODx.DataView,Ext.DataView,{lookup:{},onLoadException:function(){this.getEl().update('
    '+_("data_err_load")+"
    ")},_addContextMenuItem:function(items){for(var a=items,l=a.length,i=0;i ').compile()}),MODx.Button.superclass.constructor.call(this,config)},Ext.extend(MODx.Button,Ext.Button,{onRender:function(ct,position){this.template||(Ext.Button.buttonTemplate||(Ext.Button.buttonTemplate=new Ext.Template(' '),Ext.Button.buttonTemplate.compile()),this.template=Ext.Button.buttonTemplate);var btn,targs=this.getTemplateArgs();targs.iconCls=this.iconCls,btn=position?this.template.insertBefore(position,targs,!0):this.template.append(ct,targs,!0),this.btnEl=btn.child("i"),this.mon(this.btnEl,{scope:this,focus:this.onFocus,blur:this.onBlur}),this.initButtonEl(btn,this.btnEl),Ext.ButtonToggleMgr.register(this)}}),Ext.reg("modx-button",MODx.Button),MODx.SearchBar=function(config){config=config||{},Ext.applyIf(config,{renderTo:"modx-manager-search",listClass:"modx-manager-search-results",emptyText:_("search"),id:"modx-uberbar",maxHeight:this.getViewPortSize(),typeAhead:!0,listAlign:["tl-bl?",[-12,12]],triggerConfig:{tag:"button",id:"modx-uberbar-trigger",type:"submit","aria-label":"Go",cls:"x-form-trigger icon icon-large icon-search"},defaultAutoCreate:{tag:"input",type:"text",size:"24",tabindex:"0",hasfocus:!0,"aria-label":_("search")},hasfocus:!0,minChars:1,displayField:"name",valueField:"_action",width:380,itemSelector:".x-combo-list-item",tpl:new Ext.XTemplate('','
    ','','',"

    {label:htmlEncode}

    ","
    ",'

    {name:htmlEncode} – {description:htmlEncode}

    ',"
    ","
    ",{getClass:function(values){if(values.icon)return values.icon;if(values.class)switch(values.class){case"MODX\\Revolution\\modDocument":return"file";case"MODX\\Revolution\\modSymLink":return"files-o";case"MODX\\Revolution\\modWebLink":return"link";case"MODX\\Revolution\\modStaticResource":return"file-text-o"}switch(values.type){case"resources":return"file";case"chunks":return"th-large";case"templates":return"columns";case"snippets":return"code";case"tvs":return"list-alt";case"plugins":return"cogs";case"users":return"user";case"actions":return"mail-forward"}},getLabel:function(values){return values.label?values.label:_("search_resulttype_"+values.type)}}),store:new Ext.data.JsonStore({url:MODx.config.connector_url,baseParams:{action:"Search/Search"},root:"results",totalProperty:"total",fields:["name","_action","description","type","icon","label","class"],listeners:{beforeload:function(store,options){if(options.params._action)return!1}}}),listeners:{beforequery:{fn:function(){this.tpl.type=null}},focus:this.focusBar,blur:this.blurBar,afterrender:function(){document.getElementById("modx-manager-search").onclick=function(e){e.stopPropagation()}},scope:this}}),MODx.SearchBar.superclass.constructor.call(this,config),this.blur(),this.setKeyMap()},Ext.extend(MODx.SearchBar,Ext.form.ComboBox,{setKeyMap:function(){new Ext.KeyMap(document,{key:27,handler:function(){this.hideBar()},scope:this,stopEvent:!1})},initList:function(){if(!this.list){var cls="x-combo-list",listParent=Ext.getDom(this.getListParent()||Ext.getBody());this.list=new Ext.Layer({parentEl:listParent,shadow:this.shadow,cls:[cls,this.listClass].join(" "),constrain:!1,zindex:this.getZIndex(listParent)}),this.list.on("click",(function(e){e.stopPropagation()}));var lw=this.listWidth||Math.max(this.wrap.getWidth(),this.minListWidth);this.list.setSize(lw,0),this.list.swallowEvent("mousewheel"),this.assetHeight=0,!1!==this.syncFont&&this.list.setStyle("font-size",this.el.getStyle("font-size")),this.title&&(this.header=this.list.createChild({cls:cls+"-hd",html:this.title}),this.assetHeight+=this.header.getHeight()),this.innerList=this.list.createChild({cls:cls+"-inner"}),this.mon(this.innerList,"mouseover",this.onViewOver,this),this.mon(this.innerList,"mousemove",this.onViewMove,this),this.innerList.setWidth(lw-this.list.getFrameWidth("lr")),this.pageSize&&(this.footer=this.list.createChild({cls:cls+"-ft"}),this.pageTb=new Ext.PagingToolbar({store:this.store,pageSize:this.pageSize,renderTo:this.footer}),this.assetHeight+=this.footer.getHeight()),this.tpl||(this.tpl='
    {'+this.displayField+"}
    "),this.view=new Ext.DataView({applyTo:this.innerList,tpl:this.tpl,singleSelect:!0,selectedClass:this.selectedClass,itemSelector:this.itemSelector||"."+cls+"-item",emptyText:this.listEmptyText,deferEmptyText:!1}),this.view.on("click",(function(view,index,node,vent){view.select(node),window.event||(window.event=vent),this.onViewClick()}),this),this.bindStore(this.store,!0),this.resizable&&(this.resizer=new Ext.Resizable(this.list,{pinned:!0,handles:"se"}),this.mon(this.resizer,"resize",(function(r,w,h){this.maxHeight=h-this.handleHeight-this.list.getFrameWidth("tb")-this.assetHeight,this.listWidth=w,this.innerList.setWidth(w-this.list.getFrameWidth("lr")),this.restrictHeight()}),this),this[this.pageSize?"footer":"innerList"].setStyle("margin-bottom",this.handleHeight+"px"))}},onTypeAhead:function(){},onSelect:function(record,index){var e=Ext.EventObject;e.stopPropagation(),e.preventDefault();var target="?a="+record.data._action;if(e.ctrlKey||e.metaKey||e.shiftKey)return window.open(target);MODx.loadPage(target)},hideBar:function(){},focusBar:function(){this.selectText()},blurBar:function(){},getViewPortSize:function(){var height=300;return void 0!==window.innerHeight&&(height=window.innerHeight),height-70}}),Ext.reg("modx-searchbar",MODx.SearchBar),Ext.namespace("MODx.panel"),MODx.Panel=function(config){config=config||{},Ext.applyIf(config,{cls:"modx-panel",title:""}),MODx.Panel.superclass.constructor.call(this,config),this.config=config},Ext.extend(MODx.Panel,Ext.Panel),Ext.reg("modx-panel",MODx.Panel),MODx.FormPanel=function(config){config=config||{},Ext.applyIf(config,{autoHeight:!0,collapsible:!0,bodyStyle:"",layout:"anchor",border:!1,header:!1,method:"POST",cls:"modx-form",allowDrop:!0,errorReader:MODx.util.JSONReader,checkDirty:!0,useLoadingMask:!1,defaults:{collapsible:!1,autoHeight:!0,border:!1}}),config.items&&this.addChangeEvent(config.items),MODx.FormPanel.superclass.constructor.call(this,config),this.config=config,this.addEvents({setup:!0,fieldChange:!0,ready:!0,beforeSubmit:!0,success:!0,failure:!0,save:!0,actionNew:!0,actionContinue:!0,actionClose:!0,postReady:!0}),this.getForm().addEvents({success:!0,failure:!0}),this.dropTargets=[],this.on("ready",this.onReady),this.config.useLoadingMask&&this.on("render",(function(){this.mask=new Ext.LoadMask(this.getEl()),this.mask.show()})),this.fireEvent("setup",config)&&this.clearDirty(),this.focusFirstField()},Ext.extend(MODx.FormPanel,Ext.FormPanel,{isReady:!1,defaultValues:[],initialized:!1,isStatic:!1,errorHandlingTabs:[],errorHandlingIgnoreTabs:[],submit:function(o){var fm=this.getForm();return!(!fm.isValid()&&!o.bypassValidCheck)&&((o=o||{}).headers={"Powered-By":"MODx",modAuth:MODx.siteId},this.fireEvent("beforeSubmit",{form:fm,options:o,config:this.config})&&fm.submit({waitMsg:this.config.saveMsg||_("saving"),scope:this,headers:o.headers,clientValidation:!o.bypassValidCheck,failure:function(f,a){this.fireEvent("failure",{form:f,result:a.result,options:o,config:this.config})&&MODx.form.Handler.errorExt(a.result,f)},success:function(f,a){this.config.success&&Ext.callback(this.config.success,this.config.scope||this,[f,a]),this.fireEvent("success",{form:f,result:a.result,options:o,config:this.config}),this.clearDirty(),this.fireEvent("setup",this.config);var lastActiveEle=Ext.state.Manager.get("curFocus");if(lastActiveEle&&""!=lastActiveEle){Ext.state.Manager.clear("curFocus");var initFocus=document.getElementById(lastActiveEle);initFocus&&initFocus.focus()}}}),!0)},failure:function(o){if(this.warnUnsavedChanges=!0,-1!==this.getForm().baseParams.action.search(/\/create/i)){const btn=Ext.getCmp("modx-abtn-save");btn&&btn.enable()}this.fireEvent("failureSubmit")},focusFirstField:function(){if(this.getForm().items.getCount()>0){var fld=this.findFirstTextField();fld&&fld.focus(!1,200)}},findFirstTextField:function(i){i=i||0;var fld=this.getForm().items.itemAt(i);return!!fld&&((fld.isXType("combo")||fld.isXType("checkbox")||fld.isXType("radio")||fld.isXType("displayfield")||fld.isXType("statictextfield")||fld.isXType("hidden"))&&(i+=1,fld=this.findFirstTextField(i)),fld)},addChangeEvent:function(items){if(!items)return!1;"object"==typeof items&&items.items&&(items=items.items);for(var f=0;f{fieldKey=fieldKey.trim();const fieldCmpId=`modx-${formId}-${fieldKey}-file`,sourceKey=Ext.isEmpty(sharedSourceKey)?fieldKey:sharedSourceKey,sourceCmpId=`modx-${formId}-${sourceKey}-source`,fieldCmp=Ext.getCmp(fieldCmpId),sourceCmp=Ext.getCmp(sourceCmpId);fieldCmp&&sourceCmp&&(fieldCmp.config.source=sourceCmp.getValue())}))},destroy:function(){for(var i=0;i0&&keys.forEach((function(key){map.hasOwnProperty(key)&&"string"==typeof map[key].id?tabIds.push(map[key].id):"modx-panel-resource-tv"==key&&1==MODx.config.tvs_below_content&&tabIds.push(key)})),tabIds},showErroredTab:function(targetForms,tabsId){const mainTabs=Ext.getCmp(tabsId),searchTabs=this.getTabIdsFromKeys(mainTabs.items.map,targetForms);let component,mainTabName=null,mainTabIndex=null,erroredNode=null;mainTabs.items.length>mainTabs.initialConfig.items.length&&mainTabs.items.keys.forEach((function(key){mainTabs.items.map[key].hasOwnProperty("id")&&(this.errorHandlingIgnoreTabs.includes(mainTabs.items.map[key].id)||searchTabs.includes(mainTabs.items.map[key].id)||searchTabs.push(mainTabs.items.map[key].id))}),this);for(let i=0;i0&&erroredFlds[0].id},insertTagCopyUtility:function(cmp,elType){const helpTag=cmp.getEl().child(".example-replace-name"),elTag=cmp.getEl().child(".copy-this");let tagText,nameVal=cmp.previousSibling().getValue();helpTag&&(nameVal.length>0&&(helpTag.update(nameVal),tagText=elTag.dom.innerText),helpTag.on({click:function(){if(nameVal=cmp.previousSibling().getValue(),nameVal.length>0){tagText=elTag.dom.innerText;const tmp=document.createElement("textarea");if(tmp.value=tagText,document.body.appendChild(tmp),tmp.select(),document.execCommand("copy")){const feedback=document.createElement("span");feedback.className="element-panel feedback item-copied",feedback.textContent=_(elType+"_tag_copied"),elTag.insertSibling(feedback,"after"),setTimeout((function(){feedback.style.opacity=0,setTimeout((function(){feedback.remove()}),1200)}),10)}tmp.remove()}}}))},onChangeStaticSource:function(cmp,elType){const isStatic=Ext.getCmp(`modx-${elType}-static`).getValue(),staticFileField=Ext.getCmp(`modx-${elType}-static-file`),staticFile=staticFileField.getValue(),staticDir=staticFile.slice(0,staticFile.lastIndexOf("/")+1),staticFileFieldId=staticFileField.id,staticFileFieldContainer=Ext.getCmp(staticFileField.ownerCt.id),itemKey=staticFileFieldContainer.items.keys.indexOf(staticFileFieldId),previousSource=this.previousFileSource||0,currentSource=cmp.getValue(),currentRecord={static:isStatic,static_file:staticFile,source:currentSource,openTo:staticDir};let newStaticFile,changeFieldType=!1,updateFieldSource=!1;if("template"===elType)var newPreviewFileField,staticPreviewFileField=Ext.getCmp(`modx-${elType}-preview-file`),staticPreviewFile=staticPreviewFileField.getValue(),staticPreviewDir=staticPreviewFile.slice(0,staticPreviewFile.lastIndexOf("/")+1),staticPreviewFileFieldId=staticPreviewFileField.id,staticPreviewFileFieldContainer=Ext.getCmp(staticPreviewFileField.ownerCt.id),previewItemKey=staticPreviewFileFieldContainer.items.keys.indexOf(staticPreviewFileFieldId),currentPreviewRecord={static:isStatic,preview_file:staticPreviewFile,source:currentSource,openTo:staticPreviewDir};this.previousFileSource=currentSource,previousSource>0&&0==currentSource?(newStaticFile=this.getStaticFileField(elType,currentRecord,!1),"template"===elType&&(newPreviewFileField=this.getTemplatePreviewImageField(currentPreviewRecord,!1)),changeFieldType=!0):0==previousSource&¤tSource>0?(newStaticFile=this.getStaticFileField(elType,currentRecord),"template"===elType&&(newPreviewFileField=this.getTemplatePreviewImageField(currentPreviewRecord)),changeFieldType=!0,updateFieldSource=!0):updateFieldSource=!0,updateFieldSource&&(changeFieldType?(newStaticFile.source=currentSource,"template"===elType&&(newPreviewFileField.source=currentSource)):(staticFileField.config.source=currentSource,"template"===elType&&(staticPreviewFileField.config.source=currentSource))),changeFieldType&&(staticFileField.clearInvalid(),staticFileField.destroy(),staticFileFieldContainer.insert(itemKey,newStaticFile),"template"===elType&&(staticPreviewFileField.clearInvalid(),staticPreviewFileField.destroy(),staticPreviewFileFieldContainer.insert(previewItemKey,newPreviewFileField)),this.doLayout())},getStaticFileField:function(elType,record,loadBrowserField=!0){const sharedConfig={fieldLabel:_("static_file"),description:MODx.expandHelp?"":_("static_file_desc"),name:"static_file",id:`modx-${elType}-static-file`,maxLength:255,anchor:"100%",value:record.static_file||""};let finalConfig;return(0===record.source||!record.hasOwnProperty("source")&&Ext.isEmpty(MODx.config.default_media_source))&&(loadBrowserField=!1),finalConfig=loadBrowserField?Object.assign(sharedConfig,{xtype:"modx-combo-browser",browserEl:"modx-browser",triggerClass:"x-form-code-trigger",source:null!=record.source?record.source:MODx.config.default_media_source,openTo:record.openTo||""}):Object.assign(sharedConfig,{xtype:"textfield"}),record.static||(finalConfig.hidden=!0),finalConfig},getTemplatePreviewImageField:function(record,loadBrowserField=!0){const sharedConfig={fieldLabel:_("template_preview"),description:MODx.expandHelp?"":_("template_preview_description"),name:"preview_file",id:"modx-template-preview-file",allowedFileTypes:"jpg,jpeg,png,gif,bmp",maxLength:255,anchor:"100%",value:record.preview_file||""};let finalConfig;return(0===record.source||!record.hasOwnProperty("source")&&Ext.isEmpty(MODx.config.default_media_source))&&(loadBrowserField=!1),finalConfig=loadBrowserField?Object.assign(sharedConfig,{xtype:"modx-combo-browser",browserEl:"modx-browser",triggerClass:"x-form-image-trigger",source:null!=record.source?record.source:MODx.config.default_media_source,openTo:record.openTo||""}):Object.assign(sharedConfig,{xtype:"textfield"}),finalConfig},toggleFieldVisibility:function(ctrlId,containerId,fieldIds,ctrlValToShow,addSibling){const ctrlCmp=Ext.getCmp(ctrlId),containerCmp=Ext.getCmp(containerId);if(!ctrlCmp||void 0===ctrlCmp)return console.error(`toggleFieldVisibility: Could not get the control component with the id '${ctrlId}'`),!1;if(containerId&&(!containerCmp||void 0===containerCmp))return console.error(`toggleFieldVisibility: Could not get the container component with the id '${containerId}'`),!1;addSibling=!1!==addSibling,ctrlValToShow=!1!==ctrlValToShow;const showVal="combo-boolean"===ctrlCmp.xtype?ctrlCmp.getValue():ctrlCmp.checked,show=!1===ctrlValToShow?!showVal:showVal;show?(containerCmp.show(),containerCmp.doLayout()):containerCmp.hide(),fieldIds.forEach((field=>{const fieldCmp=Ext.getCmp(field),sibling=fieldCmp.nextSibling(),siblingIsHelp=sibling&&"label"===sibling.xtype;fieldCmp&&(show?(fieldCmp.show(),addSibling&&siblingIsHelp&&sibling.show()):(fieldCmp.hide(),addSibling&&siblingIsHelp&&sibling.hide()))}))},formatMainPanelTitle:function(formId,record,realtimeValue=null,returnBaseTitle=!1){let title="",baseTitle="";const modeCreate=!(record.hasOwnProperty("id")&&record.id>0),prefixSeparator=modeCreate&&!realtimeValue?"":": ",prefix=(modeCreate?_("create")+" ":_("edit")+" ")+_("resource"===formId?"document":formId)+prefixSeparator;if(!Ext.isEmpty(record)){const postfix=MODx.perm.tree_show_resource_ids&&!Ext.isEmpty(record.id)?` (${record.id})`:"";if("resource"===formId){const headerCmp=Ext.getCmp("modx-header-breadcrumbs");title=realtimeValue||record.pagetitle,baseTitle=this.encodeTitle(title,!1),title=void 0===title?prefix:this.encodeTitle(title)+postfix,headerCmp?headerCmp.updateHeader(title):Ext.getCmp("modx-resource-header").el.dom.innerText=title}else{const headerCmpId=`modx-${formId}-header`;realtimeValue?baseTitle=this.encodeTitle(realtimeValue):(title="template"===formId?record.templatename:record.name,baseTitle=this.encodeTitle(title)),title=void 0===title?prefix:prefix+baseTitle+postfix,Ext.getCmp(headerCmpId).getEl().update(title)}}if(returnBaseTitle)return baseTitle},encodeTitle:function(title,htmlEncode=!0){return title&&(title=htmlEncode?Ext.util.Format.htmlEncode(Ext.util.Format.stripTags(title)):Ext.util.Format.stripTags(title)),title},getElementProperties:function(properties){if(!Ext.isEmpty(properties)){const gridCmp=Ext.getCmp("modx-grid-element-properties");gridCmp&&(gridCmp.defaultProperties=properties,gridCmp.getStore().loadData(properties))}}}),Ext.reg("modx-formpanel",MODx.FormPanel),MODx.panel.Wizard=function(config){config=config||{},Ext.applyIf(config,{layout:"card",activeItem:0,resizable:!0,collapsible:!0,maximizable:!0,autoHeight:!0,width:750,firstPanel:"",lastPanel:"",defaults:{border:!1},modal:!0,txtFinish:_("finish"),txtNext:_("next"),txtBack:_("back"),bbar:[{id:"pi-btn-bck",itemId:"btn-back",text:config.txtBack||_("back"),handler:this.navHandler.createDelegate(this,[-1]),scope:this,disabled:!0},{id:"pi-btn-fwd",itemId:"btn-fwd",text:config.txtNext||_("next"),handler:this.navHandler.createDelegate(this,[1]),scope:this}]}),MODx.panel.Wizard.superclass.constructor.call(this,config),this.config=config,this.lastActiveItem=this.config.firstPanel,this._go()},Ext.extend(MODx.panel.Wizard,Ext.Panel,{windows:{},_go:function(){this.getBottomToolbar().items.item(1).setText(this.config.txtNext),this.proceed(this.config.firstPanel)},navHandler:function(dir){this.doLayout();var a=this.getLayout().activeItem;-1==dir?this.proceed(a.config.back||a.config.id):a.submit({scope:this,proceed:this.proceed})},proceed:function(id){this.doLayout(),this.getLayout().setActiveItem(id),id==this.config.firstPanel?(this.getBottomToolbar().items.item(0).setDisabled(!0),this.getBottomToolbar().items.item(1).setText(this.config.txtNext)):id==this.config.lastPanel?this.getBottomToolbar().items.item(1).setText(this.config.txtFinish):(this.getBottomToolbar().items.item(0).setDisabled(!1),this.getBottomToolbar().items.item(1).setText(this.config.txtNext))}}),Ext.reg("modx-panel-wizard",MODx.panel.Wizard),MODx.panel.WizardPanel=function(config){config=config||{},Ext.applyIf(config,{wizard:null,checkDirty:!1,bodyStyle:"padding: 3em 3em",hideMode:"offsets"}),MODx.panel.WizardPanel.superclass.constructor.call(this,config)},Ext.extend(MODx.panel.WizardPanel,MODx.FormPanel),Ext.reg("modx-wizard-panel",MODx.panel.WizardPanel),MODx.PanelSpacer={html:"
    ",border:!1},MODx.TemplatePanel=function(config){config=config||{},Ext.applyIf(config,{frame:!1,startingMarkup:'

    {text}

    ',startingText:"Loading...",markup:null,plain:!0,border:!1}),MODx.TemplatePanel.superclass.constructor.call(this,config),this.on("render",this.init,this)},Ext.extend(MODx.TemplatePanel,Ext.Panel,{init:function(){this.defaultMarkup=new Ext.XTemplate(this.startingMarkup,{compiled:!0}),this.reset(),this.tpl=new Ext.XTemplate(this.markup,{compiled:!0})},reset:function(){this.body.hide(),this.defaultMarkup.overwrite(this.body,{text:this.startingText}),this.body.slideIn("r",{stopFx:!0,duration:.2}),setTimeout((function(){Ext.getCmp("modx-content").doLayout()}),500)},updateDetail:function(data){this.body.hide(),this.tpl.overwrite(this.body,data),this.body.slideIn("r",{stopFx:!0,duration:.2}),setTimeout((function(){Ext.getCmp("modx-content").doLayout()}),500)}}),Ext.reg("modx-template-panel",MODx.TemplatePanel),MODx.BreadcrumbsPanel=function(config){config=config||{},Ext.applyIf(config,{frame:!1,plain:!0,border:!1,desc:"This the description part of this panel",bdMarkup:"
      {text}

    {text}

    ",root:{text:"Home",className:"first",root:!0,pnl:""},bodyCssClass:"breadcrumbs"}),MODx.BreadcrumbsPanel.superclass.constructor.call(this,config),this.on("render",this.init,this)},Ext.extend(MODx.BreadcrumbsPanel,Ext.Panel,{data:{trail:[]},init:function(){this.tpl=new Ext.XTemplate(this.bdMarkup,{compiled:!0}),this.reset(this.desc),this.body.on("click",this.onClick,this)},getResetText:function(srcInstance){if("object"!=typeof srcInstance||null==srcInstance)return srcInstance;var newInstance=srcInstance.constructor();for(var i in srcInstance)newInstance[i]=this.getResetText(srcInstance[i]);return newInstance.hasOwnProperty("pnl")&&delete newInstance.pnl,newInstance},updateDetail:function(data){(this.data=data,data.hasOwnProperty("trail"))&&data.trail.unshift(this.root);this._updatePanel(data)},getData:function(){return this.data},reset:function(msg){void 0===this.resetText&&(this.resetText=this.getResetText(this.root)),this.data={text:msg,trail:[this.resetText]},this._updatePanel(this.data)},onClick:function(e){for(var target=e.getTarget(),index=1,parent=target.parentElement;null!=(parent=parent.previousSibling);)index+=1;for(var remove=this.data.trail.length-index;remove>0;)this.data.trail.pop(),remove-=1;if(elm=target.className.split(" ")[0],""!=elm&&"controlBtn"==elm){var panel=target.className.split(" ")[1];if("install"==panel){var last=this.data.trail[this.data.trail.length-1];if(null!=last&&null!=last.rec)return this.data.trail.pop(),void Ext.getCmp("modx-package-grid").install(last.rec)}else Ext.getCmp(panel).activate()}},_updatePanel:function(data){this.body.hide(),this.tpl.overwrite(this.body,data),this.body.slideIn("r",{stopFx:!0,duration:.2}),setTimeout((function(){Ext.getCmp("modx-content").doLayout()}),500)}}),Ext.reg("modx-breadcrumbs-panel",MODx.BreadcrumbsPanel),Ext.override(Ext.TabPanel,{onStripMouseDown:function(e){if(0!==e.button)return;e.preventDefault();const t=this.findTargets(e);t.close?!1!==t.item.fireEvent("beforeclose",t.item)&&(t.item.fireEvent("close",t.item),this.remove(t.item)):t.item&&t.item!==this.activeTab&&(this.tabClicked=!0,this.setActiveTab(t.item))}}),MODx.Tabs=function(config={}){Ext.applyIf(config,{enableTabScroll:!0,layoutOnTabChange:!0,plain:!0,deferredRender:!0,hideMode:"offsets",defaults:{autoHeight:!0,hideMode:"offsets",border:!0,autoWidth:!0,bodyCssClass:"tab-panel-wrapper"},activeTab:0,tabClicked:!1,border:!1,autoScroll:!0,autoHeight:!0,cls:"modx-tabs",itemTpl:new Ext.XTemplate('
  • ','','','{text}',"","
  • ")}),MODx.Tabs.superclass.constructor.call(this,config),this.config=config,this.on({afterrender:function(tabPanel){if(MODx.request&&Object.prototype.hasOwnProperty.call(MODx.request,"tab")){const tabId=parseInt(MODx.request.tab,10);"modx-leftbar-tabpanel"!==this.id&&this.setActiveTab(tabId)}tabPanel.on({beforetabchange:function(tabPanelCmp,newTab,currentTab){if(this.tabClicked&&newTab&¤tTab&&newTab.id!==currentTab.id){const resetVerticalTabPanelFilters="modx-vtabs"===currentTab.items?.items[0]?.xtype||"modx-vtabs"===currentTab.ownerCt?.xtype,changedBetweenVtabs="modx-vtabs"===newTab.ownerCt?.xtype&&"modx-vtabs"===currentTab.ownerCt?.xtype;if("modx-usergroup-permissions-panel"===newTab.itemId&&!this.stateful){const vTabPanel=newTab.items?.items[0];vTabPanel&&"modx-vtabs"===vTabPanel.xtype&&vTabPanel.setActiveTab(0)}this.clearFiltersBeforeChange(currentTab,resetVerticalTabPanelFilters,changedBetweenVtabs)}}})}})},Ext.extend(MODx.Tabs,Ext.TabPanel,{findGridObject:function(itemsSource){const grid=itemsSource.find((obj=>Object.entries(obj).find((([key,value])=>"xtype"===key&&value.includes("-grid-")))));if(grid)return grid;const nextItemsSource=itemsSource?.items;nextItemsSource&&this.findGridObject(nextItemsSource)},clearFiltersBeforeChange:function(tabObj,resetVtabFilters,changedVtabs){let itemsSource,gridObj=null;if(itemsSource=resetVtabFilters?changedVtabs?tabObj.items:tabObj.items.items[0].activeTab.items:tabObj.items,itemsSource.length>0&&(gridObj=this.findGridObject(itemsSource),!gridObj)){let customItemsSource=null;itemsSource?.map["modx-tree-panel-usergroup"]?customItemsSource=itemsSource.map["modx-tree-panel-usergroup"].items:itemsSource?.map["packages-breadcrumbs"]&&(customItemsSource=itemsSource.map["card-container"].items.map["modx-panel-packages"].items),customItemsSource&&(gridObj=this.findGridObject(customItemsSource))}if(gridObj){const toolbar=gridObj.getTopToolbar(),filterIds=[];toolbar&&toolbar.items.items.length>0&&toolbar.items.items.forEach((cmp=>{cmp.xtype&&(cmp.xtype.includes("combo")||"textfield"===cmp.xtype)&&cmp.itemId&&filterIds.push(cmp.itemId)})),filterIds.length>0&&gridObj.clearGridFilters(filterIds)}}}),Ext.reg("modx-tabs",MODx.Tabs),MODx.VerticalTabs=function(config={}){Ext.applyIf(config,{cls:"vertical-tabs-panel",headerCfg:{tag:"div",cls:"x-tab-panel-header vertical-tabs-header"},bwrapCfg:{tag:"div",cls:"x-tab-panel-bwrap vertical-tabs-bwrap"},defaults:{bodyCssClass:"vertical-tabs-body",autoScroll:!0,autoHeight:!0,autoWidth:!0,layout:"form"}}),MODx.VerticalTabs.superclass.constructor.call(this,config),this.config=config,this.on({afterrender:function(){if(MODx.request&&Object.prototype.hasOwnProperty.call(MODx.request,"vtab")){const tabId=parseInt(MODx.request.vtab,10);this.setActiveTab(tabId)}}})},Ext.extend(MODx.VerticalTabs,MODx.Tabs),Ext.reg("modx-vtabs",MODx.VerticalTabs),Ext.Window.prototype.floating={shadow:!1},Ext.override(Ext.Window,{animShow:function(){this.afterShow();var win=this;setTimeout((function(){win.el.hasClass("anim-ready")||(win.el.addClass("anim-ready"),setTimeout((function(){void 0!==win.mask&&(win.mask instanceof Ext.Element?win.mask.addClass("fade-in"):win.mask.el.addClass("fade-in")),win.el.addClass("zoom-in")}),250))}),300)},animHide:function(){this.afterHide()},onShow:function(){if(this.el.hasClass("x-window-dlg"))this.mask.addClass("fade-in"),this.el.applyStyles({opacity:1});else{this.addClass("anim-ready");var win=this;setTimeout((function(){void 0!==win.mask&&(win.mask instanceof Ext.Element?win.mask.addClass("fade-in"):win.mask.el.addClass("fade-in")),win.el.addClass("zoom-in")}),250)}},onHide:function(){if(this.el.hasClass("zoom-in")){this.el.removeClass("zoom-in"),void 0!==this.mask&&(this.mask instanceof Ext.Element?this.mask.removeClass("fade-in"):this.mask.el.removeClass("fade-in")),this.addClass("zoom-out");var win=this;setTimeout((function(){win.isDestroyed||(win.el.hide(),win.el.removeClass("zoom-out"),win.el.removeClass("anim-ready"))}),250)}else this.el.hasClass("x-window-dlg")&&(this.el.applyStyles({opacity:0}),void 0!==this.mask&&(this.mask instanceof Ext.Element?this.mask.removeClass("fade-in"):this.mask.el.removeClass("fade-in")))}}),MODx.Window=function(config){config=config||{},Ext.applyIf(config,{modal:!1,layout:"auto",closeAction:"hide",shadow:!0,resizable:!0,collapsible:!0,maximizable:!0,autoHeight:!1,autoScroll:!0,allowDrop:!0,width:400,constrain:!0,constrainHeader:!0,cls:"modx-window",buttons:[{text:config.cancelBtnText||_("cancel"),scope:this,handler:function(){"close"!==config.closeAction?this.hide():this.close()}},{text:config.saveBtnText||_("save"),cls:"primary-button",scope:this,handler:this.submit}],record:{},keys:[{key:Ext.EventObject.ENTER,fn:function(keyCode,event){var elem=event.getTarget(),component=Ext.getCmp(elem.id);if(component instanceof Ext.form.TextArea)return component.append("\n");this.submit()},scope:this}]}),MODx.Window.superclass.constructor.call(this,config),this.options=config,this.config=config,this.addEvents({success:!0,failure:!0,beforeSubmit:!0,updateWindow:!1}),this._loadForm(),this.on("show",(function(){this.config.blankValues&&this.fp.getForm().reset(),this.config.allowDrop&&this.loadDropZones(),this.syncSize(),this.focusFirstField()}),this),this.on("afterrender",(function(){this.originalHeight=this.el.getHeight(),this.toolsHeight=this.originalHeight-this.body.getHeight()+50,this.resizeWindow()})),Ext.EventManager.onWindowResize(this.resizeWindow,this)},Ext.extend(MODx.Window,Ext.Window,{_loadForm:function(){if(this.checkIfLoaded(this.config.record||null))return!1;var r=this.config.record;if(this.config.fields)for(var l=this.config.fields.length,i=0;i0){var fld=this.findFirstTextField();fld&&fld.focus(!1,200)}},findFirstTextField:function(i){i=i||0;var fld=this.fp.getForm().items.itemAt(i);return!!fld&&((fld.isXType("combo")||fld.isXType("checkbox")||fld.isXType("radio")||fld.isXType("displayfield")||fld.isXType("statictextfield")||fld.isXType("hidden"))&&(i+=1,fld=this.findFirstTextField(i)),fld)},submit:function(close){close=!1!==close;var f=this.fp.getForm();f.isValid()&&this.fireEvent("beforeSubmit",f.getValues())&&f.submit({waitMsg:this.config.waitMsg||_("saving"),submitEmptyText:!1!==this.config.submitEmptyText,scope:this,failure:function(frm,a){this.fireEvent("failure",{f:frm,a})&&MODx.form.Handler.errorExt(a.result,frm),this.doLayout()},success:function(frm,a){this.config.success&&Ext.callback(this.config.success,this.config.scope||this,[frm,a]),this.fireEvent("success",{f:frm,a}),close&&("close"!==this.config.closeAction?this.hide():this.close()),this.doLayout()}})},createForm:function(config){return Ext.applyIf(this.config,{formFrame:!0,border:!1,bodyBorder:!1,autoHeight:!0}),config=config||{},Ext.applyIf(config,{labelAlign:this.config.labelAlign||"top",labelWidth:this.config.labelWidth||100,labelSeparator:this.config.labelSeparator||"",frame:this.config.formFrame,border:this.config.border,bodyBorder:this.config.bodyBorder,autoHeight:this.config.autoHeight,anchor:"100% 100%",errorReader:MODx.util.JSONReader,defaults:this.config.formDefaults||{msgTarget:this.config.msgTarget||"under"},url:this.config.url,baseParams:this.config.baseParams||{},fileUpload:this.config.fileUpload||!1}),new Ext.FormPanel(config)},renderForm:function(){this.fp.on("destroy",(function(){Ext.EventManager.removeResizeListener(this.resizeWindow,this)}),this),this.add(this.fp)},checkIfLoaded:function(r){return r=r||{},!(!this.fp||!this.fp.getForm())&&(this.fp.getForm().reset(),this.fp.getForm().setValues(r),!0)},setValues:function(r){if(null===r)return!1;this.fp.getForm().setValues(r)},reset:function(){this.fp.getForm().reset()},hideField:function(f){f.disable(),f.hide();var d=f.getEl().up(".x-form-item");d&&d.setDisplayed(!1)},showField:function(f){f.enable(),f.show();var d=f.getEl().up(".x-form-item");d&&d.setDisplayed(!0)},loadDropZones:function(){if(this._dzLoaded)return!1;this.fp.getForm().items.each((function(fld){fld.isFormField&&(fld.isXType("textfield")||fld.isXType("textarea"))&&!fld.isXType("combo")&&new MODx.load({xtype:"modx-treedrop",target:fld,targetEl:fld.getEl().dom})})),this._dzLoaded=!0},resizeWindow:function(){var viewHeight=Ext.getBody().getViewSize().height,el=this.fp.getForm().el;viewHeight
    {name:htmlEncode}',"
    {description:htmlEncode}
    ")}),MODx.combo.UserGroup.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.UserGroup,MODx.combo.ComboBox),Ext.reg("modx-combo-usergroup",MODx.combo.UserGroup),MODx.combo.UserGroupRole=function(config){config=config||{},Ext.applyIf(config,{name:"role",hiddenName:"role",displayField:"name",valueField:"id",fields:["name","id"],pageSize:20,url:MODx.config.connector_url,baseParams:{action:"Security/Role/GetList"}}),MODx.combo.UserGroupRole.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.UserGroupRole,MODx.combo.ComboBox),Ext.reg("modx-combo-usergrouprole",MODx.combo.UserGroupRole),MODx.combo.EventGroup=function(config){config=config||{},Ext.applyIf(config,{name:"group",hiddenName:"group",displayField:"name",valueField:"name",fields:["name"],pageSize:20,url:MODx.config.connector_url,baseParams:{action:"System/Event/GroupList"},tpl:new Ext.XTemplate('
    {name:htmlEncode}',"
    ")}),MODx.combo.EventGroup.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.EventGroup,MODx.combo.ComboBox),Ext.reg("modx-combo-eventgroup",MODx.combo.EventGroup),MODx.combo.ResourceGroup=function(config){config=config||{},Ext.applyIf(config,{name:"resourcegroup",hiddenName:"resourcegroup",displayField:"name",valueField:"id",fields:["name","id"],pageSize:20,url:MODx.config.connector_url,baseParams:{action:"Security/ResourceGroup/GetList"}}),MODx.combo.ResourceGroup.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.ResourceGroup,MODx.combo.ComboBox),Ext.reg("modx-combo-resourcegroup",MODx.combo.ResourceGroup),MODx.combo.Context=function(config){config=config||{},Ext.applyIf(config,{name:"context",hiddenName:"context",displayField:"key",valueField:"key",fields:["key","name"],pageSize:20,url:MODx.config.connector_url,baseParams:{action:"Context/GetList",exclude:config.exclude||""},tpl:new Ext.XTemplate('
    {name:htmlEncode} ({key:htmlEncode})
    ')}),MODx.combo.Context.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Context,MODx.combo.ComboBox),Ext.reg("modx-combo-context",MODx.combo.Context),MODx.combo.Policy=function(config){config=config||{},Ext.applyIf(config,{name:"policy",hiddenName:"policy",displayField:"name",valueField:"id",fields:["id","name","permissions"],allowBlank:!1,editable:!1,pageSize:20,url:MODx.config.connector_url,baseParams:{action:"Security/Access/Policy/GetList"}}),MODx.combo.Policy.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Policy,MODx.combo.ComboBox),Ext.reg("modx-combo-policy",MODx.combo.Policy),MODx.combo.Template=function(config){config=config||{},Ext.applyIf(config,{url:MODx.config.connector_url,baseParams:{action:"Element/Template/GetList",combo:!0},fields:["id","templatename","description","category_name","preview","time"],name:"template",hiddenName:"template",displayField:"templatename",valueField:"id",pageSize:20,allowBlank:!0,editable:!0,typeAhead:!0,tpl:new Ext.XTemplate('
    {this.label:htmlEncode}
    {templatename:htmlEncode}
    {description:htmlEncode()}
    ',{group:null,label:null,getGroup:function(label,time){var group=time+"_"+label;return group===this.group||Ext.isEmpty(group)?null:(this.group=group,this.label=label)}})}),MODx.combo.Template.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Template,MODx.combo.ComboBox),Ext.reg("modx-combo-template",MODx.combo.Template),MODx.combo.Category=function(config){config=config||{},Ext.applyIf(config,{name:"category",hiddenName:"category",displayField:"name",valueField:"id",fields:["id","category","parent","name"],forceSelection:!0,typeAhead:!1,allowBlank:!0,editable:!1,enableKeyEvents:!0,pageSize:20,url:MODx.config.connector_url,baseParams:{action:"Element/Category/GetList",showNone:!0,limit:0}}),MODx.combo.Category.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Category,MODx.combo.ComboBox,{_onblur:function(t,e){var v=this.getRawValue();this.setRawValue(v),this.setValue(v,!0)}}),Ext.reg("modx-combo-category",MODx.combo.Category),MODx.combo.Language=function(config){config=config||{},Ext.applyIf(config,{name:"language",hiddenName:"language",displayField:"name",valueField:"name",fields:["name"],typeAhead:!0,minChars:1,editable:!0,allowBlank:!0,url:MODx.config.connector_url,baseParams:{action:"System/Language/GetList"}}),MODx.combo.Language.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Language,MODx.combo.ComboBox),Ext.reg("modx-combo-language",MODx.combo.Language),MODx.combo.Charset=function(config){config=config||{},Ext.applyIf(config,{name:"charset",hiddenName:"charset",displayField:"text",valueField:"value",fields:["value","text"],forceSelection:!0,typeAhead:!1,editable:!1,allowBlank:!1,url:MODx.config.connector_url,baseParams:{action:"System/Charset/GetList"}}),MODx.combo.Charset.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Charset,MODx.combo.ComboBox),Ext.reg("modx-combo-charset",MODx.combo.Charset),MODx.combo.RTE=function(config){config=config||{},Ext.applyIf(config,{name:"rte",hiddenName:"rte",displayField:"value",valueField:"value",fields:["value"],forceSelection:!0,typeAhead:!1,editable:!1,allowBlank:!1,url:MODx.config.connector_url,baseParams:{action:"System/Rte/GetList"}}),MODx.combo.RTE.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.RTE,MODx.combo.ComboBox),Ext.reg("modx-combo-rte",MODx.combo.RTE),MODx.combo.Role=function(config){config=config||{},Ext.applyIf(config,{name:"role",hiddenName:"role",forceSelection:!0,typeAhead:!1,editable:!1,allowBlank:!1,pageSize:20,url:MODx.config.connector_url,baseParams:{action:"Security/Role/GetList",addNone:!0}}),MODx.combo.Role.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Role,MODx.combo.ComboBox),Ext.reg("modx-combo-role",MODx.combo.Role),MODx.combo.ContentType=function(config){config=config||{},Ext.applyIf(config,{name:"content_type",hiddenName:"content_type",forceSelection:!0,typeAhead:!1,editable:!1,allowBlank:!1,pageSize:20,url:MODx.config.connector_url,baseParams:{action:"System/ContentType/GetList"}}),MODx.combo.ContentType.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.ContentType,MODx.combo.ComboBox),Ext.reg("modx-combo-content-type",MODx.combo.ContentType),MODx.combo.ContentDisposition=function(config){config=config||{},Ext.applyIf(config,{store:new Ext.data.SimpleStore({fields:["d","v"],data:[[_("inline"),0],[_("attachment"),1]]}),name:"content_dispo",hiddenName:"content_dispo",displayField:"d",valueField:"v",mode:"local",triggerAction:"all",editable:!1,pageSize:20,selectOnFocus:!1,preventRender:!0}),MODx.combo.ContentDisposition.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.ContentDisposition,MODx.combo.ComboBox),Ext.reg("modx-combo-content-disposition",MODx.combo.ContentDisposition),MODx.combo.ClassDerivatives=function(config){config=config||{},Ext.applyIf(config,{name:"class",hiddenName:"class",url:MODx.config.connector_url,baseParams:{action:"System/Derivatives/GetList",class:"MODX\\Revolution\\modResource"},displayField:"name",valueField:"id",fields:["id","name"],forceSelection:!0,typeAhead:!1,editable:!1,allowBlank:!1,pageSize:20}),MODx.combo.ClassDerivatives.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.ClassDerivatives,MODx.combo.ComboBox),Ext.reg("modx-combo-class-derivatives",MODx.combo.ClassDerivatives),MODx.combo.Namespace=function(config){config=config||{},Ext.applyIf(config,{name:"namespace",hiddenName:"namespace",typeAhead:!0,minChars:1,queryParam:"query",editable:!0,allowBlank:!0,preselectValue:!1,pageSize:20,url:MODx.config.connector_url,baseParams:{action:"Workspace/PackageNamespace/GetList"},fields:["name"],displayField:"name",valueField:"name"}),MODx.combo.Namespace.superclass.constructor.call(this,config),!1!==config.preselectValue&&(this.store.on("load",this.preselectFirstValue,this,{single:!0}),this.store.load())},Ext.extend(MODx.combo.Namespace,MODx.combo.ComboBox,{preselectFirstValue:function(r){var item;if(""==this.config.preselectValue)item=r.getAt(0);else{var found=r.find("name",this.config.preselectValue);item=-1!=found?r.getAt(found):r.getAt(0)}item&&(this.setValue(item.data.name),this.fireEvent("select",this,item))}}),Ext.reg("modx-combo-namespace",MODx.combo.Namespace),MODx.combo.Browser=function(config){config=config||{},Ext.applyIf(config,{width:400,triggerAction:"all",triggerClass:"x-form-file-trigger",source:config.source||MODx.config.default_media_source}),MODx.combo.Browser.superclass.constructor.call(this,config),this.config=config},Ext.extend(MODx.combo.Browser,Ext.form.TriggerField,{browser:null,onTriggerClick:function(btn){return!this.disabled&&(this.browser=MODx.load({xtype:"modx-browser",closeAction:"close",id:Ext.id(),multiple:!0,source:this.config.source||MODx.config.default_media_source,hideFiles:this.config.hideFiles||!1,rootVisible:this.config.rootVisible||!1,allowedFileTypes:this.config.allowedFileTypes||"",wctx:this.config.wctx||"web",openTo:this.config.openTo||"",rootId:this.config.rootId||"/",hideSourceCombo:this.config.hideSourceCombo||!1,listeners:{select:{fn:function(data){this.setValue(data.relativeUrl),this.fireEvent("select",data)},scope:this}}}),this.browser.show(btn),!0)},onDestroy:function(){MODx.combo.Browser.superclass.onDestroy.call(this)}}),Ext.reg("modx-combo-browser",MODx.combo.Browser),MODx.combo.Country=function(config){config=config||{},Ext.applyIf(config,{name:"country",hiddenName:"country",url:MODx.config.connector_url,baseParams:{action:"System/Country/GetList",combo:!0},displayField:"country",valueField:"iso",fields:["iso","country","value"],editable:!0,typeAhead:!0}),MODx.combo.Country.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Country,MODx.combo.ComboBox),Ext.reg("modx-combo-country",MODx.combo.Country),MODx.combo.Gender=function(config){config=config||{},Ext.applyIf(config,{store:new Ext.data.SimpleStore({fields:["d","v"],data:[["",0],[_("user_male"),1],[_("user_female"),2],[_("user_other"),3]]}),displayField:"d",valueField:"v",mode:"local",triggerAction:"all",editable:!1,selectOnFocus:!1}),MODx.combo.Gender.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Gender,Ext.form.ComboBox),Ext.reg("modx-combo-gender",MODx.combo.Gender),MODx.combo.PropertySet=function(config){config=config||{},Ext.applyIf(config,{name:"propertyset",hiddenName:"propertyset",url:MODx.config.connector_url,baseParams:{action:"Element/PropertySet/GetList"},displayField:"name",valueField:"id",fields:["id","name"],editable:!1,pageSize:20,width:300}),MODx.combo.PropertySet.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.PropertySet,MODx.combo.ComboBox),Ext.reg("modx-combo-property-set",MODx.combo.PropertySet),MODx.ChangeParentField=function(config){config=config||{},Ext.applyIf(config,{triggerAction:"all",editable:!1,readOnly:!1,formpanel:"modx-panel-resource",parentcmp:"modx-resource-parent-hidden",contextcmp:"modx-resource-context-key",currentid:MODx.request.id}),MODx.ChangeParentField.superclass.constructor.call(this,config),this.config=config,this.on("click",this.onTriggerClick,this),this.addEvents({end:!0}),this.on("end",this.end,this)},Ext.extend(MODx.ChangeParentField,Ext.form.TriggerField,{oldValue:!1,oldDisplayValue:!1,end:function(p){var t=Ext.getCmp("modx-resource-tree");t&&(p.d=p.d||p.v,t.removeListener("click",this.handleChangeParent,this),t.on("click",t._handleClick,t),t.disableHref=!1,MODx.debug("Setting parent to: "+p.v),Ext.getCmp(this.config.parentcmp).setValue(p.v),this.setValue(p.d),this.oldValue=!1,"modx-template-picker-parent-id"!==this.config.parentcmp&&Ext.getCmp(this.config.formpanel).fireEvent("fieldChange"))},onTriggerClick:function(){if(this.disabled)return!1;if(this.oldValue)return this.fireEvent("end",{v:this.oldValue,d:this.oldDisplayValue}),!1;if(MODx.debug("onTriggerClick"),!Ext.getCmp("modx-resource-tree")){MODx.debug("no tree found, trying to activate");var tp=Ext.getCmp("modx-leftbar-tabpanel");return tp?(tp.on("tabchange",(function(tbp,tab){"modx-resource-tree-ct"==tab.id&&this.disableTreeClick()}),this),tp.activate("modx-resource-tree-ct")):MODx.debug("no tabpanel"),!1}this.disableTreeClick()},disableTreeClick:function(){return MODx.debug("Disabling tree click"),t=Ext.getCmp("modx-resource-tree"),t?(this.oldDisplayValue=this.getValue(),this.oldValue=Ext.getCmp(this.config.parentcmp).getValue(),this.setValue(_("resource_parent_select_node")),t.expand(),t.removeListener("click",t._handleClick),t.on("click",this.handleChangeParent,this),t.disableHref=!0,!0):(MODx.debug("No tree found in disableTreeClick!"),!1)},handleChangeParent:function(node,e){var t=Ext.getCmp("modx-resource-tree");if(!t)return!1;t.disableHref=!0;var id=node.id.split("_");if((id=id[1])==this.config.currentid)return MODx.msg.alert("",_("resource_err_own_parent")),!1;var ctxf=Ext.getCmp(this.config.contextcmp);if(ctxf){var ctxv=ctxf.getValue();node.attributes&&node.attributes.ctx!=ctxv&&ctxf.setValue(node.attributes.ctx)}return this.fireEvent("end",{v:"modContext"!=node.attributes.type?id:node.attributes.pk,d:Ext.util.Format.stripTags(node.text)}),e.preventDefault(),e.stopEvent(),!0}}),Ext.reg("modx-field-parent-change",MODx.ChangeParentField),MODx.combo.TVWidget=function(config){config=config||{},Ext.applyIf(config,{name:"widget",hiddenName:"widget",displayField:"name",valueField:"value",fields:["value","name"],editable:!1,url:MODx.config.connector_url,baseParams:{action:"Element/TemplateVar/Renders/GetOutputs"},value:"default"}),MODx.combo.TVWidget.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.TVWidget,MODx.combo.ComboBox),Ext.reg("modx-combo-tv-widget",MODx.combo.TVWidget),MODx.combo.TVInputType=function(config){config=config||{},Ext.applyIf(config,{name:"type",hiddenName:"type",displayField:"name",valueField:"value",editable:!1,fields:["value","name"],url:MODx.config.connector_url,baseParams:{action:"Element/TemplateVar/Renders/GetInputs"},value:"text"}),MODx.combo.TVInputType.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.TVInputType,MODx.combo.ComboBox),Ext.reg("modx-combo-tv-input-type",MODx.combo.TVInputType),MODx.combo.Dashboard=function(config){config=config||{},Ext.applyIf(config,{name:"dashboard",hiddenName:"dashboard",displayField:"name",valueField:"id",fields:["id","name","description"],pageSize:20,url:MODx.config.connector_url,baseParams:{action:"System/Dashboard/GetList"},tpl:new Ext.XTemplate('','
    ','

    {name:htmlEncode}

    ','

    {description:htmlEncode}

    ',"
    ")}),MODx.combo.Dashboard.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Dashboard,MODx.combo.ComboBox),Ext.reg("modx-combo-dashboard",MODx.combo.Dashboard),MODx.combo.MediaSource=function(config){config=config||{},Ext.applyIf(config,{name:"source",hiddenName:"source",displayField:"name",valueField:"id",fields:["id","name","description"],pageSize:20,url:MODx.config.connector_url,baseParams:{action:"Source/GetList"},tpl:new Ext.XTemplate('','
    ','

    {name:htmlEncode}

    ','

    {description:htmlEncode}

    ',"
    ")}),MODx.combo.MediaSource.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.MediaSource,MODx.combo.ComboBox),Ext.reg("modx-combo-source",MODx.combo.MediaSource),MODx.combo.MediaSourceType=function(config){config=config||{},Ext.applyIf(config,{name:"class_key",hiddenName:"class_key",displayField:"name",valueField:"class",fields:["id","class","name","description"],pageSize:20,url:MODx.config.connector_url,baseParams:{action:"Source/Type/GetList"},tpl:new Ext.XTemplate('','
    ','

    {name:htmlEncode}

    ','

    {description:htmlEncode}

    ',"
    ")}),MODx.combo.MediaSourceType.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.MediaSourceType,MODx.combo.ComboBox),Ext.reg("modx-combo-source-type",MODx.combo.MediaSourceType),MODx.combo.Authority=function(config){config=config||{},Ext.applyIf(config,{name:"authority",hiddenName:"authority",forceSelection:!0,typeAhead:!1,editable:!1,allowBlank:!1,pageSize:20,url:MODx.config.connector_url,baseParams:{action:"Security/Role/GetAuthorityList",addNone:!0}}),MODx.combo.Authority.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Authority,MODx.combo.ComboBox),Ext.reg("modx-combo-authority",MODx.combo.Authority),MODx.combo.ManagerTheme=function(config){config=config||{},Ext.applyIf(config,{name:"theme",hiddenName:"theme",displayField:"theme",valueField:"theme",fields:["theme"],url:MODx.config.connector_url,baseParams:{action:"Workspace/Theme/GetList"},typeAhead:!1,editable:!1}),MODx.combo.ManagerTheme.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.ManagerTheme,MODx.combo.ComboBox),Ext.reg("modx-combo-manager-theme",MODx.combo.ManagerTheme),MODx.combo.SettingKey=function(config){config=config||{},Ext.applyIf(config,{name:"key",hiddenName:"key",displayField:"key",valueField:"key",fields:["key"],url:MODx.config.connector_url,baseParams:{action:"System/Settings/GetList"},triggerAction:"all",editable:!0,forceSelection:!1,pageSize:20}),MODx.combo.SettingKey.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.SettingKey,MODx.combo.ComboBox),Ext.reg("modx-combo-setting-key",MODx.combo.SettingKey),MODx.combo.Visibility=function(config){config=config||{},Ext.applyIf(config,{name:"visibility",hiddenName:"visibility",store:new Ext.data.SimpleStore({fields:["d","v"],data:[[_("file_folder_visibility_public"),"public"],[_("file_folder_visibility_private"),"private"]]}),displayField:"d",valueField:"v",mode:"local",triggerAction:"all",editable:!1,selectOnFocus:!1,preventRender:!0,forceSelection:!0,enableKeyEvents:!0}),MODx.combo.Visibility.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Visibility,MODx.combo.ComboBox),Ext.reg("modx-combo-visibility",MODx.combo.Visibility),MODx.combo.Permission=function(config){config=config||{},Ext.applyIf(config,{name:"permission",hiddenName:"permission",displayField:"name",valueField:"name",fields:["name","description"],editable:!0,typeAhead:!1,forceSelection:!1,enableKeyEvents:!0,autoSelect:!1,pageSize:20,tpl:new Ext.XTemplate('
    {name:htmlEncode}','

    {description:htmlEncode}

    '),url:MODx.config.connector_url,baseParams:{action:"Security/Access/Permission/GetList"}}),MODx.combo.Permission.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Permission,MODx.combo.ComboBox),Ext.reg("modx-combo-permission",MODx.combo.Permission),Ext.namespace("MODx.grid"),MODx.grid.Grid=function(config={}){if(this.config=config,this._loadStore(),this._loadColumnModel(),Ext.applyIf(config,{store:this.store,cm:this.cm,sm:new Ext.grid.RowSelectionModel({singleSelect:!0}),paging:!!config.bbar,loadMask:!0,autoHeight:!0,collapsible:!0,stripeRows:!0,header:!1,cls:"modx-grid",preventRender:!0,preventSaveRefresh:!0,showPerPage:!0,stateful:!1,showActionsColumn:!0,disableContextMenuAction:!1,menuConfig:{defaultAlign:"tl-b?",enableScrolling:!1},viewConfig:{forceFit:!0,enableRowBody:!0,autoFill:!0,showPreview:!0,scrollOffset:0,emptyText:config.emptyText||_("ext_emptymsg")},groupingConfig:{enableGroupingMenu:!0}}),config.paging){var pgItms=config.showPerPage?[_("per_page")+":",{xtype:"textfield",cls:"x-tbar-page-size",value:config.pageSize||parseInt(MODx.config.default_per_page)||20,listeners:{change:{fn:this.onChangePerPage,scope:this},render:{fn:function(cmp){new Ext.KeyMap(cmp.getEl(),{key:Ext.EventObject.ENTER,fn:this.blur,scope:cmp})},scope:this}}}]:[];if(config.pagingItems)for(var i=0;i 1 ? "'+(config.pluralText||_("records"))+'" : "'+(config.singleText||_("record"))+'"]})'};Ext.applyIf(config.groupingConfig,groupingConfig),Ext.applyIf(config,{view:new Ext.grid.GroupingView(config.groupingConfig)})}if(config.tbar)for(var ix=0;ix1)return!1;return!0};config.columns&&Array.isArray(config.columns)&&(void 0===config.actionsColumnWidth&&isPercentage(config.columns)&&(defaultActionsColumnWidth=.1),config.columns.push({id:"modx-actions",width:config.actionsColumnWidth||defaultActionsColumnWidth,menuDisabled:!0,renderer:this.actionsColumnRenderer.bind(this)})),config.cm&&config.cm.columns&&Array.isArray(config.cm.columns)&&(void 0===config.actionsColumnWidth&&isPercentage(config.cm.columns)&&(defaultActionsColumnWidth=.1),config.cm.columns.push({id:"modx-actions",width:config.actionsColumnWidth||defaultActionsColumnWidth,menuDisabled:!0,renderer:this.actionsColumnRenderer.bind(this)}))}MODx.grid.Grid.superclass.constructor.call(this,config),this._loadMenu(config),this.addEvents("beforeRemoveRow","afterRemoveRow","afterAutoSave"),this.autosave&&this.on("afterAutoSave",this.onAfterAutoSave,this),config.preventRender||this.render(),this.on({render:{fn:function(){const topToolbar=this.getTopToolbar();topToolbar&&topToolbar.initialConfig.cls&&"has-nested-filters"==topToolbar.initialConfig.cls&&(this.hasNestedFilters=!0)},scope:this},rowcontextmenu:{fn:this._showMenu,scope:this}}),config.autosave&&this.on("afteredit",this.saveRecord,this),config.paging&&config.grouping&&this.getBottomToolbar().bind(this.store),config.paging||config.hasOwnProperty("pageSize")||(config.pageSize=0),this.getStore().load({params:{start:config.pageStart||0,limit:config.hasOwnProperty("pageSize")?config.pageSize:parseInt(MODx.config.default_per_page)||20}}),this.getStore().on("exception",this.onStoreException,this),this.config=config,this.on("click",this.onClickHandler,this)},Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{windows:{},onStoreException:function(dataProxy,type,action,options,response){const responseStatusCode=response.status||"Unknown",responseStatusText=Ext.isEmpty(response.statusText)?"":`(${response.statusText})`;let output="",msg="";if(Ext.isEmpty(response.responseText))output=200!==responseStatusCode?`
    ${responseStatusCode} ${responseStatusText}
    `:"";else try{const responseText=Ext.decode(response.responseText);responseText&&responseText.message&&(output=responseText.message)}catch(e){output=response.responseText}output?MODx.config.debug>0?(output=MODx.util.safeHtml(output,"
    ","class,colspan,rowspan"),msg=_("error_grid_get_content_toscreen",{message:`
    ${output}
    `})):(msg=_("error_grid_get_content_tolog"),output=Ext.util.Format.stripTags(output).replaceAll(">",">").replaceAll("<","<"),console.error(output)):msg=_("error_grid_get_content_no_msg"),this.getView().emptyText=`
    ${msg}
    `,this.getView().refresh(!1)},saveRecord:function(e){e.record.data.menu=null;var p=this.config.saveParams||{};Ext.apply(e.record.data,p);var d=Ext.util.JSON.encode(e.record.data),url=this.config.saveUrl||this.config.url||this.config.connector;MODx.Ajax.request({url,params:{action:this.config.save_action||"updateFromGrid",data:d},listeners:{success:{fn:function(r){if(this.config.save_callback&&Ext.callback(this.config.save_callback,this.config.scope||this,[r]),e.record.commit(),!this.config.preventSaveRefresh){new Ext.util.DelayedTask((()=>this.refresh())).delay(200)}this.fireEvent("afterAutoSave",r)},scope:this},failure:{fn:function(r){e.record.reject(),this.fireEvent("afterAutoSave",r)},scope:this}}})},onAfterAutoSave:function(response){if(!response.success&&""===response.message){var msg="";response.data.length&&Ext.each(response.data,(function(data,index,list){msg+=(""!=msg?"
    ":"")+data.msg}),this),Ext.isEmpty(msg)&&(msg=this.autosaveErrorMsg||_("error")),MODx.msg.alert(_("error"),msg)}},onChangePerPage:function(tf,nv){if(Ext.isEmpty(nv))return!1;nv=parseInt(nv),this.getBottomToolbar().pageSize=nv,this.store.load({params:{start:0,limit:nv}})},loadWindow:function(btn,e,win,or){var r=this.menu.record;this.windows[win.xtype]&&!win.force||(Ext.applyIf(win,{record:win.blankValues?{}:r,grid:this,listeners:{success:{fn:win.success||this.refresh,scope:win.scope||this}}}),or&&Ext.apply(win,or),this.windows[win.xtype]=Ext.ComponentMgr.create(win)),this.windows[win.xtype].setValues&&!0!==win.blankValues&&null!=r&&this.windows[win.xtype].setValues(r),this.windows[win.xtype].show(e.target)},confirm:function(type,text){var p={action:type},k=this.config.primaryKey||"id";p[k]=this.menu.record[k],MODx.msg.confirm({title:_(type),text:_(text)||_("confirm_remove"),url:this.config.url,params:p,listeners:{success:{fn:this.refresh,scope:this}}})},remove:function(text,action){if(this.destroying)return MODx.grid.Grid.superclass.remove.apply(this,arguments);var r=this.menu.record;text=text||"confirm_remove";var p=this.config.saveParams||{};Ext.apply(p,{action:action||"remove"});var k=this.config.primaryKey||"id";p[k]=r[k],this.fireEvent("beforeRemoveRow",r)&&MODx.msg.confirm({title:_("warning"),text:_(text,r),url:this.config.url,params:p,listeners:{success:{fn:function(){this.removeActiveRow(r)},scope:this}}})},removeActiveRow:function(r){if(this.fireEvent("afterRemoveRow",r)){var rx=this.getSelectionModel().getSelected();this.getStore().remove(rx)}},_loadMenu:function(){this.menu=new Ext.menu.Menu(this.config.menuConfig)},_showMenu:function(g,ri,e){if(e.stopEvent(),e.preventDefault(),this.menu.record=this.getStore().getAt(ri).data,this.getSelectionModel().isSelected(ri)||this.getSelectionModel().selectRow(ri),this.menu.removeAll(),this.getMenu){var m=this.getMenu(g,ri,e);m&&m.length&&m.length>0&&this.addContextMenuItem(m)}(!m||m.length<=0)&&this.menu.record.menu&&this.addContextMenuItem(this.menu.record.menu),this.menu.items.length>0&&this.menu.showAt(e.xy)},_loadStore:function(){this.config.grouping?this.store=new Ext.data.GroupingStore({url:this.config.url,baseParams:this.config.baseParams||{action:this.config.action||"getList"},reader:new Ext.data.JsonReader({totalProperty:"total",root:"results",fields:this.config.fields}),sortInfo:{field:this.config.sortBy||"id",direction:this.config.sortDir||"ASC"},remoteSort:this.config.remoteSort||!1,remoteGroup:this.config.remoteGroup||!1,groupField:this.config.groupBy||"name",groupDir:this.config.groupDir||"ASC",storeId:this.config.storeId||Ext.id(),autoDestroy:!0,listeners:{beforeload:function(store,options){store.groupField===store.sortInfo.field&&store.groupDir!==store.sortInfo.direction&&(store.groupDir=store.sortInfo.direction,store.baseParams.groupDir=store.sortInfo.direction)},load:function(store,records,options){const cmp=Ext.getCmp("modx-content");cmp&&cmp.doLayout()},groupchange:{fn:function(store,groupField){store.groupDir=this.config.groupDir||"ASC",store.baseParams.groupDir=store.groupDir,store.sortInfo.direction=this.config.sortDir||"ASC",store.load()},scope:this}}}):this.store=new Ext.data.JsonStore({url:this.config.url,baseParams:this.config.baseParams||{action:this.config.action||"getList"},fields:this.config.fields,root:"results",totalProperty:"total",remoteSort:this.config.remoteSort||!1,storeId:this.config.storeId||Ext.id(),autoDestroy:!0,listeners:{load:function(){const cmp=Ext.getCmp("modx-content");cmp&&cmp.doLayout()}}})},_loadColumnModel:function(){if(this.config.columns){for(var c=this.config.columns,i=0;i
    ',{compiled:!0})},actionsColumnRenderer:function(value,metaData,record,rowIndex,colIndex,store){var actions=this.getActions.apply(this,[record,rowIndex,colIndex,store]);return!0!==this.config.disableContextMenuAction&&actions.push({text:_("context_menu"),action:"contextMenu",icon:"gear"}),this._getActionsColumnTpl().apply({actions})},renderLink:function(v,attr){var el=new Ext.Element(document.createElement("a"));for(var i in el.addClass("x-grid-link"),el.dom.title=_("edit"),attr)el.dom[i]=attr[i];return el.dom.innerHTML=Ext.util.Format.htmlEncode(v),el.dom.outerHTML},checkEditable:function(e){this.checkCellIsEditable(e)},checkCellIsEditable:function(e){if(-1===(e.record.data.perm||"").indexOf("edit"))return!1;switch(e.grid.xtype){case"modx-grid-role":{const isAuthorityField="authority"===e.field;if(e.record.json.isAssigned&&isAuthorityField)return!1;break}}return!0},setEditableCellClasses:function(record,lockConditions=[],lockedClasses="locked",conditionsRequireAll=!0){const permissions=record.data.perm.trim(),hasEditPermission=permissions.split(" ").includes("edit");let classes="",shouldLock=!1;return lockConditions.length>0&&(shouldLock=conditionsRequireAll?lockConditions.every((condition=>!0===Boolean(condition))):lockConditions.some((condition=>!0===Boolean(condition)))),Ext.isEmpty(permissions)?classes="editor-disabled":hasEditPermission&&shouldLock&&(classes=lockedClasses),classes},getLinkTemplate:function(controllerPath,displayValueIndex,options={}){Ext.applyIf(options,{linkParams:[],linkClass:"x-grid-link",linkTitle:_("edit"),linkTarget:"_blank"});let params="";return controllerPath=0===controllerPath.indexOf("?a=")?controllerPath:`?a=${controllerPath}`,options.linkParams.length>0&&(params=[],options.linkParams.forEach((param=>{params.push(`${param.key}={${param.valueIndex}}`)})),params=`&${params.join("&")}`),new Ext.Template(`{${displayValueIndex}:htmlEncode}`,{compiled:!0})},getActions:function(record,rowIndex,colIndex,store){return[]},onClickHandler:function(e){var target=e.getTarget();if(target.classList.contains("x-grid-action")&&target.dataset.action){var actionHandler="action"+target.dataset.action.charAt(0).toUpperCase()+target.dataset.action.slice(1);if(this[actionHandler]&&"function"==typeof this[actionHandler]||this[actionHandler=target.dataset.action]&&"function"==typeof this[actionHandler]){var record=this.getSelectionModel().getSelected(),recordIndex=this.store.indexOf(record);this.menu.record=record.data,this[actionHandler](record,recordIndex,e)}}},actionContextMenu:function(record,recordIndex,e){this._showMenu(this,recordIndex,e)},makeUrl:function(){if(Array.isArray(this.config.urlFilters)&&this.config.urlFilters.length>0){var s=this.getStore(),p={a:MODx.request.a};MODx.request.id&&(p.id=MODx.request.id),MODx.request.key&&(p.key=MODx.request.key);for(var i=0;i0&&window.history.replaceState(this.getStore().baseParams,document.title,this.makeUrl())},findTabPanel:function(referenceCmp){if(!referenceCmp.hasOwnProperty("ownerCt"))return console.error("MODx.grid.Grid::findTabPanel: This component must have an ownerCt to find its tab panel."),!1;const container=referenceCmp.ownerCt;return container.hasOwnProperty("xtype")&&container.xtype.includes("tabs")?container:this.findTabPanel(container)},hasNestedFilters:!1,currentLanguage:MODx.config.cultureKey||"en",applyRequestFilter:function(tabPanelIndex,requestKey="policy",tabPanelType="vtab",setEmptyToString=!1){const emptyVal=setEmptyToString?"":null;return Object.prototype.hasOwnProperty.call(MODx.request,tabPanelType)&&parseInt(MODx.request[tabPanelType],10)===tabPanelIndex&&Object.prototype.hasOwnProperty.call(MODx.request,requestKey)?MODx.util.url.getParamValue(requestKey):emptyVal},applyGridFilter:function(cmp,param="query"){const filterValue=cmp.getValue(),store=this.getStore(),urlParams={},tabPanel=this.findTabPanel(this),bottomToolbar=this.getBottomToolbar();let parentTabItems,activeParentTabIdx,hasParentTabPanel=!1;if(Ext.isEmpty(filterValue)?MODx.request[param]?urlParams[param]=MODx.request[param]:MODx.util.url.clearParam(cmp):urlParams[param]=filterValue,"ns"==param?store.baseParams.namespace=filterValue:store.baseParams[param]=filterValue,tabPanel){if("modx-vtabs"==tabPanel.xtype){const parentTabPanel=this.findTabPanel(tabPanel);if(parentTabPanel){const activeParentTab=parentTabPanel.getActiveTab();hasParentTabPanel=!0,parentTabItems=parentTabPanel.items,activeParentTabIdx=parentTabItems.indexOf(activeParentTab)}}const activeTab=tabPanel.getActiveTab(),tabItems=tabPanel.items,activeTabIdx=tabItems.indexOf(activeTab);hasParentTabPanel?(tabItems.length>1&&(urlParams.vtab=activeTabIdx),parentTabItems.length>1&&(urlParams.tab=activeParentTabIdx)):tabItems.length>1&&(urlParams.tab=activeTabIdx)}store.load(),MODx.util.url.setParams(urlParams),bottomToolbar&&bottomToolbar.changePage(1)},clearGridFilters:function(items){const store=this.getStore(),bottomToolbar=this.getBottomToolbar();(Array.isArray(items)?items:items.split(",")).forEach((item=>{const itemData=item.replace(/\s+/g,"").split(":"),itemId=itemData[0],itemDefaultVal=2==itemData.length?itemData[1]:null,cmp=this.getFilterComponent(itemId),param=MODx.util.url.getParamNameFromCmp(cmp),isCombo=cmp?.xtype?.includes("combo");if(isCombo?""===itemDefaultVal?cmp.setValue(null):cmp.setValue(itemDefaultVal):cmp.setValue(""),!Ext.isEmpty(itemDefaultVal)){Object.keys(cmp.baseParams).forEach((param=>{switch(param){case"namespace":cmp.baseParams[param]="core";break;case"topic":cmp.baseParams[param]="default"}}))}isCombo&&"local"!==cmp.mode&&cmp.getStore().load(),store.baseParams[param]=itemDefaultVal})),store.load(),MODx.util.url.clearAllParams(),bottomToolbar&&bottomToolbar.changePage(1)},hasNestedFilters:!1,getFilterComponent:function(filterId){const topToolbar=this.getTopToolbar(),cmp=this.hasNestedFilters&&"filter-query"!==filterId?topToolbar.find("itemId",`${filterId}-container`)[0].getComponent(filterId):topToolbar.getComponent(filterId);if(void 0!==cmp)return cmp;console.error(`getFilterComponent: The filter component with itemId '${filterId}' could not be retrieved.`)},refreshFilterOptions:function(filterData=[],clearDependentParams=!0){filterData.length>0&&(filterData.forEach((data=>{const filter=this.getFilterComponent(data.filterId);if(filter){const store=filter.getStore();if(filter.setValue(""),store){if(data.hasOwnProperty("dependentParams")){(Array.isArray(data.dependentParams)?data.dependentParams:data.dependentParams.split(",")).forEach((param=>{clearDependentParams&&store.baseParams.hasOwnProperty(param)&&(store.baseParams[param]="")}))}store.load()}}})),this.refresh())},updateDependentFilter:function(filterId,paramKey,paramValue,clearValue=!1){const filter=this.getFilterComponent(filterId),filterStore=filter?filter.getStore():null;filterStore&&"string"==typeof paramKey&&(clearValue&&filter.setValue(""),filterStore.baseParams[paramKey]=paramValue,filterStore.load())},getQueryFilterField:function(filterSpec="filter-query",implementation="default"){let queryValue="";const filterSpecs=filterSpec.split(":"),filterId=filterSpecs[0].trim();return queryValue=2===filterSpecs.length?filterSpecs[1]:MODx.request.query?MODx.util.url.decodeParamValue(MODx.request.query):"",{xtype:"textfield",itemId:filterId,emptyText:_("search"),value:queryValue,cls:"filter-query",listeners:{change:{fn:function(cmp,newValue,oldValue){this.applyGridFilter(cmp);const usergroupTree=Ext.getCmp("modx-tree-usergroup");if("user-group-users"===implementation&&usergroupTree){const selectedNode=usergroupTree.getSelectionModel().getSelectedNode(),groupId=MODx.util.tree.getGroupIdFromNode(selectedNode);MODx.util.url.setParams({group:groupId})}},scope:this},afterrender:{fn:function(cmp){MODx.request.query&&this.applyGridFilter(cmp)},scope:this},render:{fn:function(cmp){new Ext.KeyMap(cmp.getEl(),{key:Ext.EventObject.ENTER,fn:this.blur,scope:cmp})},scope:this}}}},getClearFiltersButton:function(filters="filter-query",dependentFilterResets=null){if(Ext.isEmpty(filters))return console.error("MODx.grid.Grid::getClearFiltersButton: There was a problem creating the Clear Filter button because the supplied filters list is invalid."),{};const config={text:_("filter_clear"),itemId:"filter-clear",listeners:{click:{fn:function(cmp){if(cmp.dependentResets){cmp.dependentResets.split(",").forEach((reset=>{const[filterId,filterDataIndex]=reset.split(":").map((item=>item.trim()));this.updateDependentFilter(filterId,filterDataIndex,"",!0)}))}this.clearGridFilters(filters)},scope:this},mouseout:{fn:function(evt){this.removeClass("x-btn-focus")}}}};return dependentFilterResets&&(config.dependentResets=dependentFilterResets),config},getCategoryFilterValue:()=>void 0===MODx.request.tab||void 0===MODx.request.category?null:Math.abs(parseInt(MODx.request.category,10))}),MODx.grid.LocalGrid=function(config){if((config=config||{}).grouping&&Ext.applyIf(config,{view:new Ext.grid.GroupingView({forceFit:!0,scrollOffset:0,hideGroupedColumn:!!config.hideGroupedColumn,groupTextTpl:config.groupTextTpl||'{text} ({[values.rs.length]} {[values.rs.length > 1 ? "'+(config.pluralText||_("records"))+'" : "'+(config.singleText||_("record"))+'"]})'})}),config.tbar)for(var i=0;i
    ',{compiled:!0})},actionsColumnRenderer:function(value,metaData,record,rowIndex,colIndex,store){var actions=this.getActions.apply(this,arguments);return!0!==this.config.disableContextMenuAction&&actions.push({text:_("context_menu"),action:"contextMenu",icon:"gear"}),this._getActionsColumnTpl().apply({actions})},renderLink:function(v,attr){var el=new Ext.Element(document.createElement("a"));for(var i in el.addClass("x-grid-link"),el.dom.title=_("edit"),attr)el.dom[i]=attr[i];return el.dom.innerHTML=Ext.util.Format.htmlEncode(v),el.dom.outerHTML},getActions:function(value,metaData,record,rowIndex,colIndex,store){return[]},onClick:function(e){var target=e.getTarget();if(target.classList.contains("x-grid-action")&&target.dataset.action){var actionHandler="action"+target.dataset.action.charAt(0).toUpperCase()+target.dataset.action.slice(1);if(this[actionHandler]&&"function"==typeof this[actionHandler]||this[actionHandler=target.dataset.action]&&"function"==typeof this[actionHandler]){var record=this.getSelectionModel().getSelected(),recordIndex=this.store.indexOf(record);this.menu.record=record.data,this[actionHandler](record,recordIndex,e)}}},actionContextMenu:function(record,recordIndex,e){this._showMenu(this,recordIndex,e)}}),Ext.reg("grid-local",MODx.grid.LocalGrid),Ext.reg("modx-grid-local",MODx.grid.LocalGrid), +Ext.ns("Ext.ux.form"),Ext.ux.form.FileUploadField=Ext.extend(Ext.form.TextField,{buttonText:"Browse...",buttonOnly:!1,buttonOffset:3,readOnly:!0,autoSize:Ext.emptyFn,initComponent:function(){Ext.ux.form.FileUploadField.superclass.initComponent.call(this),this.addEvents("fileselected")},onRender:function(ct,position){Ext.ux.form.FileUploadField.superclass.onRender.call(this,ct,position),this.wrap=this.el.wrap({cls:"x-form-field-wrap x-form-fileupload-wrap"}),this.el.addClass("x-form-file-text"),this.el.dom.removeAttribute("name"),this.createFileInput();var btnCfg=Ext.applyIf(this.buttonCfg||{},{text:this.buttonText});this.button=new Ext.Button(Ext.apply(btnCfg,{renderTo:this.wrap,cls:"x-form-file-btn"+(btnCfg.iconCls?" x-btn-icon":"")})),this.buttonOnly&&(this.el.hide(),this.wrap.setWidth(this.button.getEl().getWidth())),this.bindListeners(),this.resizeEl=this.positionEl=this.wrap},bindListeners:function(){this.fileInput.on({scope:this,mouseenter:function(){this.button.addClass(["x-btn-over","x-btn-focus"])},mouseleave:function(){this.button.removeClass(["x-btn-over","x-btn-focus","x-btn-click"])},mousedown:function(){this.button.addClass("x-btn-click")},mouseup:function(){this.button.removeClass(["x-btn-over","x-btn-focus","x-btn-click"])},change:function(){var v=this.fileInput.dom.value;this.setValue(v),this.fireEvent("fileselected",this,v)}})},createFileInput:function(){this.fileInput=this.wrap.createChild({id:this.getFileInputId(),name:this.name||this.getId(),cls:"x-form-file",tag:"input",type:"file",size:1})},reset:function(){this.rendered&&(this.fileInput.remove(),this.createFileInput(),this.bindListeners()),Ext.ux.form.FileUploadField.superclass.reset.call(this)},getFileInputId:function(){return this.id+"-file"},onResize:function(w,h){if(Ext.ux.form.FileUploadField.superclass.onResize.call(this,w,h),this.wrap.setWidth(w),!this.buttonOnly){w=this.wrap.getWidth()-this.button.getEl().getWidth()-this.buttonOffset;this.el.setWidth(w)}},onDestroy:function(){Ext.ux.form.FileUploadField.superclass.onDestroy.call(this),Ext.destroy(this.fileInput,this.button,this.wrap)},onDisable:function(){Ext.ux.form.FileUploadField.superclass.onDisable.call(this),this.doDisable(!0)},onEnable:function(){Ext.ux.form.FileUploadField.superclass.onEnable.call(this),this.doDisable(!1)},doDisable:function(disabled){this.fileInput.dom.disabled=disabled,this.button.setDisabled(disabled)},preFocus:Ext.emptyFn,alignErrorIcon:function(){this.errorIcon.alignTo(this.wrap,"tl-tr",[2,0])}}),Ext.reg("fileuploadfield",Ext.ux.form.FileUploadField),Ext.form.FileUploadField=Ext.ux.form.FileUploadField,Ext.namespace("Ext.ux.form"),Ext.ux.form.SuperBoxSelect=function(config){Ext.ux.form.SuperBoxSelect.superclass.constructor.call(this,config),this.addEvents("beforeadditem","additem","newitem","beforeremoveitem","removeitem","clear")},Ext.ux.form.SuperBoxSelect=Ext.extend(Ext.ux.form.SuperBoxSelect,Ext.form.ComboBox,{addNewDataOnBlur:!1,allowAddNewData:!1,allowQueryAll:!0,backspaceDeletesLastItem:!0,classField:null,clearBtnCls:"",clearLastQueryOnEscape:!1,clearOnEscape:!1,displayFieldTpl:null,extraItemCls:"",extraItemStyle:"",expandBtnCls:"",fixFocusOnTabSelect:!0,forceFormValue:!0,forceSameValueQuery:!1,itemDelimiterKey:Ext.EventObject.ENTER,navigateItemsWithTab:!0,pinList:!0,preventDuplicates:!0,queryFilterRe:"",queryValuesDelimiter:"|",queryValuesIndicator:"valuesqry",removeValuesFromStore:!0,renderFieldBtns:!0,stackItems:!1,styleField:null,supressClearValueRemoveEvents:!1,validationEvent:"blur",valueDelimiter:",",initComponent:function(){Ext.apply(this,{items:new Ext.util.MixedCollection(!1),usedRecords:new Ext.util.MixedCollection(!1),addedRecords:[],remoteLookup:[],hideTrigger:!0,grow:!1,resizable:!1,multiSelectMode:!1,preRenderValue:null,filteredQueryData:""}),this.queryFilterRe&&Ext.isString(this.queryFilterRe)&&(this.queryFilterRe=new RegExp(this.queryFilterRe)),this.transform&&this.doTransform(),this.forceFormValue&&this.items.on({add:this.manageNameAttribute,remove:this.manageNameAttribute,clear:this.manageNameAttribute,scope:this}),Ext.ux.form.SuperBoxSelect.superclass.initComponent.call(this),"remote"===this.mode&&this.store&&this.store.on("load",this.onStoreLoad,this)},onRender:function(ct,position){var h=this.hiddenName;this.hiddenName=null,Ext.ux.form.SuperBoxSelect.superclass.onRender.call(this,ct,position),this.hiddenName=h,this.manageNameAttribute();var extraClass=!0===this.stackItems?"x-superboxselect-stacked":"";this.renderFieldBtns&&(extraClass+=" x-superboxselect-display-btns"),this.el.removeClass("x-form-text").addClass("x-superboxselect-input-field"),this.wrapEl=this.el.wrap({tag:"ul"}),this.outerWrapEl=this.wrapEl.wrap({tag:"div",cls:"x-form-text x-superboxselect "+extraClass}),this.inputEl=this.el.wrap({tag:"li",cls:"x-superboxselect-input"}),this.renderFieldBtns&&this.setupFieldButtons().manageClearBtn(),this.setupFormInterception()},doTransform:function(){var s=Ext.getDom(this.transform),transformValues=[];if(!this.store){this.mode="local";for(var d=[],opts=s.options,i=0,len=opts.length;i0&&(this.collapse(),(it=this.items.get(0)).el.focus()),!0):e.getKey()===e.BACKSPACE?(e.stopEvent(),this.currentFocus?(toDestroy=this.currentFocus,this.on("expand",(function(){this.collapse()}),this,{single:!0}),idx=this.items.indexOfKey(toDestroy.key),this.clearCurrentFocus(),idx0?(this.el.removeClass(this.emptyClass),this.setRawValue(""),this):(this.rendered&&this.emptyText&&this.getRawValue().length<1&&(this.setRawValue(this.emptyText),this.el.addClass(this.emptyClass)),this)},removeAllItems:function(){return this.items.each((function(item){item.preDestroy(!0)}),this),this.manageClearBtn(),this},killItems:function(){return this.items.each((function(item){item.kill()}),this),this.resetStore(),this.items.clear(),this.manageClearBtn(),this},resetStore:function(){return this.store.clearFilter(),this.removeValuesFromStore?(this.usedRecords.each((function(rec){this.store.add(rec)}),this),this.usedRecords.clear(),this.store.remoteSort||this.store.sort(this.displayField,"ASC"),this):this},sortStore:function(){var ss=this.store.getSortState();return ss&&ss.field&&this.store.sort(ss.field,ss.direction),this},getCaption:function(dataObject){"string"==typeof this.displayFieldTpl&&(this.displayFieldTpl=new Ext.XTemplate(this.displayFieldTpl));var caption,recordData=dataObject instanceof Ext.data.Record?dataObject.data:dataObject;return this.displayFieldTpl?caption=this.displayFieldTpl.apply(recordData):this.displayField&&(caption=recordData[this.displayField]),caption},htmlEncode:function(string){return string.replace(/[\u00A0-\u9999<>&]/g,(function(i){return"&#"+i.charCodeAt(0)+";"}))},addRecord:function(record){var display=record.data[this.displayField],caption=this.getCaption(record),val=record.data[this.valueField],cls=this.classField?record.data[this.classField]:"",style=this.styleField?record.data[this.styleField]:"";this.removeValuesFromStore&&(this.usedRecords.add(val,record),this.store.remove(record)),this.addItemBox(val,display,caption,cls,style),this.fireEvent("additem",this,val,record)},createRecord:function(recordData){if(!this.recordConstructor){var recordFields=[{name:this.valueField},{name:this.displayField}];this.classField&&recordFields.push({name:this.classField}),this.styleField&&recordFields.push({name:this.styleField}),this.recordConstructor=Ext.data.Record.create(recordFields)}return new this.recordConstructor(recordData)},addItems:function(newItemObjects){Ext.isArray(newItemObjects)?Ext.each(newItemObjects,(function(item){this.addItem(item)}),this):this.addItem(newItemObjects)},addNewItem:function(newItemObject){this.addItem(newItemObject,!0)},addItem:function(newItemObject,forcedAdd){var val=newItemObject[this.valueField];if(this.disabled)return!1;if(!this.preventDuplicates||!this.hasValue(val)){var record=this.findRecord(this.valueField,val);if(record)this.addRecord(record);else if(this.allowAddNewData){if("remote"===this.mode)return this.remoteLookup.push(newItemObject),void this.doQuery(val,!1,!1,forcedAdd);var rec=this.createRecord(newItemObject);return this.store.add(rec),this.addRecord(rec),!0}}},addItemBox:function(itemVal,itemDisplay,itemCaption,itemClass,itemStyle){var hConfig,itemKey=Ext.id(null,"sbx-item"),box=new Ext.ux.form.SuperBoxSelectItem({owner:this,disabled:this.disabled,renderTo:this.wrapEl,cls:this.extraItemCls+" "+itemClass,style:function(s){var ret="";switch(typeof s){case"function":ret=s.call();break;case"object":for(var p in s)ret+=p+":"+s[p]+";";break;case"string":ret=s+";"}return ret}(this.extraItemStyle)+" "+itemStyle,caption:itemCaption,display:itemDisplay,value:itemVal,key:itemKey,listeners:{remove:function(item){if(!1===this.fireEvent("beforeremoveitem",this,item.value))return!1;this.items.removeKey(item.key),this.removeValuesFromStore&&this.usedRecords.containsKey(item.value)&&(this.store.add(this.usedRecords.get(item.value)),this.usedRecords.removeKey(item.value),this.sortStore(),this.view&&this.view.render()),this.preventMultipleRemoveEvents||this.fireEvent.defer(250,this,["removeitem",this,item.value,this.findInStore(item.value)])},destroy:function(){this.collapse(),this.autoSize().manageClearBtn().validateValue()},scope:this}});box.render(),hConfig={tag:"input",type:"hidden",value:itemVal,name:this.hiddenName||this.name},this.disabled&&Ext.apply(hConfig,{disabled:"disabled"}),box.hidden=this.el.insertSibling(hConfig,"before"),this.items.add(itemKey,box),this.applyEmptyText().autoSize().manageClearBtn().validateValue()},manageClearBtn:function(){if(!this.renderFieldBtns||!this.rendered)return this;var cls="x-superboxselect-btn-hide";return 0===this.items.getCount()?this.buttonClear.addClass(cls):this.buttonClear.removeClass(cls),this},findInStore:function(val){var index=this.store.find(this.valueField,val);return index>-1&&this.store.getAt(index)},getSelectedRecords:function(){var ret=[];if(this.removeValuesFromStore)ret=this.usedRecords.getRange();else{var vals=[];this.items.each((function(item){vals.push(item.value)})),Ext.each(vals,(function(val){ret.push(this.findInStore(val))}),this)}return ret},findSelectedItem:function(el){var ret;return this.items.each((function(item){if(item.el.dom===el)return ret=item,!1})),ret},findSelectedRecord:function(el){var ret,item=this.findSelectedItem(el);return item&&(ret=this.findSelectedRecordByValue(item.value)),ret},findSelectedRecordByValue:function(val){var ret;return this.removeValuesFromStore?this.usedRecords.each((function(rec){if(rec.get(this.valueField)==val)return ret=rec,!1}),this):ret=this.findInStore(val),ret},getValue:function(){var ret=[];return this.items.each((function(item){ret.push(item.value)})),ret.join(this.valueDelimiter)},getCount:function(){return this.items.getCount()},getValueEx:function(){var ret=[];return this.items.each((function(item){var newItem={};newItem[this.valueField]=item.value,newItem[this.displayField]=item.display,this.classField&&(newItem[this.classField]=item.cls||""),this.styleField&&(newItem[this.styleField]=item.style||""),ret.push(newItem)}),this),ret},initValue:function(){Ext.isObject(this.value)||Ext.isArray(this.value)?(this.setValueEx(this.value),this.originalValue=this.getValue()):Ext.ux.form.SuperBoxSelect.superclass.initValue.call(this),"remote"===this.mode&&(this.setOriginal=!0)},addValue:function(value){if(!Ext.isEmpty(value)){var values=value;if(Ext.isArray(value)||(values=(value=""+value).split(this.valueDelimiter)),Ext.each(values,(function(val){var record=this.findRecord(this.valueField,val);record?this.addRecord(record):"remote"===this.mode&&this.remoteLookup.push(val)}),this),"remote"===this.mode){var q=this.remoteLookup.join(this.queryValuesDelimiter);this.doQuery(q,!1,!0)}}},setValue:function(value){this.rendered?(this.removeAllItems().resetStore(),this.remoteLookup=[],this.addValue(value)):this.value=value},setValueEx:function(data){this.rendered?(this.removeAllItems().resetStore(),Ext.isArray(data)||(data=[data]),this.remoteLookup=[],this.allowAddNewData&&"remote"===this.mode?Ext.each(data,(function(d){var r=this.findRecord(this.valueField,d[this.valueField])||this.createRecord(d);this.addRecord(r)}),this):Ext.each(data,(function(item){this.addItem(item)}),this)):this.value=data},hasValue:function(val){var has=!1;return this.items.each((function(item){if(item.value==val)return has=!0,!1}),this),has},onSelect:function(record,index){if(!1!==this.fireEvent("beforeselect",this,record,index)){var val=record.data[this.valueField];if(this.preventDuplicates&&this.hasValue(val))return;this.setRawValue(""),this.lastSelectionText="",!1!==this.fireEvent("beforeadditem",this,val,record,this.filteredQueryData)&&this.addRecord(record),0!==this.store.getCount()&&this.multiSelectMode?this.restrictHeight():this.collapse()}},onDestroy:function(){this.items.purgeListeners(),this.killItems(),this.allowQueryAll&&Ext.destroy(this.buttonExpand),this.renderFieldBtns&&Ext.destroy(this.buttonClear,this.buttonWrap),Ext.destroy(this.inputEl,this.wrapEl,this.outerWrapEl),Ext.ux.form.SuperBoxSelect.superclass.onDestroy.call(this)},autoSize:function(){if(!this.rendered)return this;this.metrics||(this.metrics=Ext.util.TextMetrics.createInstance(this.el));var v=this.el.dom.value,d=document.createElement("div");""===v&&this.emptyText&&this.items.getCount()<1&&(v=this.emptyText),d.appendChild(document.createTextNode(v)),v=d.innerHTML,d=null,v+=" ";var w=Math.max(this.metrics.getWidth(v)+24,24);return void 0!==this._width&&(w=Math.min(this._width,w)),this.el.setWidth(w),Ext.isIE&&(this.el.dom.style.top="0"),this.fireEvent("autosize",this,w),this},shouldQuery:function(q){if(this.lastQuery){var m=q.match("^"+this.lastQuery);return!(m&&!this.store.getCount())||m[0]!==this.lastQuery}return!0},doQuery:function(q,forceAll,valuesQuery,forcedAdd){if(q=Ext.isEmpty(q)?"":q,this.queryFilterRe){this.filteredQueryData="";var m=q.match(this.queryFilterRe);if(m&&m.length&&(this.filteredQueryData=m[0]),!(q=q.replace(this.queryFilterRe,""))&&m)return}var qe={query:q,forceAll,combo:this,cancel:!1};if(!1===this.fireEvent("beforequery",qe)||qe.cancel)return!1;q=qe.query,(!0===(forceAll=qe.forceAll)||q.length>=this.minChars||valuesQuery&&!Ext.isEmpty(q))&&(forcedAdd||this.forceSameValueQuery||this.shouldQuery(q)?(this.lastQuery=q,"local"==this.mode?(this.selectedIndex=-1,forceAll?this.store.clearFilter():this.store.filter(this.displayField,q),this.onLoad()):(this.store.baseParams[this.queryParam]=q,this.store.baseParams[this.queryValuesIndicator]=valuesQuery,this.store.load({params:this.getParams(q)}),forcedAdd||this.expand())):(this.selectedIndex=-1,this.onLoad()))},onStoreLoad:function(store,records,options){var q=options.params[this.queryParam]||store.baseParams[this.queryParam]||"",isValuesQuery=options.params[this.queryValuesIndicator]||store.baseParams[this.queryValuesIndicator];if(this.removeValuesFromStore&&this.store.each((function(record){this.usedRecords.containsKey(record.get(this.valueField))&&this.store.remove(record)}),this),isValuesQuery){var params=q.split(this.queryValuesDelimiter);Ext.each(params,(function(p){this.remoteLookup.remove(p);var rec=this.findRecord(this.valueField,p);rec&&this.addRecord(rec)}),this),this.setOriginal&&(this.setOriginal=!1,this.originalValue=this.getValue())}""!==q&&this.allowAddNewData&&Ext.each(this.remoteLookup,(function(r){if("object"==typeof r&&r[this.valueField]===q){if(this.remoteLookup.remove(r),records.length&&records[0].get(this.valueField)===q)return void this.addRecord(records[0]);var rec=this.createRecord(r);return this.store.add(rec),this.addRecord(rec),this.addedRecords.push(rec),void function(){this.isExpanded()&&this.collapse()}.defer(10,this)}}),this);var toAdd=[];if(""===q)Ext.each(this.addedRecords,(function(rec){this.preventDuplicates&&this.usedRecords.containsKey(rec.get(this.valueField))||toAdd.push(rec)}),this);else{var re=new RegExp(Ext.escapeRe(q)+".*","i");Ext.each(this.addedRecords,(function(rec){this.preventDuplicates&&this.usedRecords.containsKey(rec.get(this.valueField))||re.test(rec.get(this.displayField))&&toAdd.push(rec)}),this)}this.store.add(toAdd),this.sortStore(),0===this.store.getCount()&&this.isExpanded()&&this.collapse()}}),Ext.reg("superboxselect",Ext.ux.form.SuperBoxSelect),Ext.ux.form.SuperBoxSelectItem=function(config){Ext.apply(this,config),Ext.ux.form.SuperBoxSelectItem.superclass.constructor.call(this)},Ext.ux.form.SuperBoxSelectItem=Ext.extend(Ext.ux.form.SuperBoxSelectItem,Ext.Component,{initComponent:function(){Ext.ux.form.SuperBoxSelectItem.superclass.initComponent.call(this)},onElClick:function(e){var o=this.owner;if(o.clearCurrentFocus().collapse(),o.navigateItemsWithTab)this.focus();else{o.el.dom.focus();(function(){this.onLnkFocus(),o.currentFocus=this}).defer(10,this)}},onLnkClick:function(e){e&&e.stopEvent(),this.preDestroy(),this.owner.navigateItemsWithTab||this.owner.el.focus()},onLnkFocus:function(){this.el.addClass("x-superboxselect-item-focus"),this.owner.outerWrapEl.addClass("x-form-focus")},onLnkBlur:function(){this.el.removeClass("x-superboxselect-item-focus"),this.owner.outerWrapEl.removeClass("x-form-focus")},enableElListeners:function(){this.el.on("click",this.onElClick,this,{stopEvent:!0}),this.el.addClassOnOver("x-superboxselect-item-hover")},enableLnkListeners:function(){this.lnk.on({click:this.onLnkClick,focus:this.onLnkFocus,blur:this.onLnkBlur,scope:this})},enableAllListeners:function(){this.enableElListeners(),this.enableLnkListeners()},disableAllListeners:function(){this.el.removeAllListeners(),this.lnk.un("click",this.onLnkClick,this),this.lnk.un("focus",this.onLnkFocus,this),this.lnk.un("blur",this.onLnkBlur,this)},onRender:function(ct,position){Ext.ux.form.SuperBoxSelectItem.superclass.onRender.call(this,ct,position);var el=this.el;el&&el.remove(),this.el=el=ct.createChild({tag:"li"},ct.last()),el.addClass("x-superboxselect-item");var btnEl=this.owner.navigateItemsWithTab?Ext.isSafari?"button":"a":"span";this.key;Ext.apply(el,{focus:function(){var c=this.down(btnEl+".x-superboxselect-item-close");c&&c.focus()},preDestroy:function(){this.preDestroy()}.createDelegate(this)}),this.enableElListeners(),el.update(this.caption);var cfg={tag:btnEl,class:"x-superboxselect-item-close",tabIndex:this.owner.navigateItemsWithTab?"0":"-1"};"a"===btnEl&&(cfg.href="#"),this.lnk=el.createChild(cfg),this.disabled?this.disableAllListeners():this.enableLnkListeners(),this.on({disable:this.disableAllListeners,enable:this.enableAllListeners,scope:this}),this.setupKeyMap()},setupKeyMap:function(){this.keyMap=new Ext.KeyMap(this.lnk,[{key:[Ext.EventObject.BACKSPACE,Ext.EventObject.DELETE,Ext.EventObject.SPACE],fn:this.preDestroy,scope:this},{key:[Ext.EventObject.RIGHT,Ext.EventObject.DOWN],fn:function(){this.moveFocus("right")},scope:this},{key:[Ext.EventObject.LEFT,Ext.EventObject.UP],fn:function(){this.moveFocus("left")},scope:this},{key:[Ext.EventObject.HOME],fn:function(){var l=this.owner.items.get(0).el.focus();l&&l.el.focus()},scope:this},{key:[Ext.EventObject.END],fn:function(){this.owner.el.focus()},scope:this},{key:Ext.EventObject.ENTER,fn:function(){}}]),this.keyMap.stopEvent=!0},moveFocus:function(dir){var el=this.el["left"==dir?"prev":"next"]()||this.owner.el;el.focus.defer(100,el)},preDestroy:function(supressEffect){if(!1!==this.fireEvent("remove",this)){var actionDestroy=function(){this.owner.navigateItemsWithTab&&this.moveFocus("right"),this.hidden.remove(),this.hidden=null,this.destroy()};return supressEffect?actionDestroy.call(this):this.el.hide({duration:.2,callback:actionDestroy,scope:this}),this}},kill:function(){this.hidden.remove(),this.hidden=null,this.purgeListeners(),this.destroy()},onDisable:function(){this.hidden&&this.hidden.dom.setAttribute("disabled","disabled"),this.keyMap.disable(),Ext.ux.form.SuperBoxSelectItem.superclass.onDisable.call(this)},onEnable:function(){this.hidden&&this.hidden.dom.removeAttribute("disabled"),this.keyMap.enable(),Ext.ux.form.SuperBoxSelectItem.superclass.onEnable.call(this)},onDestroy:function(){Ext.destroy(this.lnk,this.el),Ext.ux.form.SuperBoxSelectItem.superclass.onDestroy.call(this)}}),MODx.Component=function(config){config=config||{},MODx.Component.superclass.constructor.call(this,config),this.config=config,this._loadForm(),this.config.tabs&&this._loadTabs(),this._loadComponents(),this._loadActionButtons(),MODx.activePage=this},Ext.extend(MODx.Component,Ext.Component,{fields:{},form:null,action:!1,_loadForm:function(){if(!this.config.form)return!1;if(this.form=new Ext.form.BasicForm(Ext.get(this.config.form),{errorReader:MODx.util.JSONReader}),this.config.fields)for(var i in this.config.fields)if(this.config.fields.hasOwnProperty(i)){var f=this.config.fields[i];f.xtype&&(f=Ext.ComponentMgr.create(f)),this.fields[i]=f,this.form.add(f)}return this.form.render()},_loadActionButtons:function(){return!!this.config.buttons&&(this.ab=MODx.load({xtype:"modx-actionbuttons",form:this.form||null,formpanel:this.config.formpanel||null,actions:this.config.actions||null,items:this.config.buttons||[]}),this.ab)},_loadTabs:function(){if(!this.config.tabs)return!1;var o=this.config.tabOptions||{};return Ext.applyIf(o,{xtype:"modx-tabs",renderTo:this.config.tabs_div||"tabs_div",items:this.config.tabs}),MODx.load(o)},_loadComponents:function(){if(!this.config.components)return!1;for(var l=this.config.components.length,cp=Ext.getCmp("modx-content"),i=0;i","<-",""," "];if(-1!=ex.indexOf(el)||el.xtype&&"switch"==el.xtype)MODx.toolbar.ActionButtons.superclass.add.call(this,el);else{var id=el.id||Ext.id();if(Ext.applyIf(el,{xtype:"button",cls:el.icon?"x-btn-icon bmenu":"x-btn-text bmenu",scope:this,disabled:!!el.checkDirty,listeners:{},id}),el.button&&MODx.toolbar.ActionButtons.superclass.add.call(this,el),null===el.handler&&null===el.menu?el.handler=this.checkConfirm:el.confirm&&el.handler?el.handler=function(){Ext.Msg.confirm(_("warning"),el.confirm,(function(e){"yes"===e&&Ext.callback(el.handler,this)}),el.scope||this)}:el.handler||(el.handler=this.handleClick),el.javascript&&(el.listeners.click={fn:this.evalJS,scope:this}),"button"==el.xtype&&(el.listeners.render={fn:function(btn){el.checkDirty&&btn&&this.checkDirtyBtns.push(btn)},scope:this}),el.keys){el.keyMap=new Ext.KeyMap(Ext.get(document));for(var j=0;j{item&&item.validate&&!item.validate()&&(isv=!1)})),isv?(Ext.applyIf(o.params,{action:itm.process}),Ext.apply(f.baseParams,o.params),o.form.on("success",(function(r){if(o.form.clearDirty&&o.form.clearDirty(),MODx.msg.status({title:_("success"),message:r.result.message||_("save_successful"),dontHide:""!=r.result.message}),0!=itm.redirect){var redirect=this.redirect;"function"==typeof itm.redirect&&(redirect=itm.redirect),Ext.callback(redirect,this,[o,itm,r.result],1e3)}this.resetDirtyButtons(r.result)}),this),o.form.submit({headers:{"Powered-By":"MODx",modAuth:MODx.siteId}})):(o.form.fireEvent("failureSubmit"),Ext.Msg.alert(_("error"),_("correct_errors")))}else{var params=itm.params||{};Ext.applyIf(params,o.baseParams||{}),MODx.loadPage("?"+Ext.urlEncode(params))}return!1},resetDirtyButtons:function(r){for(var i=0;i0}},contextmenu:{fn:this._showContextMenu,scope:this}}),Ext.applyIf(config,{store:this.store,singleSelect:!0,overClass:"x-view-over",emptyText:'
    '+_("file_err_filter")+"
    ",closeAction:"hide"}),MODx.DataView.superclass.constructor.call(this,config),this.config=config,this.cm=new Ext.menu.Menu},Ext.extend(MODx.DataView,Ext.DataView,{lookup:{},onLoadException:function(){this.getEl().update('
    '+_("data_err_load")+"
    ")},_addContextMenuItem:function(items){for(var a=items,l=a.length,i=0;i ').compile()}),MODx.Button.superclass.constructor.call(this,config)},Ext.extend(MODx.Button,Ext.Button,{onRender:function(ct,position){this.template||(Ext.Button.buttonTemplate||(Ext.Button.buttonTemplate=new Ext.Template(' '),Ext.Button.buttonTemplate.compile()),this.template=Ext.Button.buttonTemplate);var btn,targs=this.getTemplateArgs();targs.iconCls=this.iconCls,btn=position?this.template.insertBefore(position,targs,!0):this.template.append(ct,targs,!0),this.btnEl=btn.child("i"),this.mon(this.btnEl,{scope:this,focus:this.onFocus,blur:this.onBlur}),this.initButtonEl(btn,this.btnEl),Ext.ButtonToggleMgr.register(this)}}),Ext.reg("modx-button",MODx.Button),MODx.SearchBar=function(config){config=config||{},Ext.applyIf(config,{renderTo:"modx-manager-search",listClass:"modx-manager-search-results",emptyText:_("search"),id:"modx-uberbar",maxHeight:this.getViewPortSize(),typeAhead:!0,listAlign:["tl-bl?",[-12,12]],triggerConfig:{tag:"button",id:"modx-uberbar-trigger",type:"submit","aria-label":"Go",cls:"x-form-trigger icon icon-large icon-search"},defaultAutoCreate:{tag:"input",type:"text",size:"24",tabindex:"0",hasfocus:!0,"aria-label":_("search")},hasfocus:!0,minChars:1,displayField:"name",valueField:"_action",width:380,itemSelector:".x-combo-list-item",tpl:new Ext.XTemplate('','
    ','','',"

    {label:htmlEncode}

    ","
    ",'

    {name:htmlEncode} – {description:htmlEncode}

    ',"
    ","
    ",{getClass:function(values){if(values.icon)return values.icon;if(values.class)switch(values.class){case"MODX\\Revolution\\modDocument":return"file";case"MODX\\Revolution\\modSymLink":return"files-o";case"MODX\\Revolution\\modWebLink":return"link";case"MODX\\Revolution\\modStaticResource":return"file-text-o"}switch(values.type){case"resources":return"file";case"chunks":return"th-large";case"templates":return"columns";case"snippets":return"code";case"tvs":return"list-alt";case"plugins":return"cogs";case"users":return"user";case"actions":return"mail-forward"}},getLabel:function(values){return values.label?values.label:_("search_resulttype_"+values.type)}}),store:new Ext.data.JsonStore({url:MODx.config.connector_url,baseParams:{action:"Search/Search"},root:"results",totalProperty:"total",fields:["name","_action","description","type","icon","label","class"],listeners:{beforeload:function(store,options){if(options.params._action)return!1}}}),listeners:{beforequery:{fn:function(){this.tpl.type=null}},focus:this.focusBar,blur:this.blurBar,afterrender:function(){document.getElementById("modx-manager-search").onclick=function(e){e.stopPropagation()}},scope:this}}),MODx.SearchBar.superclass.constructor.call(this,config),this.blur(),this.setKeyMap()},Ext.extend(MODx.SearchBar,Ext.form.ComboBox,{setKeyMap:function(){new Ext.KeyMap(document,{key:27,handler:function(){this.hideBar()},scope:this,stopEvent:!1})},initList:function(){if(!this.list){var cls="x-combo-list",listParent=Ext.getDom(this.getListParent()||Ext.getBody());this.list=new Ext.Layer({parentEl:listParent,shadow:this.shadow,cls:[cls,this.listClass].join(" "),constrain:!1,zindex:this.getZIndex(listParent)}),this.list.on("click",(function(e){e.stopPropagation()}));var lw=this.listWidth||Math.max(this.wrap.getWidth(),this.minListWidth);this.list.setSize(lw,0),this.list.swallowEvent("mousewheel"),this.assetHeight=0,!1!==this.syncFont&&this.list.setStyle("font-size",this.el.getStyle("font-size")),this.title&&(this.header=this.list.createChild({cls:cls+"-hd",html:this.title}),this.assetHeight+=this.header.getHeight()),this.innerList=this.list.createChild({cls:cls+"-inner"}),this.mon(this.innerList,"mouseover",this.onViewOver,this),this.mon(this.innerList,"mousemove",this.onViewMove,this),this.innerList.setWidth(lw-this.list.getFrameWidth("lr")),this.pageSize&&(this.footer=this.list.createChild({cls:cls+"-ft"}),this.pageTb=new Ext.PagingToolbar({store:this.store,pageSize:this.pageSize,renderTo:this.footer}),this.assetHeight+=this.footer.getHeight()),this.tpl||(this.tpl='
    {'+this.displayField+"}
    "),this.view=new Ext.DataView({applyTo:this.innerList,tpl:this.tpl,singleSelect:!0,selectedClass:this.selectedClass,itemSelector:this.itemSelector||"."+cls+"-item",emptyText:this.listEmptyText,deferEmptyText:!1}),this.view.on("click",(function(view,index,node,vent){view.select(node),window.event||(window.event=vent),this.onViewClick()}),this),this.bindStore(this.store,!0),this.resizable&&(this.resizer=new Ext.Resizable(this.list,{pinned:!0,handles:"se"}),this.mon(this.resizer,"resize",(function(r,w,h){this.maxHeight=h-this.handleHeight-this.list.getFrameWidth("tb")-this.assetHeight,this.listWidth=w,this.innerList.setWidth(w-this.list.getFrameWidth("lr")),this.restrictHeight()}),this),this[this.pageSize?"footer":"innerList"].setStyle("margin-bottom",this.handleHeight+"px"))}},onTypeAhead:function(){},onSelect:function(record,index){var e=Ext.EventObject;e.stopPropagation(),e.preventDefault();var target="?a="+record.data._action;if(e.ctrlKey||e.metaKey||e.shiftKey)return window.open(target);MODx.loadPage(target)},hideBar:function(){},focusBar:function(){this.selectText()},blurBar:function(){},getViewPortSize:function(){var height=300;return void 0!==window.innerHeight&&(height=window.innerHeight),height-70}}),Ext.reg("modx-searchbar",MODx.SearchBar),Ext.namespace("MODx.panel"),MODx.Panel=function(config){config=config||{},Ext.applyIf(config,{cls:"modx-panel",title:""}),MODx.Panel.superclass.constructor.call(this,config),this.config=config},Ext.extend(MODx.Panel,Ext.Panel),Ext.reg("modx-panel",MODx.Panel),MODx.FormPanel=function(config){config=config||{},Ext.applyIf(config,{autoHeight:!0,collapsible:!0,bodyStyle:"",layout:"anchor",border:!1,header:!1,method:"POST",cls:"modx-form",allowDrop:!0,errorReader:MODx.util.JSONReader,checkDirty:!0,useLoadingMask:!1,defaults:{collapsible:!1,autoHeight:!0,border:!1}}),config.items&&this.addChangeEvent(config.items),MODx.FormPanel.superclass.constructor.call(this,config),this.config=config,this.addEvents({setup:!0,fieldChange:!0,ready:!0,beforeSubmit:!0,success:!0,failure:!0,save:!0,actionNew:!0,actionContinue:!0,actionClose:!0,postReady:!0}),this.getForm().addEvents({success:!0,failure:!0}),this.dropTargets=[],this.on("ready",this.onReady),this.config.useLoadingMask&&this.on("render",(function(){this.mask=new Ext.LoadMask(this.getEl()),this.mask.show()})),this.fireEvent("setup",config)&&this.clearDirty(),this.focusFirstField()},Ext.extend(MODx.FormPanel,Ext.FormPanel,{isReady:!1,defaultValues:[],initialized:!1,isStatic:!1,errorHandlingTabs:[],errorHandlingIgnoreTabs:[],submit:function(o){var fm=this.getForm();return!(!fm.isValid()&&!o.bypassValidCheck)&&((o=o||{}).headers={"Powered-By":"MODx",modAuth:MODx.siteId},this.fireEvent("beforeSubmit",{form:fm,options:o,config:this.config})&&fm.submit({waitMsg:this.config.saveMsg||_("saving"),scope:this,headers:o.headers,clientValidation:!o.bypassValidCheck,failure:function(f,a){this.fireEvent("failure",{form:f,result:a.result,options:o,config:this.config})&&MODx.form.Handler.errorExt(a.result,f)},success:function(f,a){this.config.success&&Ext.callback(this.config.success,this.config.scope||this,[f,a]),this.fireEvent("success",{form:f,result:a.result,options:o,config:this.config}),this.clearDirty(),this.fireEvent("setup",this.config);var lastActiveEle=Ext.state.Manager.get("curFocus");if(lastActiveEle&&""!=lastActiveEle){Ext.state.Manager.clear("curFocus");var initFocus=document.getElementById(lastActiveEle);initFocus&&initFocus.focus()}}}),!0)},failure:function(o){if(this.warnUnsavedChanges=!0,-1!==this.getForm().baseParams.action.search(/\/create/i)){const btn=Ext.getCmp("modx-abtn-save");btn&&btn.enable()}this.fireEvent("failureSubmit")},focusFirstField:function(){if(this.getForm().items.getCount()>0){var fld=this.findFirstTextField();fld&&fld.focus(!1,200)}},findFirstTextField:function(i){i=i||0;var fld=this.getForm().items.itemAt(i);return!!fld&&((fld.isXType("combo")||fld.isXType("checkbox")||fld.isXType("radio")||fld.isXType("displayfield")||fld.isXType("statictextfield")||fld.isXType("hidden"))&&(i+=1,fld=this.findFirstTextField(i)),fld)},addChangeEvent:function(items){if(!items)return!1;"object"==typeof items&&items.items&&(items=items.items);for(var f=0;f{fieldKey=fieldKey.trim();const fieldCmpId=`modx-${formId}-${fieldKey}-file`,sourceKey=Ext.isEmpty(sharedSourceKey)?fieldKey:sharedSourceKey,sourceCmpId=`modx-${formId}-${sourceKey}-source`,fieldCmp=Ext.getCmp(fieldCmpId),sourceCmp=Ext.getCmp(sourceCmpId);fieldCmp&&sourceCmp&&(fieldCmp.config.source=sourceCmp.getValue())}))},destroy:function(){for(var i=0;i0&&keys.forEach((function(key){map.hasOwnProperty(key)&&"string"==typeof map[key].id?tabIds.push(map[key].id):"modx-panel-resource-tv"==key&&1==MODx.config.tvs_below_content&&tabIds.push(key)})),tabIds},showErroredTab:function(targetForms,tabsId){const mainTabs=Ext.getCmp(tabsId),searchTabs=this.getTabIdsFromKeys(mainTabs.items.map,targetForms);let component,mainTabName=null,mainTabIndex=null,erroredNode=null;mainTabs.items.length>mainTabs.initialConfig.items.length&&mainTabs.items.keys.forEach((function(key){mainTabs.items.map[key].hasOwnProperty("id")&&(this.errorHandlingIgnoreTabs.includes(mainTabs.items.map[key].id)||searchTabs.includes(mainTabs.items.map[key].id)||searchTabs.push(mainTabs.items.map[key].id))}),this);for(let i=0;i0&&erroredFlds[0].id},insertTagCopyUtility:function(cmp,elType){const helpTag=cmp.getEl().child(".example-replace-name"),elTag=cmp.getEl().child(".copy-this");let tagText,nameVal=cmp.previousSibling().getValue();helpTag&&(nameVal.length>0&&(helpTag.update(nameVal),tagText=elTag.dom.innerText),helpTag.on({click:function(){if(nameVal=cmp.previousSibling().getValue(),nameVal.length>0){tagText=elTag.dom.innerText;const tmp=document.createElement("textarea");if(tmp.value=tagText,document.body.appendChild(tmp),tmp.select(),document.execCommand("copy")){const feedback=document.createElement("span");feedback.className="element-panel feedback item-copied",feedback.textContent=_(elType+"_tag_copied"),elTag.insertSibling(feedback,"after"),setTimeout((function(){feedback.style.opacity=0,setTimeout((function(){feedback.remove()}),1200)}),10)}tmp.remove()}}}))},onChangeStaticSource:function(cmp,elType){const isStatic=Ext.getCmp(`modx-${elType}-static`).getValue(),staticFileField=Ext.getCmp(`modx-${elType}-static-file`),staticFile=staticFileField.getValue(),staticDir=staticFile.slice(0,staticFile.lastIndexOf("/")+1),staticFileFieldId=staticFileField.id,staticFileFieldContainer=Ext.getCmp(staticFileField.ownerCt.id),itemKey=staticFileFieldContainer.items.keys.indexOf(staticFileFieldId),previousSource=this.previousFileSource||0,currentSource=cmp.getValue(),currentRecord={static:isStatic,static_file:staticFile,source:currentSource,openTo:staticDir};let newStaticFile,changeFieldType=!1,updateFieldSource=!1;if("template"===elType)var newPreviewFileField,staticPreviewFileField=Ext.getCmp(`modx-${elType}-preview-file`),staticPreviewFile=staticPreviewFileField.getValue(),staticPreviewDir=staticPreviewFile.slice(0,staticPreviewFile.lastIndexOf("/")+1),staticPreviewFileFieldId=staticPreviewFileField.id,staticPreviewFileFieldContainer=Ext.getCmp(staticPreviewFileField.ownerCt.id),previewItemKey=staticPreviewFileFieldContainer.items.keys.indexOf(staticPreviewFileFieldId),currentPreviewRecord={static:isStatic,preview_file:staticPreviewFile,source:currentSource,openTo:staticPreviewDir};this.previousFileSource=currentSource,previousSource>0&&0==currentSource?(newStaticFile=this.getStaticFileField(elType,currentRecord,!1),"template"===elType&&(newPreviewFileField=this.getTemplatePreviewImageField(currentPreviewRecord,!1)),changeFieldType=!0):0==previousSource&¤tSource>0?(newStaticFile=this.getStaticFileField(elType,currentRecord),"template"===elType&&(newPreviewFileField=this.getTemplatePreviewImageField(currentPreviewRecord)),changeFieldType=!0,updateFieldSource=!0):updateFieldSource=!0,updateFieldSource&&(changeFieldType?(newStaticFile.source=currentSource,"template"===elType&&(newPreviewFileField.source=currentSource)):(staticFileField.config.source=currentSource,"template"===elType&&(staticPreviewFileField.config.source=currentSource))),changeFieldType&&(staticFileField.clearInvalid(),staticFileField.destroy(),staticFileFieldContainer.insert(itemKey,newStaticFile),"template"===elType&&(staticPreviewFileField.clearInvalid(),staticPreviewFileField.destroy(),staticPreviewFileFieldContainer.insert(previewItemKey,newPreviewFileField)),this.doLayout())},getStaticFileField:function(elType,record,loadBrowserField=!0){const sharedConfig={fieldLabel:_("static_file"),description:MODx.expandHelp?"":_("static_file_desc"),name:"static_file",id:`modx-${elType}-static-file`,maxLength:255,anchor:"100%",value:record.static_file||""};let finalConfig;return(0===record.source||!record.hasOwnProperty("source")&&Ext.isEmpty(MODx.config.default_media_source))&&(loadBrowserField=!1),finalConfig=loadBrowserField?Object.assign(sharedConfig,{xtype:"modx-combo-browser",browserEl:"modx-browser",triggerClass:"x-form-code-trigger",source:null!=record.source?record.source:MODx.config.default_media_source,openTo:record.openTo||""}):Object.assign(sharedConfig,{xtype:"textfield"}),record.static||(finalConfig.hidden=!0),finalConfig},getTemplatePreviewImageField:function(record,loadBrowserField=!0){const sharedConfig={fieldLabel:_("template_preview"),description:MODx.expandHelp?"":_("template_preview_description"),name:"preview_file",id:"modx-template-preview-file",allowedFileTypes:"jpg,jpeg,png,gif,bmp",maxLength:255,anchor:"100%",value:record.preview_file||""};let finalConfig;return(0===record.source||!record.hasOwnProperty("source")&&Ext.isEmpty(MODx.config.default_media_source))&&(loadBrowserField=!1),finalConfig=loadBrowserField?Object.assign(sharedConfig,{xtype:"modx-combo-browser",browserEl:"modx-browser",triggerClass:"x-form-image-trigger",source:null!=record.source?record.source:MODx.config.default_media_source,openTo:record.openTo||""}):Object.assign(sharedConfig,{xtype:"textfield"}),finalConfig},toggleFieldVisibility:function(ctrlId,containerId,fieldIds,ctrlValToShow,addSibling){const ctrlCmp=Ext.getCmp(ctrlId),containerCmp=Ext.getCmp(containerId);if(!ctrlCmp||void 0===ctrlCmp)return console.error(`toggleFieldVisibility: Could not get the control component with the id '${ctrlId}'`),!1;if(containerId&&(!containerCmp||void 0===containerCmp))return console.error(`toggleFieldVisibility: Could not get the container component with the id '${containerId}'`),!1;addSibling=!1!==addSibling,ctrlValToShow=!1!==ctrlValToShow;const showVal="combo-boolean"===ctrlCmp.xtype?ctrlCmp.getValue():ctrlCmp.checked,show=!1===ctrlValToShow?!showVal:showVal;show?(containerCmp.show(),containerCmp.doLayout()):containerCmp.hide(),fieldIds.forEach((field=>{const fieldCmp=Ext.getCmp(field),sibling=fieldCmp.nextSibling(),siblingIsHelp=sibling&&"label"===sibling.xtype;fieldCmp&&(show?(fieldCmp.show(),addSibling&&siblingIsHelp&&sibling.show()):(fieldCmp.hide(),addSibling&&siblingIsHelp&&sibling.hide()))}))},formatMainPanelTitle:function(formId,record,realtimeValue=null,returnBaseTitle=!1){let title="",baseTitle="";const modeCreate=!(record.hasOwnProperty("id")&&record.id>0),prefixSeparator=modeCreate&&!realtimeValue?"":": ",prefix=(modeCreate?_("create")+" ":_("edit")+" ")+_("resource"===formId?"document":formId)+prefixSeparator;if(!Ext.isEmpty(record)){const postfix=MODx.perm.tree_show_resource_ids&&!Ext.isEmpty(record.id)?` (${record.id})`:"";if("resource"===formId){const headerCmp=Ext.getCmp("modx-header-breadcrumbs");title=realtimeValue||record.pagetitle,baseTitle=this.encodeTitle(title,!1),title=void 0===title?prefix:this.encodeTitle(title)+postfix,headerCmp?headerCmp.updateHeader(title):Ext.getCmp("modx-resource-header").el.dom.innerText=title}else{const headerCmpId=`modx-${formId}-header`;realtimeValue?baseTitle=this.encodeTitle(realtimeValue):(title="template"===formId?record.templatename:record.name,baseTitle=this.encodeTitle(title)),title=void 0===title?prefix:prefix+baseTitle+postfix,Ext.getCmp(headerCmpId).getEl().update(title)}}if(returnBaseTitle)return baseTitle},encodeTitle:function(title,htmlEncode=!0){return title&&(title=htmlEncode?Ext.util.Format.htmlEncode(Ext.util.Format.stripTags(title)):Ext.util.Format.stripTags(title)),title},getElementProperties:function(properties){if(!Ext.isEmpty(properties)){const gridCmp=Ext.getCmp("modx-grid-element-properties");gridCmp&&(gridCmp.defaultProperties=properties,gridCmp.getStore().loadData(properties))}}}),Ext.reg("modx-formpanel",MODx.FormPanel),MODx.panel.Wizard=function(config){config=config||{},Ext.applyIf(config,{layout:"card",activeItem:0,resizable:!0,collapsible:!0,maximizable:!0,autoHeight:!0,width:750,firstPanel:"",lastPanel:"",defaults:{border:!1},modal:!0,txtFinish:_("finish"),txtNext:_("next"),txtBack:_("back"),bbar:[{id:"pi-btn-bck",itemId:"btn-back",text:config.txtBack||_("back"),handler:this.navHandler.createDelegate(this,[-1]),scope:this,disabled:!0},{id:"pi-btn-fwd",itemId:"btn-fwd",text:config.txtNext||_("next"),handler:this.navHandler.createDelegate(this,[1]),scope:this}]}),MODx.panel.Wizard.superclass.constructor.call(this,config),this.config=config,this.lastActiveItem=this.config.firstPanel,this._go()},Ext.extend(MODx.panel.Wizard,Ext.Panel,{windows:{},_go:function(){this.getBottomToolbar().items.item(1).setText(this.config.txtNext),this.proceed(this.config.firstPanel)},navHandler:function(dir){this.doLayout();var a=this.getLayout().activeItem;-1==dir?this.proceed(a.config.back||a.config.id):a.submit({scope:this,proceed:this.proceed})},proceed:function(id){this.doLayout(),this.getLayout().setActiveItem(id),id==this.config.firstPanel?(this.getBottomToolbar().items.item(0).setDisabled(!0),this.getBottomToolbar().items.item(1).setText(this.config.txtNext)):id==this.config.lastPanel?this.getBottomToolbar().items.item(1).setText(this.config.txtFinish):(this.getBottomToolbar().items.item(0).setDisabled(!1),this.getBottomToolbar().items.item(1).setText(this.config.txtNext))}}),Ext.reg("modx-panel-wizard",MODx.panel.Wizard),MODx.panel.WizardPanel=function(config){config=config||{},Ext.applyIf(config,{wizard:null,checkDirty:!1,bodyStyle:"padding: 3em 3em",hideMode:"offsets"}),MODx.panel.WizardPanel.superclass.constructor.call(this,config)},Ext.extend(MODx.panel.WizardPanel,MODx.FormPanel),Ext.reg("modx-wizard-panel",MODx.panel.WizardPanel),MODx.PanelSpacer={html:"
    ",border:!1},MODx.TemplatePanel=function(config){config=config||{},Ext.applyIf(config,{frame:!1,startingMarkup:'

    {text}

    ',startingText:"Loading...",markup:null,plain:!0,border:!1}),MODx.TemplatePanel.superclass.constructor.call(this,config),this.on("render",this.init,this)},Ext.extend(MODx.TemplatePanel,Ext.Panel,{init:function(){this.defaultMarkup=new Ext.XTemplate(this.startingMarkup,{compiled:!0}),this.reset(),this.tpl=new Ext.XTemplate(this.markup,{compiled:!0})},reset:function(){this.body.hide(),this.defaultMarkup.overwrite(this.body,{text:this.startingText}),this.body.slideIn("r",{stopFx:!0,duration:.2}),setTimeout((function(){Ext.getCmp("modx-content").doLayout()}),500)},updateDetail:function(data){this.body.hide(),this.tpl.overwrite(this.body,data),this.body.slideIn("r",{stopFx:!0,duration:.2}),setTimeout((function(){Ext.getCmp("modx-content").doLayout()}),500)}}),Ext.reg("modx-template-panel",MODx.TemplatePanel),MODx.BreadcrumbsPanel=function(config){config=config||{},Ext.applyIf(config,{frame:!1,plain:!0,border:!1,desc:"This the description part of this panel",bdMarkup:"
      {text}

    {text}

    ",root:{text:"Home",className:"first",root:!0,pnl:""},bodyCssClass:"breadcrumbs"}),MODx.BreadcrumbsPanel.superclass.constructor.call(this,config),this.on("render",this.init,this)},Ext.extend(MODx.BreadcrumbsPanel,Ext.Panel,{data:{trail:[]},init:function(){this.tpl=new Ext.XTemplate(this.bdMarkup,{compiled:!0}),this.reset(this.desc),this.body.on("click",this.onClick,this)},getResetText:function(srcInstance){if("object"!=typeof srcInstance||null==srcInstance)return srcInstance;var newInstance=srcInstance.constructor();for(var i in srcInstance)newInstance[i]=this.getResetText(srcInstance[i]);return newInstance.hasOwnProperty("pnl")&&delete newInstance.pnl,newInstance},updateDetail:function(data){(this.data=data,data.hasOwnProperty("trail"))&&data.trail.unshift(this.root);this._updatePanel(data)},getData:function(){return this.data},reset:function(msg){void 0===this.resetText&&(this.resetText=this.getResetText(this.root)),this.data={text:msg,trail:[this.resetText]},this._updatePanel(this.data)},onClick:function(e){for(var target=e.getTarget(),index=1,parent=target.parentElement;null!=(parent=parent.previousSibling);)index+=1;for(var remove=this.data.trail.length-index;remove>0;)this.data.trail.pop(),remove-=1;if(elm=target.className.split(" ")[0],""!=elm&&"controlBtn"==elm){var panel=target.className.split(" ")[1];if("install"==panel){var last=this.data.trail[this.data.trail.length-1];if(null!=last&&null!=last.rec)return this.data.trail.pop(),void Ext.getCmp("modx-package-grid").install(last.rec)}else Ext.getCmp(panel).activate()}},_updatePanel:function(data){this.body.hide(),this.tpl.overwrite(this.body,data),this.body.slideIn("r",{stopFx:!0,duration:.2}),setTimeout((function(){Ext.getCmp("modx-content").doLayout()}),500)}}),Ext.reg("modx-breadcrumbs-panel",MODx.BreadcrumbsPanel),Ext.override(Ext.TabPanel,{onStripMouseDown:function(e){if(0!==e.button)return;e.preventDefault();const t=this.findTargets(e);t.close?!1!==t.item.fireEvent("beforeclose",t.item)&&(t.item.fireEvent("close",t.item),this.remove(t.item)):t.item&&t.item!==this.activeTab&&(this.tabClicked=!0,this.setActiveTab(t.item))}}),MODx.Tabs=function(config={}){Ext.applyIf(config,{enableTabScroll:!0,layoutOnTabChange:!0,plain:!0,deferredRender:!0,hideMode:"offsets",defaults:{autoHeight:!0,hideMode:"offsets",border:!0,autoWidth:!0,bodyCssClass:"tab-panel-wrapper"},activeTab:0,tabClicked:!1,border:!1,autoScroll:!0,autoHeight:!0,cls:"modx-tabs",itemTpl:new Ext.XTemplate('
  • ','','','{text}',"","
  • ")}),MODx.Tabs.superclass.constructor.call(this,config),this.config=config,this.on({afterrender:function(tabPanel){if(MODx.request&&Object.prototype.hasOwnProperty.call(MODx.request,"tab")){const tabId=parseInt(MODx.request.tab,10);"modx-leftbar-tabpanel"!==this.id&&this.setActiveTab(tabId)}tabPanel.on({beforetabchange:function(tabPanelCmp,newTab,currentTab){if(this.tabClicked&&newTab&¤tTab&&newTab.id!==currentTab.id){const resetVerticalTabPanelFilters="modx-vtabs"===currentTab.items?.items[0]?.xtype||"modx-vtabs"===currentTab.ownerCt?.xtype,changedBetweenVtabs="modx-vtabs"===newTab.ownerCt?.xtype&&"modx-vtabs"===currentTab.ownerCt?.xtype;if("modx-usergroup-permissions-panel"===newTab.itemId&&!this.stateful){const vTabPanel=newTab.items?.items[0];vTabPanel&&"modx-vtabs"===vTabPanel.xtype&&vTabPanel.setActiveTab(0)}this.clearFiltersBeforeChange(currentTab,resetVerticalTabPanelFilters,changedBetweenVtabs)}}})}})},Ext.extend(MODx.Tabs,Ext.TabPanel,{findGridObject:function(itemsSource){const grid=itemsSource.find((obj=>Object.entries(obj).find((([key,value])=>"xtype"===key&&value.includes("-grid-")))));if(grid)return grid;const nextItemsSource=itemsSource?.items;nextItemsSource&&this.findGridObject(nextItemsSource)},clearFiltersBeforeChange:function(tabObj,resetVtabFilters,changedVtabs){let itemsSource,gridObj=null;if(itemsSource=resetVtabFilters?changedVtabs?tabObj.items:tabObj.items.items[0].activeTab.items:tabObj.items,itemsSource.length>0&&(gridObj=this.findGridObject(itemsSource),!gridObj)){let customItemsSource=null;itemsSource?.map["modx-tree-panel-usergroup"]?customItemsSource=itemsSource.map["modx-tree-panel-usergroup"].items:itemsSource?.map["packages-breadcrumbs"]&&(customItemsSource=itemsSource.map["card-container"].items.map["modx-panel-packages"].items),customItemsSource&&(gridObj=this.findGridObject(customItemsSource))}if(gridObj){const toolbar=gridObj.getTopToolbar(),filterIds=[];toolbar&&toolbar.items.items.length>0&&toolbar.items.items.forEach((cmp=>{cmp.xtype&&(cmp.xtype.includes("combo")||"textfield"===cmp.xtype)&&cmp.itemId&&filterIds.push(cmp.itemId)})),filterIds.length>0&&gridObj.clearGridFilters(filterIds)}}}),Ext.reg("modx-tabs",MODx.Tabs),MODx.VerticalTabs=function(config={}){Ext.applyIf(config,{cls:"vertical-tabs-panel",headerCfg:{tag:"div",cls:"x-tab-panel-header vertical-tabs-header"},bwrapCfg:{tag:"div",cls:"x-tab-panel-bwrap vertical-tabs-bwrap"},defaults:{bodyCssClass:"vertical-tabs-body",autoScroll:!0,autoHeight:!0,autoWidth:!0,layout:"form"}}),MODx.VerticalTabs.superclass.constructor.call(this,config),this.config=config,this.on({afterrender:function(){if(MODx.request&&Object.prototype.hasOwnProperty.call(MODx.request,"vtab")){const tabId=parseInt(MODx.request.vtab,10);this.setActiveTab(tabId)}}})},Ext.extend(MODx.VerticalTabs,MODx.Tabs),Ext.reg("modx-vtabs",MODx.VerticalTabs),Ext.Window.prototype.floating={shadow:!1},Ext.override(Ext.Window,{animShow:function(){this.afterShow();var win=this;setTimeout((function(){win.el.hasClass("anim-ready")||(win.el.addClass("anim-ready"),setTimeout((function(){void 0!==win.mask&&(win.mask instanceof Ext.Element?win.mask.addClass("fade-in"):win.mask.el.addClass("fade-in")),win.el.addClass("zoom-in")}),250))}),300)},animHide:function(){this.afterHide()},onShow:function(){if(this.el.hasClass("x-window-dlg"))this.mask.addClass("fade-in"),this.el.applyStyles({opacity:1});else{this.addClass("anim-ready");var win=this;setTimeout((function(){void 0!==win.mask&&(win.mask instanceof Ext.Element?win.mask.addClass("fade-in"):win.mask.el.addClass("fade-in")),win.el.addClass("zoom-in")}),250)}},onHide:function(){if(this.el.hasClass("zoom-in")){this.el.removeClass("zoom-in"),void 0!==this.mask&&(this.mask instanceof Ext.Element?this.mask.removeClass("fade-in"):this.mask.el.removeClass("fade-in")),this.addClass("zoom-out");var win=this;setTimeout((function(){win.isDestroyed||(win.el.hide(),win.el.removeClass("zoom-out"),win.el.removeClass("anim-ready"))}),250)}else this.el.hasClass("x-window-dlg")&&(this.el.applyStyles({opacity:0}),void 0!==this.mask&&(this.mask instanceof Ext.Element?this.mask.removeClass("fade-in"):this.mask.el.removeClass("fade-in")))}}),MODx.Window=function(config){config=config||{},Ext.applyIf(config,{modal:!1,layout:"auto",closeAction:"hide",shadow:!0,resizable:!0,collapsible:!0,maximizable:!0,autoHeight:!1,autoScroll:!0,allowDrop:!0,width:400,constrain:!0,constrainHeader:!0,cls:"modx-window",buttons:[{text:config.cancelBtnText||_("cancel"),scope:this,handler:function(){"close"!==config.closeAction?this.hide():this.close()}},{text:config.saveBtnText||_("save"),cls:"primary-button",scope:this,handler:this.submit}],record:{},keys:[{key:Ext.EventObject.ENTER,fn:function(keyCode,event){var elem=event.getTarget(),component=Ext.getCmp(elem.id);if(component instanceof Ext.form.TextArea)return component.append("\n");this.submit()},scope:this}]}),MODx.Window.superclass.constructor.call(this,config),this.options=config,this.config=config,this.addEvents({success:!0,failure:!0,beforeSubmit:!0,updateWindow:!1}),this._loadForm(),this.on("show",(function(){this.config.blankValues&&this.fp.getForm().reset(),this.config.allowDrop&&this.loadDropZones(),this.syncSize(),this.focusFirstField()}),this),this.on("afterrender",(function(){this.originalHeight=this.el.getHeight(),this.toolsHeight=this.originalHeight-this.body.getHeight()+50,this.resizeWindow()})),Ext.EventManager.onWindowResize(this.resizeWindow,this)},Ext.extend(MODx.Window,Ext.Window,{_loadForm:function(){if(this.checkIfLoaded(this.config.record||null))return!1;var r=this.config.record;if(this.config.fields)for(var l=this.config.fields.length,i=0;i0){var fld=this.findFirstTextField();fld&&fld.focus(!1,200)}},findFirstTextField:function(i){i=i||0;var fld=this.fp.getForm().items.itemAt(i);return!!fld&&((fld.isXType("combo")||fld.isXType("checkbox")||fld.isXType("radio")||fld.isXType("displayfield")||fld.isXType("statictextfield")||fld.isXType("hidden"))&&(i+=1,fld=this.findFirstTextField(i)),fld)},submit:function(close){close=!1!==close;var f=this.fp.getForm();f.isValid()&&this.fireEvent("beforeSubmit",f.getValues())&&f.submit({waitMsg:this.config.waitMsg||_("saving"),submitEmptyText:!1!==this.config.submitEmptyText,scope:this,failure:function(frm,a){this.fireEvent("failure",{f:frm,a})&&MODx.form.Handler.errorExt(a.result,frm),this.doLayout()},success:function(frm,a){this.config.success&&Ext.callback(this.config.success,this.config.scope||this,[frm,a]),this.fireEvent("success",{f:frm,a}),close&&("close"!==this.config.closeAction?this.hide():this.close()),this.doLayout()}})},createForm:function(config){return Ext.applyIf(this.config,{formFrame:!0,border:!1,bodyBorder:!1,autoHeight:!0}),config=config||{},Ext.applyIf(config,{labelAlign:this.config.labelAlign||"top",labelWidth:this.config.labelWidth||100,labelSeparator:this.config.labelSeparator||"",frame:this.config.formFrame,border:this.config.border,bodyBorder:this.config.bodyBorder,autoHeight:this.config.autoHeight,anchor:"100% 100%",errorReader:MODx.util.JSONReader,defaults:this.config.formDefaults||{msgTarget:this.config.msgTarget||"under"},url:this.config.url,baseParams:this.config.baseParams||{},fileUpload:this.config.fileUpload||!1}),new Ext.FormPanel(config)},renderForm:function(){this.fp.on("destroy",(function(){Ext.EventManager.removeResizeListener(this.resizeWindow,this)}),this),this.add(this.fp)},checkIfLoaded:function(r){return r=r||{},!(!this.fp||!this.fp.getForm())&&(this.fp.getForm().reset(),this.fp.getForm().setValues(r),!0)},setValues:function(r){if(null===r)return!1;this.fp.getForm().setValues(r)},reset:function(){this.fp.getForm().reset()},hideField:function(f){f.disable(),f.hide();var d=f.getEl().up(".x-form-item");d&&d.setDisplayed(!1)},showField:function(f){f.enable(),f.show();var d=f.getEl().up(".x-form-item");d&&d.setDisplayed(!0)},loadDropZones:function(){if(this._dzLoaded)return!1;this.fp.getForm().items.each((function(fld){fld.isFormField&&(fld.isXType("textfield")||fld.isXType("textarea"))&&!fld.isXType("combo")&&new MODx.load({xtype:"modx-treedrop",target:fld,targetEl:fld.getEl().dom})})),this._dzLoaded=!0},resizeWindow:function(){var viewHeight=Ext.getBody().getViewSize().height,el=this.fp.getForm().el;viewHeight
    {name:htmlEncode}',"
    {description:htmlEncode}
    ")}),MODx.combo.UserGroup.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.UserGroup,MODx.combo.ComboBox),Ext.reg("modx-combo-usergroup",MODx.combo.UserGroup),MODx.combo.UserGroupRole=function(config){config=config||{},Ext.applyIf(config,{name:"role",hiddenName:"role",displayField:"name",valueField:"id",fields:["name","id"],pageSize:20,url:MODx.config.connector_url,baseParams:{action:"Security/Role/GetList"}}),MODx.combo.UserGroupRole.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.UserGroupRole,MODx.combo.ComboBox),Ext.reg("modx-combo-usergrouprole",MODx.combo.UserGroupRole),MODx.combo.EventGroup=function(config){config=config||{},Ext.applyIf(config,{name:"group",hiddenName:"group",displayField:"name",valueField:"name",fields:["name"],pageSize:20,url:MODx.config.connector_url,baseParams:{action:"System/Event/GroupList"},tpl:new Ext.XTemplate('
    {name:htmlEncode}',"
    ")}),MODx.combo.EventGroup.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.EventGroup,MODx.combo.ComboBox),Ext.reg("modx-combo-eventgroup",MODx.combo.EventGroup),MODx.combo.ResourceGroup=function(config){config=config||{},Ext.applyIf(config,{name:"resourcegroup",hiddenName:"resourcegroup",displayField:"name",valueField:"id",fields:["name","id"],pageSize:20,url:MODx.config.connector_url,baseParams:{action:"Security/ResourceGroup/GetList"}}),MODx.combo.ResourceGroup.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.ResourceGroup,MODx.combo.ComboBox),Ext.reg("modx-combo-resourcegroup",MODx.combo.ResourceGroup),MODx.combo.Context=function(config){config=config||{},Ext.applyIf(config,{name:"context",hiddenName:"context",displayField:"key",valueField:"key",fields:["key","name"],pageSize:20,url:MODx.config.connector_url,baseParams:{action:"Context/GetList",exclude:config.exclude||""},tpl:new Ext.XTemplate('
    {name:htmlEncode} ({key:htmlEncode})
    ')}),MODx.combo.Context.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Context,MODx.combo.ComboBox),Ext.reg("modx-combo-context",MODx.combo.Context),MODx.combo.Policy=function(config){config=config||{},Ext.applyIf(config,{name:"policy",hiddenName:"policy",displayField:"name",valueField:"id",fields:["id","name","permissions"],allowBlank:!1,editable:!1,pageSize:20,url:MODx.config.connector_url,baseParams:{action:"Security/Access/Policy/GetList"}}),MODx.combo.Policy.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Policy,MODx.combo.ComboBox),Ext.reg("modx-combo-policy",MODx.combo.Policy),MODx.combo.Template=function(config){config=config||{},Ext.applyIf(config,{url:MODx.config.connector_url,baseParams:{action:"Element/Template/GetList",combo:!0},fields:["id","templatename","description","category_name","preview","time"],name:"template",hiddenName:"template",displayField:"templatename",valueField:"id",pageSize:20,allowBlank:!0,editable:!0,typeAhead:!0,tpl:new Ext.XTemplate('
    {this.label:htmlEncode}
    {templatename:htmlEncode}
    {description:htmlEncode()}
    ',{group:null,label:null,getGroup:function(label,time){var group=time+"_"+label;return group===this.group||Ext.isEmpty(group)?null:(this.group=group,this.label=label)}})}),MODx.combo.Template.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Template,MODx.combo.ComboBox),Ext.reg("modx-combo-template",MODx.combo.Template),MODx.combo.Category=function(config){config=config||{},Ext.applyIf(config,{name:"category",hiddenName:"category",displayField:"name",valueField:"id",fields:["id","category","parent","name"],forceSelection:!0,typeAhead:!1,allowBlank:!0,editable:!1,enableKeyEvents:!0,pageSize:20,url:MODx.config.connector_url,baseParams:{action:"Element/Category/GetList",showNone:!0,limit:0}}),MODx.combo.Category.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Category,MODx.combo.ComboBox,{_onblur:function(t,e){var v=this.getRawValue();this.setRawValue(v),this.setValue(v,!0)}}),Ext.reg("modx-combo-category",MODx.combo.Category),MODx.combo.Language=function(config){config=config||{},Ext.applyIf(config,{name:"language",hiddenName:"language",displayField:"name",valueField:"name",fields:["name"],typeAhead:!0,minChars:1,editable:!0,allowBlank:!0,url:MODx.config.connector_url,baseParams:{action:"System/Language/GetList"}}),MODx.combo.Language.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Language,MODx.combo.ComboBox),Ext.reg("modx-combo-language",MODx.combo.Language),MODx.combo.Charset=function(config){config=config||{},Ext.applyIf(config,{name:"charset",hiddenName:"charset",displayField:"text",valueField:"value",fields:["value","text"],forceSelection:!0,typeAhead:!1,editable:!1,allowBlank:!1,url:MODx.config.connector_url,baseParams:{action:"System/Charset/GetList"}}),MODx.combo.Charset.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Charset,MODx.combo.ComboBox),Ext.reg("modx-combo-charset",MODx.combo.Charset),MODx.combo.RTE=function(config){config=config||{},Ext.applyIf(config,{name:"rte",hiddenName:"rte",displayField:"value",valueField:"value",fields:["value"],forceSelection:!0,typeAhead:!1,editable:!1,allowBlank:!1,url:MODx.config.connector_url,baseParams:{action:"System/Rte/GetList"}}),MODx.combo.RTE.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.RTE,MODx.combo.ComboBox),Ext.reg("modx-combo-rte",MODx.combo.RTE),MODx.combo.Role=function(config){config=config||{},Ext.applyIf(config,{name:"role",hiddenName:"role",forceSelection:!0,typeAhead:!1,editable:!1,allowBlank:!1,pageSize:20,url:MODx.config.connector_url,baseParams:{action:"Security/Role/GetList",addNone:!0}}),MODx.combo.Role.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Role,MODx.combo.ComboBox),Ext.reg("modx-combo-role",MODx.combo.Role),MODx.combo.ContentType=function(config){config=config||{},Ext.applyIf(config,{name:"content_type",hiddenName:"content_type",forceSelection:!0,typeAhead:!1,editable:!1,allowBlank:!1,pageSize:20,url:MODx.config.connector_url,baseParams:{action:"System/ContentType/GetList"}}),MODx.combo.ContentType.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.ContentType,MODx.combo.ComboBox),Ext.reg("modx-combo-content-type",MODx.combo.ContentType),MODx.combo.ContentDisposition=function(config){config=config||{},Ext.applyIf(config,{store:new Ext.data.SimpleStore({fields:["d","v"],data:[[_("inline"),0],[_("attachment"),1]]}),name:"content_dispo",hiddenName:"content_dispo",displayField:"d",valueField:"v",mode:"local",triggerAction:"all",editable:!1,pageSize:20,selectOnFocus:!1,preventRender:!0}),MODx.combo.ContentDisposition.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.ContentDisposition,MODx.combo.ComboBox),Ext.reg("modx-combo-content-disposition",MODx.combo.ContentDisposition),MODx.combo.ClassDerivatives=function(config){config=config||{},Ext.applyIf(config,{name:"class",hiddenName:"class",url:MODx.config.connector_url,baseParams:{action:"System/Derivatives/GetList",class:"MODX\\Revolution\\modResource"},displayField:"name",valueField:"id",fields:["id","name"],forceSelection:!0,typeAhead:!1,editable:!1,allowBlank:!1,pageSize:20}),MODx.combo.ClassDerivatives.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.ClassDerivatives,MODx.combo.ComboBox),Ext.reg("modx-combo-class-derivatives",MODx.combo.ClassDerivatives),MODx.combo.Namespace=function(config){config=config||{},Ext.applyIf(config,{name:"namespace",hiddenName:"namespace",typeAhead:!0,minChars:1,queryParam:"query",editable:!0,allowBlank:!0,preselectValue:!1,pageSize:20,url:MODx.config.connector_url,baseParams:{action:"Workspace/PackageNamespace/GetList"},fields:["name"],displayField:"name",valueField:"name"}),MODx.combo.Namespace.superclass.constructor.call(this,config),!1!==config.preselectValue&&(this.store.on("load",this.preselectFirstValue,this,{single:!0}),this.store.load())},Ext.extend(MODx.combo.Namespace,MODx.combo.ComboBox,{preselectFirstValue:function(r){var item;if(""==this.config.preselectValue)item=r.getAt(0);else{var found=r.find("name",this.config.preselectValue);item=-1!=found?r.getAt(found):r.getAt(0)}item&&(this.setValue(item.data.name),this.fireEvent("select",this,item))}}),Ext.reg("modx-combo-namespace",MODx.combo.Namespace),MODx.combo.Browser=function(config){config=config||{},Ext.applyIf(config,{width:400,triggerAction:"all",triggerClass:"x-form-file-trigger",source:config.source||MODx.config.default_media_source}),MODx.combo.Browser.superclass.constructor.call(this,config),this.config=config},Ext.extend(MODx.combo.Browser,Ext.form.TriggerField,{browser:null,onTriggerClick:function(btn){return!this.disabled&&(this.browser=MODx.load({xtype:"modx-browser",closeAction:"close",id:Ext.id(),multiple:!0,source:this.config.source||MODx.config.default_media_source,hideFiles:this.config.hideFiles||!1,rootVisible:this.config.rootVisible||!1,allowedFileTypes:this.config.allowedFileTypes||"",wctx:this.config.wctx||"web",openTo:this.config.openTo||"",rootId:this.config.rootId||"/",hideSourceCombo:this.config.hideSourceCombo||!1,listeners:{select:{fn:function(data){this.setValue(data.relativeUrl),this.fireEvent("select",data)},scope:this}}}),this.browser.show(btn),!0)},onDestroy:function(){MODx.combo.Browser.superclass.onDestroy.call(this)}}),Ext.reg("modx-combo-browser",MODx.combo.Browser),MODx.combo.Country=function(config){config=config||{},Ext.applyIf(config,{name:"country",hiddenName:"country",url:MODx.config.connector_url,baseParams:{action:"System/Country/GetList",combo:!0},displayField:"country",valueField:"iso",fields:["iso","country","value"],editable:!0,typeAhead:!0}),MODx.combo.Country.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Country,MODx.combo.ComboBox),Ext.reg("modx-combo-country",MODx.combo.Country),MODx.combo.Gender=function(config){config=config||{},Ext.applyIf(config,{store:new Ext.data.SimpleStore({fields:["d","v"],data:[["",0],[_("user_male"),1],[_("user_female"),2],[_("user_other"),3]]}),displayField:"d",valueField:"v",mode:"local",triggerAction:"all",editable:!1,selectOnFocus:!1}),MODx.combo.Gender.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Gender,Ext.form.ComboBox),Ext.reg("modx-combo-gender",MODx.combo.Gender),MODx.combo.PropertySet=function(config){config=config||{},Ext.applyIf(config,{name:"propertyset",hiddenName:"propertyset",url:MODx.config.connector_url,baseParams:{action:"Element/PropertySet/GetList"},displayField:"name",valueField:"id",fields:["id","name"],editable:!1,pageSize:20,width:300}),MODx.combo.PropertySet.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.PropertySet,MODx.combo.ComboBox),Ext.reg("modx-combo-property-set",MODx.combo.PropertySet),MODx.ChangeParentField=function(config){config=config||{},Ext.applyIf(config,{triggerAction:"all",editable:!1,readOnly:!1,formpanel:"modx-panel-resource",parentcmp:"modx-resource-parent-hidden",contextcmp:"modx-resource-context-key",currentid:MODx.request.id}),MODx.ChangeParentField.superclass.constructor.call(this,config),this.config=config,this.on("click",this.onTriggerClick,this),this.addEvents({end:!0}),this.on("end",this.end,this)},Ext.extend(MODx.ChangeParentField,Ext.form.TriggerField,{oldValue:!1,oldDisplayValue:!1,end:function(p){var t=Ext.getCmp("modx-resource-tree");t&&(p.d=p.d||p.v,t.removeListener("click",this.handleChangeParent,this),t.on("click",t._handleClick,t),t.disableHref=!1,MODx.debug("Setting parent to: "+p.v),Ext.getCmp(this.config.parentcmp).setValue(p.v),this.setValue(p.d),this.oldValue=!1,"modx-template-picker-parent-id"!==this.config.parentcmp&&Ext.getCmp(this.config.formpanel).fireEvent("fieldChange"))},onTriggerClick:function(){if(this.disabled)return!1;if(this.oldValue)return this.fireEvent("end",{v:this.oldValue,d:this.oldDisplayValue}),!1;if(MODx.debug("onTriggerClick"),!Ext.getCmp("modx-resource-tree")){MODx.debug("no tree found, trying to activate");var tp=Ext.getCmp("modx-leftbar-tabpanel");return tp?(tp.on("tabchange",(function(tbp,tab){"modx-resource-tree-ct"==tab.id&&this.disableTreeClick()}),this),tp.activate("modx-resource-tree-ct")):MODx.debug("no tabpanel"),!1}this.disableTreeClick()},disableTreeClick:function(){return MODx.debug("Disabling tree click"),t=Ext.getCmp("modx-resource-tree"),t?(this.oldDisplayValue=this.getValue(),this.oldValue=Ext.getCmp(this.config.parentcmp).getValue(),this.setValue(_("resource_parent_select_node")),t.expand(),t.removeListener("click",t._handleClick),t.on("click",this.handleChangeParent,this),t.disableHref=!0,!0):(MODx.debug("No tree found in disableTreeClick!"),!1)},handleChangeParent:function(node,e){var t=Ext.getCmp("modx-resource-tree");if(!t)return!1;t.disableHref=!0;var id=node.id.split("_");if((id=id[1])==this.config.currentid)return MODx.msg.alert("",_("resource_err_own_parent")),!1;var ctxf=Ext.getCmp(this.config.contextcmp);if(ctxf){var ctxv=ctxf.getValue();node.attributes&&node.attributes.ctx!=ctxv&&ctxf.setValue(node.attributes.ctx)}return this.fireEvent("end",{v:"modContext"!=node.attributes.type?id:node.attributes.pk,d:Ext.util.Format.stripTags(node.text)}),e.preventDefault(),e.stopEvent(),!0}}),Ext.reg("modx-field-parent-change",MODx.ChangeParentField),MODx.combo.TVWidget=function(config){config=config||{},Ext.applyIf(config,{name:"widget",hiddenName:"widget",displayField:"name",valueField:"value",fields:["value","name"],editable:!1,url:MODx.config.connector_url,baseParams:{action:"Element/TemplateVar/Renders/GetOutputs"},value:"default"}),MODx.combo.TVWidget.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.TVWidget,MODx.combo.ComboBox),Ext.reg("modx-combo-tv-widget",MODx.combo.TVWidget),MODx.combo.TVInputType=function(config){config=config||{},Ext.applyIf(config,{name:"type",hiddenName:"type",displayField:"name",valueField:"value",editable:!1,fields:["value","name"],url:MODx.config.connector_url,baseParams:{action:"Element/TemplateVar/Renders/GetInputs"},value:"text"}),MODx.combo.TVInputType.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.TVInputType,MODx.combo.ComboBox),Ext.reg("modx-combo-tv-input-type",MODx.combo.TVInputType),MODx.combo.Dashboard=function(config){config=config||{},Ext.applyIf(config,{name:"dashboard",hiddenName:"dashboard",displayField:"name",valueField:"id",fields:["id","name","description"],pageSize:20,url:MODx.config.connector_url,baseParams:{action:"System/Dashboard/GetList"},tpl:new Ext.XTemplate('','
    ','

    {name:htmlEncode}

    ','

    {description:htmlEncode}

    ',"
    ")}),MODx.combo.Dashboard.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Dashboard,MODx.combo.ComboBox),Ext.reg("modx-combo-dashboard",MODx.combo.Dashboard),MODx.combo.MediaSource=function(config){config=config||{},Ext.applyIf(config,{name:"source",hiddenName:"source",displayField:"name",valueField:"id",fields:["id","name","description"],pageSize:20,url:MODx.config.connector_url,baseParams:{action:"Source/GetList"},tpl:new Ext.XTemplate('','
    ','

    {name:htmlEncode}

    ','

    {description:htmlEncode}

    ',"
    ")}),MODx.combo.MediaSource.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.MediaSource,MODx.combo.ComboBox),Ext.reg("modx-combo-source",MODx.combo.MediaSource),MODx.combo.MediaSourceType=function(config){config=config||{},Ext.applyIf(config,{name:"class_key",hiddenName:"class_key",displayField:"name",valueField:"class",fields:["id","class","name","description"],pageSize:20,url:MODx.config.connector_url,baseParams:{action:"Source/Type/GetList"},tpl:new Ext.XTemplate('','
    ','

    {name:htmlEncode}

    ','

    {description:htmlEncode}

    ',"
    ")}),MODx.combo.MediaSourceType.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.MediaSourceType,MODx.combo.ComboBox),Ext.reg("modx-combo-source-type",MODx.combo.MediaSourceType),MODx.combo.Authority=function(config){config=config||{},Ext.applyIf(config,{name:"authority",hiddenName:"authority",forceSelection:!0,typeAhead:!1,editable:!1,allowBlank:!1,pageSize:20,url:MODx.config.connector_url,baseParams:{action:"Security/Role/GetAuthorityList",addNone:!0}}),MODx.combo.Authority.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Authority,MODx.combo.ComboBox),Ext.reg("modx-combo-authority",MODx.combo.Authority),MODx.combo.ManagerTheme=function(config){config=config||{},Ext.applyIf(config,{name:"theme",hiddenName:"theme",displayField:"theme",valueField:"theme",fields:["theme"],url:MODx.config.connector_url,baseParams:{action:"Workspace/Theme/GetList"},typeAhead:!1,editable:!1}),MODx.combo.ManagerTheme.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.ManagerTheme,MODx.combo.ComboBox),Ext.reg("modx-combo-manager-theme",MODx.combo.ManagerTheme),MODx.combo.SettingKey=function(config){config=config||{},Ext.applyIf(config,{name:"key",hiddenName:"key",displayField:"key",valueField:"key",fields:["key"],url:MODx.config.connector_url,baseParams:{action:"System/Settings/GetList"},triggerAction:"all",editable:!0,forceSelection:!1,pageSize:20}),MODx.combo.SettingKey.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.SettingKey,MODx.combo.ComboBox),Ext.reg("modx-combo-setting-key",MODx.combo.SettingKey),MODx.combo.Visibility=function(config){config=config||{},Ext.applyIf(config,{name:"visibility",hiddenName:"visibility",store:new Ext.data.SimpleStore({fields:["d","v"],data:[[_("file_folder_visibility_public"),"public"],[_("file_folder_visibility_private"),"private"]]}),displayField:"d",valueField:"v",mode:"local",triggerAction:"all",editable:!1,selectOnFocus:!1,preventRender:!0,forceSelection:!0,enableKeyEvents:!0}),MODx.combo.Visibility.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Visibility,MODx.combo.ComboBox),Ext.reg("modx-combo-visibility",MODx.combo.Visibility),MODx.combo.Permission=function(config){config=config||{},Ext.applyIf(config,{name:"permission",hiddenName:"permission",displayField:"name",valueField:"name",fields:["name","description"],editable:!0,typeAhead:!1,forceSelection:!1,enableKeyEvents:!0,autoSelect:!1,pageSize:20,tpl:new Ext.XTemplate('
    {name:htmlEncode}','

    {description:htmlEncode}

    '),url:MODx.config.connector_url,baseParams:{action:"Security/Access/Permission/GetList"}}),MODx.combo.Permission.superclass.constructor.call(this,config)},Ext.extend(MODx.combo.Permission,MODx.combo.ComboBox),Ext.reg("modx-combo-permission",MODx.combo.Permission),Ext.namespace("MODx.grid"),MODx.grid.GridBase=function(config={}){if(this.config=config,this._loadStore(),this._loadColumnModel(),this._loadMenu(),config.paging){const pgItms=config.showPerPage?[`${_("per_page")}:`,{xtype:"textfield",cls:"x-tbar-page-size",value:config.pageSize||parseInt(MODx.config.default_per_page,10)||20,listeners:{change:{fn:this.onChangePerPage,scope:this},render:{fn:function(cmp){new Ext.KeyMap(cmp.getEl(),{key:Ext.EventObject.ENTER,fn:this.blur,scope:cmp})},scope:this}}}]:[];if(config.pagingItems)for(let i=0;i 1 ? '${config.pluralText||_("records")}' : '${config.singleText||_("record")}']})`};Ext.applyIf(config.groupingConfig,groupingConfig),Object.hasOwn(config,"viewConfig")&&Object.hasOwn(config.viewConfig,"getRowClass")&&Ext.applyIf(config.groupingConfig,{getRowClass:config.viewConfig.getRowClass}),Ext.applyIf(config,{view:new Ext.grid.GroupingView(config.groupingConfig)})}if(config.tbar)for(let ix=0;ix1)return!1;return!0};config.columns&&Array.isArray(config.columns)&&(void 0===config.actionsColumnWidth&&isPercentage(config.columns)&&(defaultActionsColumnWidth=.1),config.columns.push({id:"modx-actions",width:config.actionsColumnWidth||defaultActionsColumnWidth,menuDisabled:!0,renderer:this.actionsColumnRenderer.bind(this)})),config.cm&&config.cm.columns&&Array.isArray(config.cm.columns)&&(void 0===config.actionsColumnWidth&&isPercentage(config.cm.columns)&&(defaultActionsColumnWidth=.1),config.cm.columns.push({id:"modx-actions",width:config.actionsColumnWidth||defaultActionsColumnWidth,menuDisabled:!0,renderer:this.actionsColumnRenderer.bind(this)}))}MODx.grid.GridBase.superclass.constructor.call(this,config),this.addEvents("beforeRemoveRow","afterRemoveRow"),this.on({click:{fn:this.onClickHandler,scope:this},rowcontextmenu:{fn:this._showMenu,scope:this}})},Ext.extend(MODx.grid.GridBase,Ext.grid.EditorGridPanel,{currentLanguage:MODx.config.cultureKey||"en",windows:{},protectedIdentifiers:null,permissionsProviderProp:"data",userCanEdit:!1,userCanCreate:!1,userCanDelete:!1,gridMenuActions:[],hasNestedFilters:!1,userHasPermissions:!1,userHasSavePermissions:!1,showActionsMenu:null,_loadColumnModel:function(){if(this.config.columns){const c=this.config.columns;for(let i=0;i
    ',{compiled:!0})},actionsColumnRenderer:function(value,metaData,record,rowIndex,colIndex,store){if(!1===this.showActionsMenu)return;if(this.showActionsMenu&&!this.gridMenuActions.includes("export")){const isProtected=record[this.permissionsProviderProp]?.isProtected||!1;if(!this.userHasSavePermissions&&isProtected)return;const hasPermissionsProp=Object.hasOwn(record[this.permissionsProviderProp],"permissions");if(!hasPermissionsProp&&Object.hasOwn(record.data,"cls")&&Ext.isEmpty(record.data.cls))return;if(hasPermissionsProp&&(Ext.isEmpty(record[this.permissionsProviderProp].permissions)||Object.values(record[this.permissionsProviderProp].permissions).every((permission=>!permission))))return}const actions=this.getActions.apply(this,arguments);return!0!==this.config.disableContextMenuAction&&actions.push({text:_("context_menu"),action:"contextMenu",icon:"gear"}),this._getActionsColumnTpl().apply({actions})},getActions:function(value,metaData,record,rowIndex,colIndex,store){return[]},actionContextMenu:function(record,rowIndex,e){this._showMenu(this,rowIndex,e)},addContextMenuItem:function(items){items.forEach((menuItem=>{if("-"===menuItem)this.menu.add("-");else{let handler=Ext.emptyFn;menuItem.handler?(handler=eval(menuItem.handler),handler&&"object"==typeof handler&&handler.xtype&&(handler=this.loadWindow.createDelegate(this,[handler],!0))):handler=function(item){const{options}=item,{id}=this.menu.record,doAction=(id,options)=>{const query=`?${Ext.urlEncode(options.params||{action:options.action})}&id=${id}`,content=Ext.get("modx_content");null===content?window.location.href=query:content.dom.src=query};options.confirm?Ext.Msg.confirm("",options.confirm,(function(e){"yes"===e&&doAction(id,options)}),this):doAction(id,options)},this.menu.add({id:menuItem.id||Ext.id(),text:menuItem.text,scope:menuItem.scope||this,options:menuItem,handler})}}))},setShowActionsMenu:function(action=null,permissions=[]){if(!0!==this.config.disableContextMenuAction)if(permissions.length>0)this.showActionsMenu=this.setUserHasPermissions(action,permissions);else{const permissionsValues=[];this.gridMenuActions.forEach((mode=>{const modePermission="userCanExport"===(mode="duplicate"===mode?"userCanCreate":`userCan${MODx.util.Format.firstToUpperCase(mode)}`)||this[mode];["userCanCreate","userCanEdit"].includes(mode)&&!0===modePermission&&(this.userHasSavePermissions=!0),permissionsValues.push(modePermission)})),this.showActionsMenu=!(0===permissionsValues.length||!0===permissionsValues.every((value=>!1===value)))}else this.showActionsMenu=!1},_showMenu:function(grid,rowIndex,e){let menu;e.stopEvent(),e.preventDefault(),this.menu.record=this.getStore().getAt(rowIndex).data,this.menu.recordIndex=rowIndex,this.getSelectionModel().isSelected(rowIndex)||this.getSelectionModel().selectRow(rowIndex),this.menu.removeAll(),this.getMenu&&(menu=this.getMenu(grid,rowIndex,e),menu&&menu.length&&menu.length>0&&this.addContextMenuItem(menu)),(!menu||menu.length<=0)&&this.menu.record.menu&&this.addContextMenuItem(this.menu.record.menu),this.menu.items.length>0&&this.menu.showAt(e.xy)},checkEditable:function(e){this.checkCellIsEditable(e)},checkCellIsEditable:function(e){if(-1===(e.record.data.perm||"").indexOf("edit"))return!1;switch(e.grid.xtype){case"modx-grid-role":{const isAuthorityField="authority"===e.field;if(e.record[this.permissionsProviderProp].isAssigned&&isAuthorityField)return!1;break}}return!0},setEditableCellClasses:function(record,lockConditions=[],lockedClasses="",conditionsRequireAll=!0){const userCanEditRecord=this.userCanEditRecord(record),lockedCSS=lockedClasses||"locked";let classes="",shouldLock=!1;return lockConditions.length>0&&(shouldLock=conditionsRequireAll?lockConditions.every((condition=>!0===Boolean(condition))):lockConditions.some((condition=>!0===Boolean(condition)))),this.userCanEdit&&this.userHasRecordPermissions(record)&&userCanEditRecord?userCanEditRecord&&shouldLock&&(classes=lockedCSS):classes="editor-disabled",classes},setUserHasPermissions:function(action,permissions){const permissionsList=permissions.map((item=>item.trim())),hasPermissions=action?permissionsList.every((permission=>MODx.perm[permission])):permissionsList.some((permission=>MODx.perm[permission]));return action&&(this[`userCan${MODx.util.Format.firstToUpperCase(action)}`]=hasPermissions),hasPermissions&&(this.userHasPermissions=!0),hasPermissions},setUserCanEdit:function(permissions){this.setUserHasPermissions("edit",permissions)},setUserCanCreate:function(permissions){this.setUserHasPermissions("create",permissions)},setUserCanDelete:function(permissions){this.setUserHasPermissions("delete",permissions)},userHasRecordPermissions:function(record){const objPermissions=record[this.permissionsProviderProp].permissions;return!Ext.isEmpty(objPermissions)&&Object.values(objPermissions).some((permission=>!0===Boolean(permission)))},userCanEditRecord:function(record,action="update"){const objPermissions=record[this.permissionsProviderProp].permissions;return!Ext.isEmpty(objPermissions)&&!0===objPermissions[action]},userCanDeleteRecords:function(records){return records.some((record=>this.userCanDeleteRecord(record)))},userCanDeleteRecord:function(record,action="delete"){const objPermissions=record[this.permissionsProviderProp].permissions;return!Ext.isEmpty(objPermissions)&&!record[this.permissionsProviderProp].isProtected&&!0===objPermissions[action]},userCanDuplicateRecord:function(record){const objPermissions=record[this.permissionsProviderProp].permissions;return!Ext.isEmpty(objPermissions)&&!0===objPermissions.duplicate},recordIsProtected:function(subject,protectedIdentifiers){return!Ext.isEmpty(protectedIdentifiers)&&(protectedIdentifiers=protectedIdentifiers.map((identifier=>"string"==typeof identifier?identifier.trim():identifier))).includes(subject)},valueIsReserved:function(reservedValues,value){return Array.isArray(reservedValues)||(reservedValues=reservedValues.split(",")),reservedValues.some((reserved=>reserved.toLowerCase()===value.toLowerCase()))},findTabPanel:function(referenceCmp){if(!Object.hasOwn(referenceCmp,"ownerCt"))return console.error("MODx.grid.GridBase::findTabPanel: This component must have an ownerCt to find its tab panel."),!1;const container=referenceCmp.ownerCt;return Object.hasOwn(container,"xtype")&&container.xtype.includes("tabs")?container:this.findTabPanel(container)},applyRequestFilter:function(tabPanelIndex,requestKey="policy",tabPanelType="vtab",setEmptyToString=!1){const emptyVal=setEmptyToString?"":null;return Object.prototype.hasOwnProperty.call(MODx.request,tabPanelType)&&parseInt(MODx.request[tabPanelType],10)===tabPanelIndex&&Object.prototype.hasOwnProperty.call(MODx.request,requestKey)?MODx.util.url.getParamValue(requestKey):emptyVal},applyGridFilter:function(cmp,param="query"){const filterValue=cmp.getValue(),store=this.getStore(),urlParams={},tabPanel=this.findTabPanel(this),bottomToolbar=this.getBottomToolbar();let parentTabItems,activeParentTabIdx,hasParentTabPanel=!1;if(Ext.isEmpty(filterValue)?MODx.request[param]?urlParams[param]=MODx.request[param]:MODx.util.url.clearParam(cmp):urlParams[param]=filterValue,"ns"===param?store.baseParams.namespace=filterValue:store.baseParams[param]=filterValue,tabPanel){if("modx-vtabs"===tabPanel.xtype){const parentTabPanel=this.findTabPanel(tabPanel);if(parentTabPanel){const activeParentTab=parentTabPanel.getActiveTab();hasParentTabPanel=!0,parentTabItems=parentTabPanel.items,activeParentTabIdx=parentTabItems.indexOf(activeParentTab)}}const activeTab=tabPanel.getActiveTab(),tabItems=tabPanel.items,activeTabIdx=tabItems.indexOf(activeTab);hasParentTabPanel?(tabItems.length>1&&(urlParams.vtab=activeTabIdx),parentTabItems.length>1&&(urlParams.tab=activeParentTabIdx)):tabItems.length>1&&(urlParams.tab=activeTabIdx)}store.load(),MODx.util.url.setParams(urlParams),bottomToolbar&&bottomToolbar.changePage(1)},clearGridFilters:function(items){const store=this.getStore(),bottomToolbar=this.getBottomToolbar();(Array.isArray(items)?items:items.split(",")).forEach((item=>{const itemData=item.replace(/\s+/g,"").split(":"),itemId=itemData[0],itemDefaultVal=2===itemData.length?itemData[1]:null,cmp=this.getFilterComponent(itemId),cmpParam=MODx.util.url.getParamNameFromCmp(cmp),isCombo=cmp?.xtype?.includes("combo");if(isCombo?""===itemDefaultVal?cmp.setValue(null):cmp.setValue(itemDefaultVal):cmp.setValue(""),!Ext.isEmpty(itemDefaultVal)){Object.keys(cmp.baseParams).forEach((param=>{switch(param){case"namespace":cmp.baseParams[param]="core";break;case"topic":cmp.baseParams[param]="default"}}))}isCombo&&"local"!==cmp.mode&&cmp.getStore().load(),store.baseParams[cmpParam]=itemDefaultVal})),store.load(),MODx.util.url.clearAllParams(),bottomToolbar&&bottomToolbar.changePage(1)},getFilterComponent:function(filterId){const topToolbar=this.getTopToolbar(),cmp=this.hasNestedFilters&&"filter-query"!==filterId?topToolbar.find("itemId",`${filterId}-container`)[0].getComponent(filterId):topToolbar.getComponent(filterId);if(void 0!==cmp)return cmp;console.error(`getFilterComponent: The filter component with itemId '${filterId}' could not be retrieved.`)},refreshFilterOptions:function(filterData=[],clearDependentParams=!0){filterData.length>0&&(filterData.forEach((data=>{const filter=this.getFilterComponent(data.filterId);if(filter){const store=filter.getStore();if(filter.setValue(""),store){if(Object.hasOwn(data,"dependentParams")){(Array.isArray(data.dependentParams)?data.dependentParams:data.dependentParams.split(",")).forEach((param=>{clearDependentParams&&Object.hasOwn(store.baseParams,param)&&(store.baseParams[param]="")}))}store.load()}}})),this.refresh())},updateDependentFilter:function(filterId,paramKey,paramValue,clearValue=!1){const filter=this.getFilterComponent(filterId),filterStore=filter?filter.getStore():null;filterStore&&"string"==typeof paramKey&&(clearValue&&filter.setValue(""),filterStore.baseParams[paramKey]=paramValue,filterStore.load())},renderEditableColumn:function(renderer){return function(value,metaData,record,rowIndex,colIndex,store){if(renderer){if("function"==typeof renderer.fn){const scope=!!renderer.scope&&renderer.scope;renderer=renderer.fn.bind(scope)}"function"==typeof renderer&&(value=renderer(value,metaData,record,rowIndex,colIndex,store))}return metaData.css=["x-editable-column",metaData.css||""].join(" "),value}},renderLink:function(content,attributes={},isSimulated=!1,isSimulatedTag="span"){const tag=isSimulated?isSimulatedTag:"a",classes=isSimulated?"x-grid-link simulated-link":"x-grid-link",el=new Ext.Element(document.createElement(tag));return el.addClass(classes),Object.hasOwn(attributes,"title")||(attributes.title=_("edit")),Object.entries(attributes).forEach((([attr,value])=>{el.dom[attr]=value})),el.dom.innerHTML=Ext.util.Format.htmlEncode(content),el.dom.outerHTML},rendYesNo:function(v,metaData){switch(1!==v&&"1"!==v||(v=!0),0!==v&&"0"!==v||(v=!1),v){case!0:case"true":case 1:return metaData.css+=" green",_("yes");case!1:case"false":case"":case 0:return metaData.css+=" red",_("no")}},rendPassword:function(v){let z="";for(let i=0;i0&&(params=[],options.linkParams.forEach((param=>{params.push(`${param.key}={${param.valueIndex}}`)})),params=`&${params.join("&")}`),new Ext.Template(`{${displayValueIndex}:htmlEncode}`,{compiled:!0})},getViewConfig:function(hasBulkActions=!0,hasObjectLevelPermissions=!0,markActiveRows=!1){return{forceFit:!0,scrollOffset:0,enableRowBody:!0,showPreview:!0,getRowClass:function(record,index,rowParams,store){const canDeleteRecord=this.grid.userCanDeleteRecord(record),rowClasses=[];if(this.cm&&Object.hasOwn(this.cm.config[0],"expandRow")&&rowClasses.push("x-grid3-row-collapsed"),markActiveRows&&(Object.hasOwn(record.data,"active")||Object.hasOwn(record.data,"visible"))){const activeClass=record.data.active||record.data.visible?"grid-row-active":"grid-row-inactive";rowClasses.push(activeClass)}return hasObjectLevelPermissions&&canDeleteRecord||(!hasBulkActions||canDeleteRecord||markActiveRows||rowClasses.push("disable-selection"),record[this.grid.permissionsProviderProp].isProtected&&rowClasses.push("modx-protected-row")),rowClasses.length?rowClasses.join(" "):""}}},getCreateButton:function(objectType,createHandler="create",createPermission="userCanCreate"){const handler="string"==typeof createHandler?this[createHandler]:createHandler;return{text:_(`${objectType.toLowerCase()}_create`)||_("create"),cls:"primary-button",handler,scope:this,listeners:{render:{fn:function(btn){("boolean"==typeof createPermission?createPermission:this[createPermission])||btn.hide()},scope:this}}}},getBulkActionsButton:function(objectType,deleteAction,pkType="int",...moreActions){const menuItems=[],additionalMenuItems=[],hasMoreActions=moreActions.length>0;if(hasMoreActions){const standardButtons={activate:{text:_("selected_activate"),itemId:"modx-bulk-menu-opt-activate",handler:this.activateSelected,scope:this},deactivate:{text:_("selected_deactivate"),itemId:"modx-bulk-menu-opt-deactivate",handler:this.deactivateSelected,scope:this}};moreActions.forEach((action=>{if("string"==typeof action){const key=action.toLowerCase();Object.hasOwn(standardButtons,key)&&additionalMenuItems.push(standardButtons[key])}})),menuItems.push(...additionalMenuItems),menuItems.push("-")}return menuItems.push({text:_("selected_remove"),itemId:"modx-bulk-menu-opt-remove",handler:this.removeSelected.createDelegate(this,[objectType,deleteAction,pkType]),scope:this}),{text:_("bulk_actions"),menu:menuItems,listeners:{render:{fn:function(btn){(!this.userCanDelete&&!hasMoreActions||!this.userCanDelete&&!this.userCanEdit&&hasMoreActions)&&btn.hide()},scope:this},click:{fn:function(btn){const removableItems=this.getRemovableItemsFromSelection(pkType),menuOptRemove=btn.menu.getComponent("modx-bulk-menu-opt-remove");if(0===removableItems.length?menuOptRemove.disable():menuOptRemove.enable(),hasMoreActions){const selections=this.getSelectionModel().getSelections();additionalMenuItems.forEach((item=>{const itemCmp=btn.menu.getComponent(item.itemId);0===selections.length?itemCmp.disable():itemCmp.enable()}))}},scope:this}}}},getQueryFilterField:function(filterSpec="filter-query",implementation="default"){let queryValue="";const filterSpecs=filterSpec.split(":"),filterId=filterSpecs[0].trim();return queryValue=2===filterSpecs.length?filterSpecs[1]:MODx.request.query?MODx.util.url.decodeParamValue(MODx.request.query):"",{xtype:"textfield",itemId:filterId,emptyText:_("search"),value:queryValue,cls:"filter-query",listeners:{change:{fn:function(cmp,newValue,oldValue){this.applyGridFilter(cmp);const usergroupTree=Ext.getCmp("modx-tree-usergroup");if("user-group-users"===implementation&&usergroupTree){const selectedNode=usergroupTree.getSelectionModel().getSelectedNode(),groupId=MODx.util.tree.getGroupIdFromNode(selectedNode);MODx.util.url.setParams({group:groupId})}},scope:this},afterrender:{fn:function(cmp){MODx.request.query&&this.applyGridFilter(cmp)},scope:this},render:{fn:function(cmp){new Ext.KeyMap(cmp.getEl(),{key:Ext.EventObject.ENTER,fn:this.blur,scope:cmp})},scope:this}}}},getClearFiltersButton:function(filters="filter-query",dependentFilterResets=null){if(Ext.isEmpty(filters))return console.error("MODx.grid.Grid::getClearFiltersButton: There was a problem creating the Clear Filter button because the supplied filters list is invalid."),{};const config={text:_("filter_clear"),itemId:"filter-clear",listeners:{click:{fn:function(cmp){if(cmp.dependentResets){cmp.dependentResets.split(",").forEach((reset=>{const[filterId,filterDataIndex]=reset.split(":").map((item=>item.trim()));this.updateDependentFilter(filterId,filterDataIndex,"",!0)}))}this.clearGridFilters(filters)},scope:this},mouseout:{fn:function(evt){this.removeClass("x-btn-focus")}}}};return dependentFilterResets&&(config.dependentResets=dependentFilterResets),config},editorYesNo:function(record={}){return Ext.applyIf(record,{store:new Ext.data.SimpleStore({fields:["d","v"],data:[[_("yes"),!0],[_("no"),!1]]}),displayField:"d",valueField:"v",mode:"local",triggerAction:"all",editable:!1,selectOnFocus:!1}),new Ext.form.ComboBox(record)},getSelectedAsList:function(){const sels=this.getSelectionModel().getSelections();if(sels.length<=0)return!1;let cs="";for(let i=0;i{const deletableRecord=record[this.permissionsProviderProp].permissions.delete;if(!record[this.permissionsProviderProp].isProtected&&deletableRecord){const item="string"===itemIdType?record.data[pk]:parseInt(record.data[pk],10);removableItems.push(item)}})),removableItems)},removeSelected:function(gridName,removeAction,pkType="int"){const removableSelections=this.getRemovableItemsFromSelection(pkType);let modalText,actionKey;if(0===removableSelections.length)return!1;if(modalText=1===removableSelections.length?_(`${gridName}_remove_confirm`,{name:removableSelections[0]})||_("confirm_remove"):_(`${gridName}_remove_multiple_confirm`)||_("confirm_remove_multiple"),"policy_template"===gridName)actionKey="templates";else actionKey=gridName.endsWith("y")?`${gridName.substring(0,gridName.length-1)}ies`:`${gridName}s`;return MODx.msg.confirm({title:_("selected_remove"),text:modalText,url:this.config.url,params:{action:removeAction,[actionKey]:removableSelections.join(",")},listeners:{success:{fn:function(response){this.getSelectionModel().clearSelections(!0),this.refresh(),this.fireEvent("afterRemoveRow",{...response,itemsRemoved:removableSelections})},scope:this}}}),!0},confirm:function(type,text){const p={action:type},k=this.config.primaryKey||"id";p[k]=this.menu.record[k],MODx.msg.confirm({title:_(type),text:_(text)||_("confirm_remove"),url:this.config.url,params:p,listeners:{success:{fn:this.refresh,scope:this}}})},remove:function(text,action){if(this.destroying)return MODx.grid.Grid.superclass.remove.apply(this,arguments);const{record}=this.menu,saveParams=this.config.saveParams||{},primaryKey=this.config.primaryKey||"id";text=text||"confirm_remove",Ext.apply(saveParams,{action:action||"remove"}),saveParams[primaryKey]=record[primaryKey],this.fireEvent("beforeRemoveRow",record)&&MODx.msg.confirm({title:_("warning"),text:_(text,record),url:this.config.url,params:saveParams,listeners:{success:{fn:function(){this.removeActiveRow(record)},scope:this}}})},removeActiveRow:function(record){if(this.fireEvent("afterRemoveRow",record)){const selection=this.getSelectionModel().getSelected();this.getStore().remove(selection)}},refresh:function(){this.getStore().reload()},onClickHandler:function(e){const target=e.getTarget();if(!target.classList.contains("x-grid-action"))return;if(!target.dataset.action)return;let actionHandler=`action${target.dataset.action.charAt(0).toUpperCase()}${target.dataset.action.slice(1)}`;if(!(this[actionHandler]&&"function"==typeof this[actionHandler]||(actionHandler=target.dataset.action,this[actionHandler]&&"function"==typeof this[actionHandler])))return;const record=this.getSelectionModel().getSelected(),recordIndex=this.store.indexOf(record);this.menu.record=record.data,this[actionHandler](record,recordIndex,e)},onChangePerPage:function(field,newValue){if(Ext.isEmpty(newValue))return!1;newValue=parseInt(newValue,10),this.getBottomToolbar().pageSize=newValue,this.store.load({params:{start:0,limit:newValue}})}}),MODx.grid.Grid=function(config={}){Ext.applyIf(config,{cm:this.cm,autoHeight:!0,preventRender:!0,preventSaveRefresh:!0,showPerPage:!0,stateful:!1,groupingConfig:{enableGroupingMenu:!0}}),MODx.grid.Grid.superclass.constructor.call(this,config),this.addEvents("afterAutoSave"),this.autosave&&this.on("afterAutoSave",this.onAfterAutoSave,this),config.preventRender||this.render(),this.on({render:{fn:function(){const topToolbar=this.getTopToolbar();topToolbar&&topToolbar.initialConfig.cls&&"has-nested-filters"===topToolbar.initialConfig.cls&&(this.hasNestedFilters=!0)},scope:this}}),config.autosave&&this.on("afteredit",this.saveRecord,this),config.paging&&config.grouping&&this.getBottomToolbar().bind(this.store),config.paging||Object.hasOwn(config,"pageSize")||(config.pageSize=0),this.getStore().load({params:{start:config.pageStart||0,limit:Object.hasOwn(config,"pageSize")?config.pageSize:parseInt(MODx.config.default_per_page,10)||20}}),this.getStore().on("exception",this.onStoreException,this),this.config=config},Ext.extend(MODx.grid.Grid,MODx.grid.GridBase,{permissionsProviderProp:"json",_loadStore:function(){this.config.grouping?this.store=new Ext.data.GroupingStore({url:this.config.url,baseParams:this.config.baseParams||{action:this.config.action||"getList"},reader:new Ext.data.JsonReader({totalProperty:"total",root:"results",fields:this.config.fields}),sortInfo:{field:this.config.sortBy||"id",direction:this.config.sortDir||"ASC"},remoteSort:this.config.remoteSort||!1,remoteGroup:this.config.remoteGroup||!1,groupField:this.config.groupBy||"name",groupDir:this.config.groupDir||"ASC",storeId:this.config.storeId||Ext.id(),autoDestroy:!0,listeners:{beforeload:function(store,options){store.groupField===store.sortInfo.field&&store.groupDir!==store.sortInfo.direction&&(store.groupDir=store.sortInfo.direction,store.baseParams.groupDir=store.sortInfo.direction)},load:function(store,records,options){const cmp=Ext.getCmp("modx-content");cmp&&cmp.doLayout()},groupchange:{fn:function(store,groupField){store.groupDir=this.config.groupDir||"ASC",store.baseParams.groupDir=store.groupDir,store.sortInfo.direction=this.config.sortDir||"ASC",store.load()},scope:this}}}):this.store=new Ext.data.JsonStore({url:this.config.url,baseParams:this.config.baseParams||{action:this.config.action||"getList"},fields:this.config.fields,root:"results",totalProperty:"total",remoteSort:this.config.remoteSort||!1,storeId:this.config.storeId||Ext.id(),autoDestroy:!0,listeners:{load:function(){const cmp=Ext.getCmp("modx-content");cmp&&cmp.doLayout()}}})},onStoreException:function(dataProxy,type,action,options,response){const responseStatusCode=response.status||"Unknown",responseStatusText=Ext.isEmpty(response.statusText)?"":`(${response.statusText})`;let output="",msg="";if(Ext.isEmpty(response.responseText))output=200!==responseStatusCode?`
    ${responseStatusCode} ${responseStatusText}
    `:"";else try{const responseText=Ext.decode(response.responseText);responseText&&responseText.message&&(output=responseText.message)}catch(e){output=response.responseText}output?MODx.config.debug>0?(output=MODx.util.safeHtml(output,"
    ","class,colspan,rowspan"),msg=_("error_grid_get_content_toscreen",{message:`
    ${output}
    `})):(msg=_("error_grid_get_content_tolog"),output=Ext.util.Format.stripTags(output).replaceAll(">",">").replaceAll("<","<"),console.error(output)):msg=_("error_grid_get_content_no_msg"),this.getView().emptyText=`
    ${msg}
    `,this.getView().refresh(!1)},saveRecord:function(e){e.record.data.menu=null;const p=this.config.saveParams||{};Ext.apply(e.record.data,p);const data=Ext.util.JSON.encode(e.record.data),url=this.config.saveUrl||this.config.url||this.config.connector;MODx.Ajax.request({url,params:{action:this.config.save_action||"updateFromGrid",data},listeners:{success:{fn:function(response){if(this.config.save_callback&&Ext.callback(this.config.save_callback,this.config.scope||this,[response]),e.record.commit(),!this.config.preventSaveRefresh){new Ext.util.DelayedTask((()=>this.refresh())).delay(200)}const eventData={field:e.field,originalValue:e.originalValue,value:e.value},responseData={...response,eventData};this.fireEvent("afterAutoSave",responseData)},scope:this},failure:{fn:function(response){e.record.reject(),this.fireEvent("afterAutoSave",response)},scope:this}}})},onAfterAutoSave:function(response){if(!response.success&&""===response.message){let msg="";response.data.length&&Ext.each(response.data,(function(data,index,list){msg+=(""!==msg?"
    ":"")+data.msg}),this),Ext.isEmpty(msg)&&(msg=this.autosaveErrorMsg||_("error")),MODx.msg.alert(_("error"),msg)}},encodeModified:function(){const p=this.getStore().getModifiedRecords(),rs={};for(let i=0;i0){const s=this.getStore(),p={a:MODx.request.a};MODx.request.id&&(p.id=MODx.request.id),MODx.request.key&&(p.key=MODx.request.key);for(let i=0;i0&&window.history.replaceState(this.getStore().baseParams,document.title,this.makeUrl())},getCreatorColumnConfig:function(objectType){return{header:_("grid_column_creator_header"),dataIndex:"creator",id:`modx-${objectType}--creator`,width:70,align:"center",tooltip:_("grid_column_creator_description"),menuDisabled:!0}},getCategoryFilterValue:()=>void 0===MODx.request.tab||void 0===MODx.request.category?null:Math.abs(parseInt(MODx.request.category,10))}),MODx.grid.LocalGrid=function(config={}){Ext.applyIf(config,{title:"",enableColumnMove:!0,groupingConfig:{hideGroupedColumn:config.hideGroupedColumn}}),MODx.grid.LocalGrid.superclass.constructor.call(this,config)},Ext.extend(MODx.grid.LocalGrid,MODx.grid.GridBase,{_loadStore:function(){return this.config.grouping?this.store=new Ext.data.GroupingStore({data:this.config.data||[],reader:new Ext.data.ArrayReader({},this.config.fields||[]),sortInfo:this.config.sortInfo||{field:this.config.sortBy||"name",direction:this.config.sortDir||"ASC"},groupField:this.config.groupBy||"name"}):this.store=new Ext.data.SimpleStore({fields:this.config.fields,data:this.config.data||[]}),this.store},remove:function(config){if(this.destroying)return MODx.grid.LocalGrid.superclass.remove.apply(this,arguments);const r=this.getSelectionModel().getSelected();this.fireEvent("beforeRemoveRow",r)&&Ext.Msg.confirm(config.title||"",config.text||"",(function(e){"yes"===e&&(this.getStore().remove(r),this.fireEvent("afterRemoveRow",r))}),this)},encode:function(){const s=this.getStore(),ct=s.getCount(),rs=this.config.encodeByPk?{}:[];let r;for(let j=0;j 
    '},beforeExpand:function(record,body,rowIndex){return!1!==this.fireEvent("beforeexpand",this,record,body,rowIndex)&&(this.tpl&&this.lazyRender&&(body.innerHTML=this.getBodyContent(record,rowIndex)),!0)},toggleRow:function(row){"number"==typeof row&&(row=this.grid.view.getRow(row)),this[Ext.fly(row).hasClass("x-grid3-row-collapsed")?"expandRow":"collapseRow"](row)},expandRow:function(row){"number"==typeof row&&(row=this.grid.view.getRow(row));var record=this.grid.store.getAt(row.rowIndex),body=Ext.DomQuery.selectNode("tr:nth(2) div.x-grid3-row-body",row);this.beforeExpand(record,body,row.rowIndex)&&(this.state[record.id]=!0,Ext.fly(row).replaceClass("x-grid3-row-collapsed","x-grid3-row-expanded"),this.fireEvent("expand",this,record,body,row.rowIndex))},collapseRow:function(row){"number"==typeof row&&(row=this.grid.view.getRow(row));var record=this.grid.store.getAt(row.rowIndex),body=Ext.fly(row).child("tr:nth(1) div.x-grid3-row-body",!0);!1!==this.fireEvent("beforecollapse",this,record,body,row.rowIndex)&&(this.state[record.id]=!1,Ext.fly(row).replaceClass("x-grid3-row-expanded","x-grid3-row-collapsed"),this.fireEvent("collapse",this,record,body,row.rowIndex))}}),Ext.preg("rowexpander",Ext.ux.grid.RowExpander),Ext.grid.RowExpander=Ext.ux.grid.RowExpander,Ext.ns("Ext.ux.grid"),Ext.ux.grid.CheckColumn=function(a){Ext.apply(this,a),this.id||(this.id=Ext.id()),this.renderer=this.renderer.createDelegate(this)},Ext.ux.grid.CheckColumn.prototype={init:function(b){this.grid=b,this.grid.on("render",(function(){this.grid.getView().mainBody.on("mousedown",this.onMouseDown,this)}),this),this.grid.on("destroy",this.onDestroy,this)},onMouseDown:function(e,t){if(this.grid.fireEvent("rowclick"),t.className&&-1!=t.className.indexOf("x-grid3-cc-"+this.id)){e.stopEvent();var a=this.grid.getView().findRowIndex(t),b=this.grid.store.getAt(a),sv=b.data[this.dataIndex];b.set(this.dataIndex,!sv),this.grid.fireEvent("afteredit",{grid:this.grid,record:b,field:this.dataIndex,originalValue:sv,value:b.data[this.dataIndex],cancel:!1})}},renderer:function(v,p,a){return p.css+=" x-grid3-check-col-td",'
     
    '},onDestroy:function(){var mainBody=this.grid.getView().mainBody;mainBody&&mainBody.un("mousedown",this.onMouseDown,this)}},Ext.preg("checkcolumn",Ext.ux.grid.CheckColumn),Ext.grid.CheckColumn=Ext.ux.grid.CheckColumn,Ext.grid.PropertyColumnModel=function(a,b){var g=Ext.grid,f=Ext.form;this.grid=a,g.PropertyColumnModel.superclass.constructor.call(this,[{header:this.nameText,width:50,sortable:!0,dataIndex:"name",id:"name",menuDisabled:!0},{header:this.valueText,width:50,resizable:!1,dataIndex:"value",id:"value",menuDisabled:!0}]),this.store=b;var c=new f.Field({autoCreate:{tag:"select",children:[{tag:"option",value:"true",html:"true"},{tag:"option",value:"false",html:"false"}]},getValue:function(){return"true"==this.el.dom.value}});this.editors={date:new g.GridEditor(new f.DateField({selectOnFocus:!0})),string:new g.GridEditor(new f.TextField({selectOnFocus:!0})),number:new g.GridEditor(new f.NumberField({selectOnFocus:!0,style:"text-align:left;"})),boolean:new g.GridEditor(c)},this.renderCellDelegate=this.renderCell.createDelegate(this),this.renderPropDelegate=this.renderProp.createDelegate(this)},Ext.extend(Ext.grid.PropertyColumnModel,Ext.grid.ColumnModel,{nameText:"Name",valueText:"Value",dateFormat:"m/j/Y",renderDate:function(a){return a.dateFormat(this.dateFormat)},renderBool:function(a){return a?"true":"false"},isCellEditable:function(a,b){return 1==a},getRenderer:function(a){return 1==a?this.renderCellDelegate:this.renderPropDelegate},renderProp:function(v){return this.getPropertyName(v)},renderCell:function(a){var b=a;return Ext.isDate(a)?b=this.renderDate(a):"boolean"==typeof a&&(b=this.renderBool(a)),Ext.util.Format.htmlEncode(b)},getPropertyName:function(a){var b=this.grid.propertyNames;return b&&b[a]?b[a]:a},getCellEditor:function(a,b){var p=this.store.getProperty(b),n=p.data.name,val=p.data.value;return this.grid.customEditors[n]?this.grid.customEditors[n]:Ext.isDate(val)?this.editors.date:"number"==typeof val?this.editors.number:"boolean"==typeof val?this.editors.boolean:this.editors.string},destroy:function(){for(var a in Ext.grid.PropertyColumnModel.superclass.destroy.call(this),this.editors)Ext.destroy(a)}}),MODx.grid.JsonGrid=function(config){config=config||{},this.ident=config.ident||"jsongrid-mecitem"+Ext.id(),this.hiddenField=new Ext.form.TextArea({name:config.hiddenName||config.name,hidden:!0}),this.fieldConfig=config.fieldConfig||[{name:"key"},{name:"value"}],this.fieldConfig.push({name:"id",hidden:!0}),this.fieldColumns=[],this.fieldNames=[],Ext.each(this.fieldConfig,(function(el){this.fieldNames.push(el.name),this.fieldColumns.push({header:el.header||_(el.name),dataIndex:el.name,editable:!0,menuDisabled:!0,hidden:el.hidden||!1,editor:{xtype:el.xtype||"textfield",allowBlank:el.allowBlank||!0,enableKeyEvents:!0,fieldname:el.name,listeners:{change:{fn:this.saveValue,scope:this},keyup:{fn:function(sb){var record=this.getSelectionModel().getSelected();record&&(record.set(sb.fieldname,sb.el.dom.value),this.saveValue())},scope:this}}},renderer:function(value,metadata){return metadata.css+="x-editable-column ",value},width:el.width||100})}),this),Ext.applyIf(config,{id:this.ident+"-json-grid",fields:this.fieldNames,autoHeight:!0,store:new Ext.data.JsonStore({fields:this.fieldNames,data:this.loadValue(config.value)}),enableDragDrop:!0,ddGroup:this.ident+"-json-grid-dd",labelStyle:"position: absolute",columns:this.fieldColumns,disableContextMenuAction:!0,tbar:["->",{text:' '+_("add"),cls:"primary-button",handler:this.addElement,scope:this}],listeners:{render:{fn:this.renderListener,scope:this}}}),MODx.grid.JsonGrid.superclass.constructor.call(this,config)},Ext.extend(MODx.grid.JsonGrid,MODx.grid.LocalGrid,{getMenu:function(){var m=[];return m.push({text:_("remove"),handler:this.removeElement}),m},getActions:function(){return[{action:"removeElement",icon:"trash-o",text:_("remove")}]},addElement:function(){var ds=this.getStore(),row={};Ext.each(this.fieldNames,(function(fieldname){row[fieldname]=""})),row.id=this.getStore().getCount(),this.getStore().insert(this.getStore().getCount(),new ds.recordType(row)),this.getView().refresh(),this.getSelectionModel().selectRow(0)},removeElement:function(){Ext.Msg.confirm(_("remove")||"",_("confirm_remove")||"",(function(e){if("yes"===e){var ds=this.getStore(),rows=this.getSelectionModel().getSelections();if(!rows.length)return!1;for(var i=0;i
    ',{compiled:!0})},actionsColumnRenderer:function(value,metaData,record,rowIndex,colIndex,store){return this._getActionsColumnTpl().apply({actions:this.getActions()})},onClick:function(e){var target=e.getTarget();if(target.classList.contains("x-grid-action")&&target.dataset.action){var actionHandler="action"+target.dataset.action.charAt(0).toUpperCase()+target.dataset.action.slice(1);if(this[actionHandler]&&"function"==typeof this[actionHandler]||this[actionHandler=target.dataset.action]&&"function"==typeof this[actionHandler]){var record=this.getSelectionModel().getSelected(),recordIndex=this.store.indexOf(record);this.menu.record=record.data,this[actionHandler](record,recordIndex,e)}}}}),Ext.reg("grid-json",MODx.grid.JsonGrid),Ext.reg("modx-grid-json",MODx.grid.JsonGrid),MODx.Console=function(config){config=config||{},Ext.Updater.defaults.showLoadIndicator=!1,Ext.applyIf(config,{title:_("console"),modal:!Ext.isIE,closeAction:"hide",resizable:!1,collapsible:!1,closable:!0,maximizable:!0,autoScroll:!0,height:400,width:600,refreshRate:2,cls:"modx-window modx-console",items:[{itemId:"header",cls:"modx-console-text",html:_("console_running"),border:!1},{xtype:"panel",itemId:"body",cls:"x-panel-bwrap modx-console-text"}],buttons:[{text:_("console_download_output"),handler:this.download,scope:this},{text:_("ok"),cls:"primary-button",itemId:"okBtn",disabled:!0,scope:this,handler:this.hideConsole}],keys:[{key:Ext.EventObject.S,ctrl:!0,fn:this.download,scope:this},{key:Ext.EventObject.ENTER,fn:this.hideConsole,scope:this}]}),MODx.Console.superclass.constructor.call(this,config),this.config=config,this.addEvents({shutdown:!0,complete:!0}),this.on("show",this.init,this),this.on("hide",(function(){if(this.provider&&this.provider.disconnect)try{this.provider.disconnect()}catch(e){}this.fireEvent("shutdown"),this.destroy()})),this.on("complete",this.onComplete,this)},Ext.extend(MODx.Console,Ext.Window,{mgr:null,running:!1,init:function(){Ext.Msg.hide(),this.fbar.setDisabled(!0),this.keyMap.setDisabled(!0),this.getComponent("body").el.dom.innerHTML="",this.provider=new Ext.direct.PollingProvider({type:"polling",url:MODx.config.connector_url,interval:1e3,baseParams:{action:"System/Console",register:this.config.register||"",topic:this.config.topic||"",clear:!1,show_filename:this.config.show_filename||0,format:this.config.format||"html_log"}}),Ext.Direct.addProvider(this.provider),Ext.Direct.on("message",this.onMessage,this)},onMessage:function(e,p){var out=this.getComponent("body");out&&(out.el.insertHtml("beforeEnd",e.data),e.data="",out.el.scroll("b",out.el.getHeight(),!0)),e.complete&&this.fireEvent("complete"),delete e},onComplete:function(){if(this.provider&&this.provider.disconnect)try{this.provider.disconnect()}catch(e){}this.fbar.setDisabled(!1),this.keyMap.setDisabled(!1)},download:function(){var c=this.getComponent("body").getEl().dom.innerHTML||" ";MODx.Ajax.request({url:MODx.config.connector_url,params:{action:"System/DownloadOutput",data:c},listeners:{success:{fn:function(r){location.href=MODx.config.connector_url+"?action=System/DownloadOutput&HTTP_MODAUTH="+MODx.siteId+"&download="+r.message},scope:this}}})},setRegister:function(register,topic){this.config.register=register,this.config.topic=topic},hideConsole:function(){this.hide()}}),Ext.reg("modx-console",MODx.Console),Ext.namespace("MODx.portal"),Ext.ux.Portal=Ext.extend(Ext.Panel,{layout:"column",cls:"x-portal",defaultType:"portalcolumn",initComponent:function(){Ext.ux.Portal.superclass.initComponent.call(this),this.addEvents({validatedrop:!0,beforedragover:!0,dragover:!0,beforedrop:!0,drop:!0})},initEvents:function(){Ext.ux.Portal.superclass.initEvents.call(this),this.dd=new Ext.ux.Portal.DropZone(this,this.dropConfig)},beforeDestroy:function(){this.dd&&this.dd.unreg(),Ext.ux.Portal.superclass.beforeDestroy.call(this)}}),Ext.reg("portal",Ext.ux.Portal),Ext.ux.Portal.DropZone=function(a,b){this.portal=a,Ext.dd.ScrollManager.register(a.body),Ext.ux.Portal.DropZone.superclass.constructor.call(this,a.bwrap.dom,b),a.body.ddScrollConfig=this.ddScrollConfig},Ext.extend(Ext.ux.Portal.DropZone,Ext.dd.DropTarget,{ddScrollConfig:{vthresh:50,hthresh:-1,animate:!0,increment:200},createEvent:function(a,e,b,d,c,f){return{portal:this.portal,panel:b.panel,columnIndex:d,column:c,position:f,data:b,source:a,rawEvent:e,status:this.dropAllowed}},notifyOver:function(a,e,b){var d=e.getXY(),portal=this.portal,px=a.proxy;this.grid||(this.grid=this.getGrid());var f=portal.body.dom.clientWidth;this.lastCW?this.lastCW!=f&&(this.lastCW=f,portal.doLayout(),this.grid=this.getGrid()):this.lastCW=f;for(var g=0,xs=this.grid.columnX,cmatch=!1,i=xs.length;gd[1]){match=!0;break}}pos=(match&&p?pos:c.items.getCount())+(overSelf?-1:0);var j=this.createEvent(a,e,b,g,c,pos);return!1!==portal.fireEvent("validatedrop",j)&&!1!==portal.fireEvent("beforedragover",j)?(px.getProxy().setWidth("auto"),p?px.moveProxy(p.el.dom.parentNode,match?p.el.dom:null):px.moveProxy(c.el.dom,null),this.lastPos={c,col:g,p:!!(overSelf||match&&p)&&pos},this.scrollPos=portal.body.getScroll(),portal.fireEvent("dragover",j),j.status):j.status},notifyOut:function(){delete this.grid},notifyDrop:function(a,e,b){if(delete this.grid,this.lastPos){var c=this.lastPos.c,col=this.lastPos.col,pos=this.lastPos.p,f=this.createEvent(a,e,b,col,c,!1!==pos?pos:c.items.getCount());if(!1!==this.portal.fireEvent("validatedrop",f)&&!1!==this.portal.fireEvent("beforedrop",f)){a.proxy.getProxy().remove(),a.panel.el.dom.parentNode.removeChild(a.panel.el.dom),!1!==pos?(c==a.panel.ownerCt&&c.items.items.indexOf(a.panel)<=pos&&pos++,c.insert(pos,a.panel)):c.add(a.panel),c.doLayout(),this.portal.fireEvent("drop",f);var g=this.scrollPos.top;if(g){var d=this.portal.body.dom;setTimeout((function(){d.scrollTop=g}),10)}}delete this.lastPos}},getGrid:function(){var a=this.portal.bwrap.getBox();return a.columnX=[],this.portal.items.each((function(c){a.columnX.push({x:c.el.getX(),w:c.el.getWidth()})})),a},unreg:function(){Ext.ux.Portal.DropZone.superclass.unreg.call(this)}}),MODx.portal.Column=Ext.extend(Ext.Container,{layout:"anchor",defaultType:"portlet",cls:"x-portal-column",style:"padding:10px;",columnWidth:1,defaults:{collapsible:!0,autoHeight:!0,titleCollapse:!0,draggable:!0,style:"padding: 5px 0;",bodyStyle:"padding: 15px;"}}),Ext.reg("portalcolumn",MODx.portal.Column),MODx.portal.Portlet=Ext.extend(Ext.Panel,{anchor:Ext.isSafari?"98%":"100%",frame:!0,collapsible:!0,draggable:!0,cls:"x-portlet",stateful:!1,layout:"form"}),Ext.reg("portlet",MODx.portal.Portlet),MODx.window.DuplicateResource=function(config){config=config||{},this.ident=config.ident||"dupres"+Ext.id(),Ext.applyIf(config,{title:config.pagetitle?_("duplicate")+" "+config.pagetitle:_("duplication_options"),id:this.ident}),MODx.window.DuplicateResource.superclass.constructor.call(this,config)},Ext.extend(MODx.window.DuplicateResource,MODx.Window,{_loadForm:function(){if(this.checkIfLoaded(this.config.record))return this.fp.getForm().baseParams={action:"Resource/Updateduplicate",prefixDuplicate:!0,id:this.config.resource},!1;var items=[];items.push({xtype:"textfield",id:"modx-"+this.ident+"-name",fieldLabel:_("resource_name_new"),name:"name",anchor:"100%",value:""}),this.config.hasChildren&&items.push({xtype:"xcheckbox",boxLabel:_("duplicate_children")+" ("+this.config.childCount+")",hideLabel:!0,name:"duplicate_children",id:"modx-"+this.ident+"-duplicate-children",checked:!0}),items.push({xtype:"xcheckbox",boxLabel:_("duplicate_redirect"),hideLabel:!0,name:"redirect",id:"modx-"+this.ident+"-duplicate-redirect",checked:this.config.redirect});var pov=MODx.config.default_duplicate_publish_option||"preserve";items.push({xtype:"fieldset",title:_("publishing_options"),items:[{xtype:"radiogroup",hideLabel:!0,columns:1,value:pov,items:[{boxLabel:_("po_make_all_unpub"),hideLabel:!0,name:"published_mode",inputValue:"unpublish"},{boxLabel:_("po_make_all_pub"),hideLabel:!0,name:"published_mode",inputValue:"publish"},{boxLabel:_("po_preserve"),hideLabel:!0,name:"published_mode",inputValue:"preserve"}]}]}),this.fp=this.createForm({url:this.config.url||MODx.config.connector_url,baseParams:this.config.baseParams||{action:"Resource/Duplicate",id:this.config.resource,prefixDuplicate:!0},labelWidth:125,defaultType:"textfield",autoHeight:!0,items}),this.renderForm()}}),Ext.reg("modx-window-resource-duplicate",MODx.window.DuplicateResource),MODx.window.DuplicateElement=function(config){config=config||{},this.ident=config.ident||"dupeel-"+Ext.id();var flds=[{xtype:"hidden",name:"id",id:"modx-"+this.ident+"-id"},{xtype:"hidden",name:"source",id:"modx-"+this.ident+"-source"},{xtype:"textfield",fieldLabel:_("element_name_new"),name:"template"==config.record.type?"templatename":"name",id:"modx-"+this.ident+"-name",anchor:"100%",enableKeyEvents:!0,listeners:{afterRender:{scope:this,fn:function(f,e){this.setStaticElementsPath(f)}},keyup:{scope:this,fn:function(f,e){this.setStaticElementsPath(f)}}}}];"tv"==config.record.type&&(flds.push({xtype:"textfield",fieldLabel:_("element_caption_new"),name:"caption",id:"modx-"+this.ident+"-caption",anchor:"100%"}),flds.push({xtype:"xcheckbox",hideLabel:!0,boxLabel:_("element_duplicate_values"),labelSeparator:"",name:"duplicateValues",id:"modx-"+this.ident+"-duplicate-values",anchor:"100%",inputValue:1,checked:!1})),!0===config.record.static&&flds.push({xtype:"textfield",fieldLabel:_("static_file"),name:"static_file",id:"modx-"+this.ident+"-static_file",anchor:"100%"}),flds.push({xtype:"xcheckbox",boxLabel:_("duplicate_redirect"),hideLabel:!0,name:"redirect",id:"modx-"+this.ident+"-duplicate-redirect",checked:config.redirect}),Ext.applyIf(config,{title:_("duplicate_"+config.record.type),url:MODx.config.connector_url,action:"element/"+config.record.type+"/duplicate",width:600,fields:flds,labelWidth:150}),MODx.window.DuplicateElement.superclass.constructor.call(this,config)},Ext.extend(MODx.window.DuplicateElement,MODx.Window,{setStaticElementsPath:function(f){if(!0===this.config.record.static){var category=this.config.record.category;if("number"!=typeof category){Ext.getCmp("modx-"+this.config.record.type+"-category").getValue()>0&&(category=Ext.getCmp("modx-"+this.config.record.type+"-category").lastSelectionText);var path=MODx.getStaticElementsPath(f.getValue(),category,this.config.record.type+"s");Ext.getCmp("modx-"+this.ident+"-static_file").setValue(path)}else"number"==typeof category&&category>0&&MODx.Ajax.request({url:MODx.config.connector_url,params:{action:"Element/Category/GetList",id:category},listeners:{success:{fn:function(response){for(var i=0;i"+_("session_logging_out")+"

    ",xtype:"modx-description"},{xtype:"textfield",id:"modx-"+this.ident+"-username",fieldLabel:_("username"),name:"username",anchor:"100%"},{xtype:"textfield",inputType:"password",id:"modx-"+this.ident+"-password",fieldLabel:_("password"),name:"password",anchor:"100%"},{xtype:"hidden",name:"rememberme",value:1}],buttons:[{text:_("logout"),scope:this,handler:function(){location.href="?logout=1"}},{text:_("login"),cls:"primary-button",scope:this,handler:this.submit}]}),MODx.window.Login.superclass.constructor.call(this,config),this.on("success",this.onLogin,this)},Ext.extend(MODx.window.Login,MODx.Window,{onLogin:function(o){var r=o.a.result;r.object&&r.object.token&&(Ext.Ajax.defaultHeaders={modAuth:r.object.token},Ext.Ajax.extraParams={HTTP_MODAUTH:r.object.token},MODx.siteId=r.object.token,MODx.msg.status({message:_("session_extended")}))}}),Ext.reg("modx-window-login",MODx.window.Login), +Ext.ns("Ext.ux.grid"),Ext.ux.grid.RowExpander=Ext.extend(Ext.util.Observable,{expandOnEnter:!0,expandOnDblClick:!0,header:"",width:25,sortable:!1,fixed:!0,hideable:!1,menuDisabled:!0,dataIndex:"",id:"expander",lazyRender:!0,enableCaching:!0,constructor:function(config){Ext.apply(this,config),this.addEvents({beforeexpand:!0,expand:!0,beforecollapse:!0,collapse:!0}),Ext.ux.grid.RowExpander.superclass.constructor.call(this),this.tpl&&("string"==typeof this.tpl&&(this.tpl=new Ext.Template(this.tpl)),this.tpl.compile()),this.state={},this.bodyContent={}},getRowClass:function(record,rowIndex,p,ds){p.cols-=1;let content=this.bodyContent[record.id];return content||this.lazyRender||(content=this.getBodyContent(record,rowIndex)),content&&(p.body=content),this.state[record.id]?"x-grid3-row-expanded":"x-grid3-row-collapsed"},init:function(grid){this.grid=grid;const view=grid.getView();view.getRowClass=this.getRowClass.createDelegate(this),view.enableRowBody=!0,grid.on("render",this.onRender,this),grid.on("destroy",this.onDestroy,this)},onRender:function(){const{grid}=this,{mainBody}=grid.getView();mainBody.on("mousedown",this.onMouseDown,this,{delegate:".x-grid3-row-expander"}),this.expandOnEnter&&(this.keyNav=new Ext.KeyNav(this.grid.getGridEl(),{enter:this.onEnter,scope:this})),this.expandOnDblClick&&grid.on("rowdblclick",this.onRowDblClick,this)},onDestroy:function(){this.keyNav&&(this.keyNav.disable(),delete this.keyNav);const{mainBody}=this.grid.getView();mainBody&&mainBody.un("mousedown",this.onMouseDown,this)},onRowDblClick:function(grid,rowIdx,e){this.toggleRow(rowIdx)},onEnter:function(e){const g=this.grid,sels=g.getSelectionModel().getSelections();for(let i=0,len=sels.length;i '},beforeExpand:function(record,body,rowIndex){return!1!==this.fireEvent("beforeexpand",this,record,body,rowIndex)&&(this.tpl&&this.lazyRender&&(body.innerHTML=this.getBodyContent(record,rowIndex)),!0)},toggleRow:function(row){"number"==typeof row&&(row=this.grid.view.getRow(row)),this[Ext.fly(row).hasClass("x-grid3-row-collapsed")?"expandRow":"collapseRow"](row)},expandRow:function(row){"number"==typeof row&&(row=this.grid.view.getRow(row));const record=this.grid.store.getAt(row.rowIndex),body=Ext.DomQuery.selectNode("tr:nth(2) div.x-grid3-row-body",row);this.beforeExpand(record,body,row.rowIndex)&&(this.state[record.id]=!0,Ext.fly(row).replaceClass("x-grid3-row-collapsed","x-grid3-row-expanded"),this.fireEvent("expand",this,record,body,row.rowIndex))},collapseRow:function(row){"number"==typeof row&&(row=this.grid.view.getRow(row));const record=this.grid.store.getAt(row.rowIndex),body=Ext.fly(row).child("tr:nth(1) div.x-grid3-row-body",!0);!1!==this.fireEvent("beforecollapse",this,record,body,row.rowIndex)&&(this.state[record.id]=!1,Ext.fly(row).replaceClass("x-grid3-row-expanded","x-grid3-row-collapsed"),this.fireEvent("collapse",this,record,body,row.rowIndex))}}),Ext.preg("rowexpander",Ext.ux.grid.RowExpander),Ext.grid.RowExpander=Ext.ux.grid.RowExpander,Ext.ns("Ext.ux.grid"),Ext.ux.grid.CheckColumn=function(a){Ext.apply(this,a),this.id||(this.id=Ext.id()),this.renderer=this.renderer.createDelegate(this)},Ext.ux.grid.CheckColumn.prototype={init:function(b){this.grid=b,this.grid.on("render",(function(){this.grid.getView().mainBody.on("mousedown",this.onMouseDown,this)}),this),this.grid.on("destroy",this.onDestroy,this)},onMouseDown:function(e,t){if(this.grid.fireEvent("rowclick"),t.className&&-1!==t.className.indexOf(`x-grid3-cc-${this.id}`)){e.stopEvent();const a=this.grid.getView().findRowIndex(t),b=this.grid.store.getAt(a),sv=b.data[this.dataIndex];b.set(this.dataIndex,!sv),this.grid.fireEvent("afteredit",{grid:this.grid,record:b,field:this.dataIndex,originalValue:sv,value:b.data[this.dataIndex],cancel:!1})}},renderer:function(v,p,a){return p.css+=" x-grid3-check-col-td",`
     
    `},onDestroy:function(){const{mainBody}=this.grid.getView();mainBody&&mainBody.un("mousedown",this.onMouseDown,this)}},Ext.preg("checkcolumn",Ext.ux.grid.CheckColumn),Ext.grid.CheckColumn=Ext.ux.grid.CheckColumn,Ext.grid.PropertyColumnModel=function(a,b){const g=Ext.grid,f=Ext.form;this.grid=a,g.PropertyColumnModel.superclass.constructor.call(this,[{header:this.nameText,width:50,sortable:!0,dataIndex:"name",id:"name",menuDisabled:!0},{header:this.valueText,width:50,resizable:!1,dataIndex:"value",id:"value",menuDisabled:!0}]),this.store=b;const c=new f.Field({autoCreate:{tag:"select",children:[{tag:"option",value:"true",html:"true"},{tag:"option",value:"false",html:"false"}]},getValue:function(){return"true"==this.el.dom.value}});this.editors={date:new g.GridEditor(new f.DateField({selectOnFocus:!0})),string:new g.GridEditor(new f.TextField({selectOnFocus:!0})),number:new g.GridEditor(new f.NumberField({selectOnFocus:!0,style:"text-align:left;"})),boolean:new g.GridEditor(c)},this.renderCellDelegate=this.renderCell.createDelegate(this),this.renderPropDelegate=this.renderProp.createDelegate(this)},Ext.extend(Ext.grid.PropertyColumnModel,Ext.grid.ColumnModel,{nameText:"Name",valueText:"Value",dateFormat:"m/j/Y",renderDate:function(a){return a.dateFormat(this.dateFormat)},renderBool:function(a){return a?"true":"false"},isCellEditable:function(a,b){return 1==a},getRenderer:function(a){return 1==a?this.renderCellDelegate:this.renderPropDelegate},renderProp:function(v){return this.getPropertyName(v)},renderCell:function(a){let b=a;return Ext.isDate(a)?b=this.renderDate(a):"boolean"==typeof a&&(b=this.renderBool(a)),Ext.util.Format.htmlEncode(b)},getPropertyName:function(a){const b=this.grid.propertyNames;return b&&b[a]?b[a]:a},getCellEditor:function(a,b){const p=this.store.getProperty(b),n=p.data.name,val=p.data.value;return this.grid.customEditors[n]?this.grid.customEditors[n]:Ext.isDate(val)?this.editors.date:"number"==typeof val?this.editors.number:"boolean"==typeof val?this.editors.boolean:this.editors.string},destroy:function(){Ext.grid.PropertyColumnModel.superclass.destroy.call(this);for(const a in this.editors)Ext.destroy(a)}}),MODx.grid.JsonGrid=function(config={}){this.ident=config.ident||`jsongrid-mecitem${Ext.id()}`,this.hiddenField=new Ext.form.TextArea({name:config.hiddenName||config.name,hidden:!0}),this.fieldConfig=config.fieldConfig||[{name:"key"},{name:"value"}],this.fieldConfig.push({name:"id",hidden:!0}),this.fieldColumns=[],this.fieldNames=[],Ext.each(this.fieldConfig,(function(el){this.fieldNames.push(el.name),this.fieldColumns.push({header:el.header||_(el.name),dataIndex:el.name,editable:!0,menuDisabled:!0,hidden:el.hidden||!1,editor:{xtype:el.xtype||"textfield",allowBlank:el.allowBlank||!0,enableKeyEvents:!0,fieldname:el.name,listeners:{change:{fn:this.saveValue,scope:this},keyup:{fn:function(sb){const record=this.getSelectionModel().getSelected();record&&(record.set(sb.fieldname,sb.el.dom.value),this.saveValue())},scope:this}}},renderer:function(value,metadata){return metadata.css+="x-editable-column ",value},width:el.width||100})}),this),Ext.applyIf(config,{id:`${this.ident}-json-grid`,fields:this.fieldNames,autoHeight:!0,store:new Ext.data.JsonStore({fields:this.fieldNames,data:this.loadValue(config.value)}),enableDragDrop:!0,ddGroup:`${this.ident}-json-grid-dd`,labelStyle:"position: absolute",columns:this.fieldColumns,disableContextMenuAction:!0,tbar:["->",{text:` ${_("add")}`,cls:"primary-button",handler:this.addElement,scope:this}],listeners:{render:{fn:this.renderListener,scope:this}}}),MODx.grid.JsonGrid.superclass.constructor.call(this,config)},Ext.extend(MODx.grid.JsonGrid,MODx.grid.LocalGrid,{getMenu:function(){const menu=[];return menu.push({text:_("remove"),handler:this.removeElement}),menu},getActions:function(){return[{action:"removeElement",icon:"trash-o",text:_("remove")}]},addElement:function(){const ds=this.getStore(),row={};Ext.each(this.fieldNames,(function(fieldname){row[fieldname]=""})),row.id=this.getStore().getCount(),this.getStore().insert(this.getStore().getCount(),new ds.recordType(row)),this.getView().refresh(),this.getSelectionModel().selectRow(0)},removeElement:function(){Ext.Msg.confirm(_("remove")||"",_("confirm_remove")||"",(function(e){if("yes"===e){const ds=this.getStore(),rows=this.getSelectionModel().getSelections();if(!rows.length)return!1;for(let i=0;id[1]){match=!0;break}}pos=(match&&p?pos:c.items.getCount())+(overSelf?-1:0);var j=this.createEvent(a,e,b,g,c,pos);return!1!==portal.fireEvent("validatedrop",j)&&!1!==portal.fireEvent("beforedragover",j)?(px.getProxy().setWidth("auto"),p?px.moveProxy(p.el.dom.parentNode,match?p.el.dom:null):px.moveProxy(c.el.dom,null),this.lastPos={c,col:g,p:!!(overSelf||match&&p)&&pos},this.scrollPos=portal.body.getScroll(),portal.fireEvent("dragover",j),j.status):j.status},notifyOut:function(){delete this.grid},notifyDrop:function(a,e,b){if(delete this.grid,this.lastPos){var c=this.lastPos.c,col=this.lastPos.col,pos=this.lastPos.p,f=this.createEvent(a,e,b,col,c,!1!==pos?pos:c.items.getCount());if(!1!==this.portal.fireEvent("validatedrop",f)&&!1!==this.portal.fireEvent("beforedrop",f)){a.proxy.getProxy().remove(),a.panel.el.dom.parentNode.removeChild(a.panel.el.dom),!1!==pos?(c==a.panel.ownerCt&&c.items.items.indexOf(a.panel)<=pos&&pos++,c.insert(pos,a.panel)):c.add(a.panel),c.doLayout(),this.portal.fireEvent("drop",f);var g=this.scrollPos.top;if(g){var d=this.portal.body.dom;setTimeout((function(){d.scrollTop=g}),10)}}delete this.lastPos}},getGrid:function(){var a=this.portal.bwrap.getBox();return a.columnX=[],this.portal.items.each((function(c){a.columnX.push({x:c.el.getX(),w:c.el.getWidth()})})),a},unreg:function(){Ext.ux.Portal.DropZone.superclass.unreg.call(this)}}),MODx.portal.Column=Ext.extend(Ext.Container,{layout:"anchor",defaultType:"portlet",cls:"x-portal-column",style:"padding:10px;",columnWidth:1,defaults:{collapsible:!0,autoHeight:!0,titleCollapse:!0,draggable:!0,style:"padding: 5px 0;",bodyStyle:"padding: 15px;"}}),Ext.reg("portalcolumn",MODx.portal.Column),MODx.portal.Portlet=Ext.extend(Ext.Panel,{anchor:Ext.isSafari?"98%":"100%",frame:!0,collapsible:!0,draggable:!0,cls:"x-portlet",stateful:!1,layout:"form"}),Ext.reg("portlet",MODx.portal.Portlet),MODx.window.DuplicateResource=function(config){config=config||{},this.ident=config.ident||"dupres"+Ext.id(),Ext.applyIf(config,{title:config.pagetitle?_("duplicate")+" "+config.pagetitle:_("duplication_options"),id:this.ident}),MODx.window.DuplicateResource.superclass.constructor.call(this,config)},Ext.extend(MODx.window.DuplicateResource,MODx.Window,{_loadForm:function(){if(this.checkIfLoaded(this.config.record))return this.fp.getForm().baseParams={action:"Resource/Updateduplicate",prefixDuplicate:!0,id:this.config.resource},!1;var items=[];items.push({xtype:"textfield",id:"modx-"+this.ident+"-name",fieldLabel:_("resource_name_new"),name:"name",anchor:"100%",value:""}),this.config.hasChildren&&items.push({xtype:"xcheckbox",boxLabel:_("duplicate_children")+" ("+this.config.childCount+")",hideLabel:!0,name:"duplicate_children",id:"modx-"+this.ident+"-duplicate-children",checked:!0}),items.push({xtype:"xcheckbox",boxLabel:_("duplicate_redirect"),hideLabel:!0,name:"redirect",id:"modx-"+this.ident+"-duplicate-redirect",checked:this.config.redirect});var pov=MODx.config.default_duplicate_publish_option||"preserve";items.push({xtype:"fieldset",title:_("publishing_options"),items:[{xtype:"radiogroup",hideLabel:!0,columns:1,value:pov,items:[{boxLabel:_("po_make_all_unpub"),hideLabel:!0,name:"published_mode",inputValue:"unpublish"},{boxLabel:_("po_make_all_pub"),hideLabel:!0,name:"published_mode",inputValue:"publish"},{boxLabel:_("po_preserve"),hideLabel:!0,name:"published_mode",inputValue:"preserve"}]}]}),this.fp=this.createForm({url:this.config.url||MODx.config.connector_url,baseParams:this.config.baseParams||{action:"Resource/Duplicate",id:this.config.resource,prefixDuplicate:!0},labelWidth:125,defaultType:"textfield",autoHeight:!0,items}),this.renderForm()}}),Ext.reg("modx-window-resource-duplicate",MODx.window.DuplicateResource),MODx.window.DuplicateElement=function(config){config=config||{},this.ident=config.ident||"dupeel-"+Ext.id();var flds=[{xtype:"hidden",name:"id",id:"modx-"+this.ident+"-id"},{xtype:"hidden",name:"source",id:"modx-"+this.ident+"-source"},{xtype:"textfield",fieldLabel:_("element_name_new"),name:"template"==config.record.type?"templatename":"name",id:"modx-"+this.ident+"-name",anchor:"100%",enableKeyEvents:!0,listeners:{afterRender:{scope:this,fn:function(f,e){this.setStaticElementsPath(f)}},keyup:{scope:this,fn:function(f,e){this.setStaticElementsPath(f)}}}}];"tv"==config.record.type&&(flds.push({xtype:"textfield",fieldLabel:_("element_caption_new"),name:"caption",id:"modx-"+this.ident+"-caption",anchor:"100%"}),flds.push({xtype:"xcheckbox",hideLabel:!0,boxLabel:_("element_duplicate_values"),labelSeparator:"",name:"duplicateValues",id:"modx-"+this.ident+"-duplicate-values",anchor:"100%",inputValue:1,checked:!1})),!0===config.record.static&&flds.push({xtype:"textfield",fieldLabel:_("static_file"),name:"static_file",id:"modx-"+this.ident+"-static_file",anchor:"100%"}),flds.push({xtype:"xcheckbox",boxLabel:_("duplicate_redirect"),hideLabel:!0,name:"redirect",id:"modx-"+this.ident+"-duplicate-redirect",checked:config.redirect}),Ext.applyIf(config,{title:_("duplicate_"+config.record.type),url:MODx.config.connector_url,action:"element/"+config.record.type+"/duplicate",width:600,fields:flds,labelWidth:150}),MODx.window.DuplicateElement.superclass.constructor.call(this,config)},Ext.extend(MODx.window.DuplicateElement,MODx.Window,{setStaticElementsPath:function(f){if(!0===this.config.record.static){var category=this.config.record.category;if("number"!=typeof category){Ext.getCmp("modx-"+this.config.record.type+"-category").getValue()>0&&(category=Ext.getCmp("modx-"+this.config.record.type+"-category").lastSelectionText);var path=MODx.getStaticElementsPath(f.getValue(),category,this.config.record.type+"s");Ext.getCmp("modx-"+this.ident+"-static_file").setValue(path)}else"number"==typeof category&&category>0&&MODx.Ajax.request({url:MODx.config.connector_url,params:{action:"Element/Category/GetList",id:category},listeners:{success:{fn:function(response){for(var i=0;i"+_("session_logging_out")+"

    ",xtype:"modx-description"},{xtype:"textfield",id:"modx-"+this.ident+"-username",fieldLabel:_("username"),name:"username",anchor:"100%"},{xtype:"textfield",inputType:"password",id:"modx-"+this.ident+"-password",fieldLabel:_("password"),name:"password",anchor:"100%"},{xtype:"hidden",name:"rememberme",value:1}],buttons:[{text:_("logout"),scope:this,handler:function(){location.href="?logout=1"}},{text:_("login"),cls:"primary-button",scope:this,handler:this.submit}]}),MODx.window.Login.superclass.constructor.call(this,config),this.on("success",this.onLogin,this)},Ext.extend(MODx.window.Login,MODx.Window,{onLogin:function(o){var r=o.a.result;r.object&&r.object.token&&(Ext.Ajax.defaultHeaders={modAuth:r.object.token},Ext.Ajax.extraParams={HTTP_MODAUTH:r.object.token},MODx.siteId=r.object.token,MODx.msg.status({message:_("session_extended")}))}}),Ext.reg("modx-window-login",MODx.window.Login), /*! FileAPI 2.0.25 - BSD | git://github.com/mailru/FileAPI.git * FileAPI — a set of javascript tools for working with files. Multiupload, drag'n'drop and chunked file upload. Images: crop, resize and auto orientation by EXIF. */ diff --git a/manager/assets/modext/util/utilities.js b/manager/assets/modext/util/utilities.js index 00371760026..30c818ecb77 100644 --- a/manager/assets/modext/util/utilities.js +++ b/manager/assets/modext/util/utilities.js @@ -8,78 +8,75 @@ Ext.namespace('MODx.util.Format'); * @param {Object} config An object of configuration properties * @xtype modx-json-reader */ -MODx.util.JSONReader = function(config) { - config = config || {}; - Ext.applyIf(config,{ - successProperty:'success' - ,totalProperty: 'total' - ,root: 'data' +MODx.util.JSONReader = function(config = {}) { + Ext.applyIf(config, { + successProperty: 'success', + totalProperty: 'total', + root: 'data' }); - MODx.util.JSONReader.superclass.constructor.call(this,config,['id','msg']); + MODx.util.JSONReader.superclass.constructor.call(this, config, ['id', 'msg']); }; -Ext.extend(MODx.util.JSONReader,Ext.data.JsonReader); -Ext.reg('modx-json-reader',MODx.util.JSONReader); +Ext.extend(MODx.util.JSONReader, Ext.data.JsonReader); +Ext.reg('modx-json-reader', MODx.util.JSONReader); /** * @class MODx.util.Progress */ MODx.util.Progress = { - id: 0 - ,time: function(v,id,msg) { + id: 0, + time: function(v, id, msg) { msg = msg || _('saving'); if (MODx.util.Progress.id === id && v < 11) { - Ext.MessageBox.updateProgress(v/10,msg); + Ext.MessageBox.updateProgress(v / 10, msg); } - } - ,reset: function() { - MODx.util.Progress.id = MODx.util.Progress.id + 1; + }, + reset: function() { + MODx.util.Progress.id += 1; } }; - MODx.util.UrlParams = { get() { - return this.parse(window.location.search) + return this.parse(window.location.search); }, set(data) { - const params = decodeURIComponent(new URLSearchParams(data).toString()) + const params = decodeURIComponent(new URLSearchParams(data).toString()); if (params.length) { - window.history.pushState(params, '', document.location.pathname + '?' + params); + window.history.pushState(params, '', `${document.location.pathname}?${params}`); } else { window.history.pushState('', '', document.location.pathname); } }, add(key, val) { - const params = this.get() - params[key] = val - this.set(params) + const params = this.get(); + params[key] = val; + this.set(params); }, remove(key) { - const params = this.get() - delete params[key] - this.set(params) + const params = this.get(); + delete params[key]; + this.set(params); }, clear() { - this.set({}) + this.set({}); }, parse(str) { - const params = new URLSearchParams(str) - return Object.fromEntries(params.entries()) + const params = new URLSearchParams(str); + return Object.fromEntries(params.entries()); } -} +}; /** Adds a lock mask to an element */ -MODx.LockMask = function(config) { - config = config || {}; - Ext.applyIf(config,{ - msg: _('locked') - ,msgCls: 'modx-lockmask' +MODx.LockMask = function(config = {}) { + Ext.applyIf(config, { + msg: _('locked'), + msgCls: 'modx-lockmask' }); - MODx.LockMask.superclass.constructor.call(this,config.el,config); + MODx.LockMask.superclass.constructor.call(this, config.el, config); }; -Ext.extend(MODx.LockMask,Ext.LoadMask,{ - locked: false - ,toggle: function() { +Ext.extend(MODx.LockMask, Ext.LoadMask, { + locked: false, + toggle: function() { if (this.locked) { this.hide(); this.locked = false; @@ -87,20 +84,26 @@ Ext.extend(MODx.LockMask,Ext.LoadMask,{ this.show(); this.locked = true; } + }, + lock: function() { + this.locked = true; + this.show(); + }, + unlock: function() { + this.locked = false; + this.hide(); } - ,lock: function() { this.locked = true; this.show(); } - ,unlock: function() { this.locked = false; this.hide(); } }); -Ext.reg('modx-lockmask',MODx.LockMask); +Ext.reg('modx-lockmask', MODx.LockMask); /** * Adds a new config parameter to allow preservation of trailing zeros in decimal numbers */ Ext.override(Ext.form.NumberField, { strictDecimalPrecision: false, - fixPrecision : function(value){ - var nan = isNaN(value); - if(!this.allowDecimals || this.decimalPrecision == -1 || nan || !value){ + fixPrecision: function(value) { + const nan = Number.isNaN(value); + if (!this.allowDecimals || this.decimalPrecision === -1 || nan || !value) { return nan ? '' : value; } return this.allowDecimals && this.strictDecimalPrecision @@ -111,22 +114,22 @@ Ext.override(Ext.form.NumberField, { }); /** add clearDirty to basicform */ -Ext.override(Ext.form.BasicForm,{ - clearDirty : function(nodeToRecurse){ +Ext.override(Ext.form.BasicForm, { + clearDirty: function(nodeToRecurse) { nodeToRecurse = nodeToRecurse || this; - nodeToRecurse?.items?.each?.(function(f){ - if (!f.getValue) return; - - if(f.items){ - this.clearDirty(f); - } else if(f.originalValue != f.getValue()){ - f.originalValue = f.getValue(); + nodeToRecurse?.items?.each?.(function(field) { + if (!field.getValue) { + return; + } + if (field.items) { + this.clearDirty(field); + } else if (field.originalValue !== field.getValue()) { + field.originalValue = field.getValue(); } - },this); + }, this); } }); - /** * Static Textfield */ @@ -139,7 +142,21 @@ MODx.StaticTextField = Ext.extend(Ext.form.TextField, { MODx.StaticTextField.superclass.onRender.apply(this, arguments); } }); -Ext.reg('statictextfield',MODx.StaticTextField); +Ext.reg('statictextfield', MODx.StaticTextField); + +/** + * Static Textarea + */ +MODx.StaticTextArea = Ext.extend(Ext.form.TextArea, { + fieldClass: 'x-static-text-field', + + onRender: function() { + this.readOnly = true; + this.disabled = !this.initialConfig.submitValue; + MODx.StaticTextArea.superclass.onRender.apply(this, arguments); + } +}); +Ext.reg('statictextarea', MODx.StaticTextArea); /** * Static Boolean @@ -151,10 +168,10 @@ MODx.StaticBoolean = Ext.extend(Ext.form.TextField, { this.readOnly = true; this.disabled = !this.initialConfig.submitValue; MODx.StaticBoolean.superclass.onRender.apply(this, arguments); - this.on('change',this.onChange,this); - } + this.on('change', this.onChange, this); + }, - ,setValue: function(v) { + setValue: function(v) { if (v === 1) { this.addClass('green'); v = _('yes'); @@ -165,33 +182,38 @@ MODx.StaticBoolean = Ext.extend(Ext.form.TextField, { MODx.StaticBoolean.superclass.setValue.apply(this, arguments); } }); -Ext.reg('staticboolean',MODx.StaticBoolean); +Ext.reg('staticboolean', MODx.StaticBoolean); // This method strips not allowed html tags/attributes, html comments and php tags, // replaces javascript invocation in a href attribute and masks html event attributes // in an input string - assuming the result is safe to be displayed by a browser -MODx.util.safeHtml = function (input, allowedTags, allowedAttributes) { - var strip = function(input, allowedTags, allowedAttributes) { - return input.replace(tags, function ($0, $1) { - return allowedTags.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : ''; - }).replace(attributes, function ($0, $1) { - return allowedAttributes.indexOf($1.toLowerCase() + ',') > -1 ? $0 : ''; - }); - }; - allowedTags = (((allowedTags || '
    ') + '') - .toLowerCase() - .match(/<[a-z][a-z0-9]*>/g) || []) - .join(''); // making sure the allowedTags arg is a string containing only tags in lowercase (
    ) - allowedAttributes = (((allowedAttributes || 'href,class') + '') - .toLowerCase() - .match(/[a-z\-,]*/g) || []) - .join('').concat(','); // making sure the allowedAttributes arg is a comma separated string containing only attributes in lowercase (a,b,c) - var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi, +MODx.util.safeHtml = (input, allowedTags, allowedAttributes) => { + const + tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi, attributes = /([a-z][a-z0-9]*)\s*=\s*".*?"/gi, eventAttributes = /on([a-z][a-z0-9]*\s*=)/gi, commentsAndPhpTags = /|<\?(?:php)?[\s\S]*?\?>/gi, hrefJavascript = /href(\s*?=\s*?(["'])javascript:.*?\2|\s*?=\s*?javascript:.*?(?![^> ]))/gi, - length; + strip = (string, allowedTagsDef, allowedAttrDef) => { + const + tagsReplacer = (match, group1) => (allowedTagsDef.indexOf(`<${group1.toLowerCase()}>`) > -1 ? match : ''), + attrReplacer = (match, group1) => (allowedAttrDef.indexOf(`${group1.toLowerCase()},`) > -1 ? match : '') + ; + return string.replace(tags, tagsReplacer).replace(attributes, attrReplacer); + } + ; + let length; + // making sure the allowedTags arg is a string containing only tags in lowercase () + allowedTags = ((`${allowedTags || '
    '}`) + .toLowerCase() + .match(/<[a-z][a-z0-9]*>/g) || []) + .join(''); + // making sure the allowedAttributes arg is a comma separated string containing only attributes in lowercase (a,b,c) + allowedAttributes = ((`${allowedAttributes || 'href,class'}`) + .toLowerCase() + .match(/[a-z\-,]*/g) || []) + .join('') + .concat(','); input = input.replace(commentsAndPhpTags, '').replace(hrefJavascript, 'href="javascript:void(0)"'); do { length = input.length; @@ -200,226 +222,247 @@ MODx.util.safeHtml = function (input, allowedTags, allowedAttributes) { return input.replace(eventAttributes, 'on​$1'); }; -/**************************************************************************** - * Ext-specific overrides/extensions * - ****************************************************************************/ +// *** Ext-specific overrides/extensions *** /* add helper method to set checkbox boxLabel */ Ext.override(Ext.form.Checkbox, { - setBoxLabel: function(boxLabel){ + setBoxLabel: function(boxLabel) { this.boxLabel = boxLabel; - if(this.rendered){ + if (this.rendered) { this.wrap.child('.x-form-cb-label').update(boxLabel); } } }); -var FieldSetonRender = Ext.form.FieldSet.prototype.onRender; -Ext.override(Ext.form.FieldSet, { - onRender : function(ct, position){ - FieldSetonRender.call(this, ct, position); +const FieldSetOnRender = Ext.form.FieldSet.prototype.onRender; - if(this.checkboxToggle){ - var trigger = this.el.dom.getElementsByClassName(this.headerTextCls)[0]; - var elem = this; +Ext.override(Ext.form.FieldSet, { + onRender: function(ct, position) { + FieldSetOnRender.call(this, ct, position); + if (this.checkboxToggle) { + const + trigger = this.el.dom.getElementsByClassName(this.headerTextCls)[0], + elem = this + ; if (trigger) { - trigger.addEventListener('click', function(e) { + trigger.addEventListener('click', e => { elem.checkbox.dom.click(e); }, false); } } - }, + } }); - -Array.prototype.in_array = function(p_val) { - for(var i=0,l=this.length;i 0) { + if (fields.length > 0) { this.items.addAll(fields); - for(var f=0;f', - elbowMarkup = n.attributes.pseudoroot ? - '' : - '', - - buf = ['
  • ', - '',this.indentMarkup,"", + iconClass = a.iconCls ? ` ${a.iconCls}` : '', + iconMarkup = ``, + elbowMarkup = n.attributes.pseudoroot + ? '' + : '', + checkboxMarkup = hasCheckbox ? (`' : '>'}`) : '', + targetMarkup = a.hrefTarget ? `target="${a.hrefTarget}"` : '', + buf = [ + '
  • ', + `", + checkboxMarkup, + ``, + `${renderer(a)}`, + '', + '', '', - "
  • "].join(''); - - if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){ - this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf); - }else{ - this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf); + '' + ].join('') + ; + let nel; + // eslint-disable-next-line no-cond-assign + if (bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())) { + this.wrap = Ext.DomHelper.insertHtml('beforeBegin', nel, buf); + } else { + this.wrap = Ext.DomHelper.insertHtml('beforeEnd', targetNode, buf); } + /* eslint-disable prefer-destructuring */ this.elNode = this.wrap.childNodes[0]; this.ctNode = this.wrap.childNodes[1]; - var cs = this.elNode.childNodes; + const cs = this.elNode.childNodes; this.indentNode = cs[0]; this.ecNode = cs[1]; this.iconNode = cs[2]; - var index = 3; - if(cb){ + let index = 3; + if (hasCheckbox) { this.checkbox = cs[3]; - - this.checkbox.defaultChecked = this.checkbox.checked; index++; } this.anchor = cs[index]; this.textNode = cs[index].firstChild; - } + /* eslint-enable prefer-destructuring */ + }, /** * Renders the item text as a XSS-safe value. Can be overridden with a renderItemText method on the Tree. * @param text * @returns string */ - ,renderItemText: function(item) { - return Ext.util.Format.htmlEncode(item.text) - } - ,getChildIndent : function(){ - if(!this.childIndent){ - var buf = [], - p = this.node; - while(p){ - if((!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)) && !p.attributes.pseudoroot){ - if(!p.isLast()) { - buf.unshift(''); + renderItemText: function(item) { + return Ext.util.Format.htmlEncode(item.text); + }, + getChildIndent: function() { + if (!this.childIndent) { + const buf = []; + let p = this.node; + while (p) { + if ((!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)) && !p.attributes.pseudoroot) { + if (!p.isLast()) { + buf.unshift(``); } else { - buf.unshift(''); + buf.unshift(``); } } p = p.parentNode; } - this.childIndent = buf.join(""); + this.childIndent = buf.join(''); } return this.childIndent; } }); - /* allows for messages in JSON responses */ -Ext.override(Ext.form.Action.Submit,{ - handleResponse : function(response){ - var m = Ext.decode(response.responseText); /* shaun 7/11/07 */ +Ext.override(Ext.form.Action.Submit, { + handleResponse: function(response) { + const messageData = Ext.decode(response.responseText); if (this.form.errorReader) { - var rs = this.form.errorReader.read(response); - var errors = []; - if (rs.records) { - for(var i = 0, len = rs.records.length; i < len; i=i+1) { - var r = rs.records[i]; - errors[i] = r.data; + const + responseData = this.form.errorReader.read(response), + errors = [] + ; + if (responseData.records) { + for (let i = 0, len = responseData.records.length; i < len; i++) { + const record = responseData.records[i]; + errors[i] = record.data; } } - if (errors.length < 1) { errors = null; } return { - success : rs.success - ,message : m.message /* shaun 7/11/07 */ - ,object : m.object /* shaun 7/18/07 */ - ,errors : errors + success: responseData.success, + message: messageData.message, + object: messageData.object, + errors: errors.length < 1 ? null : errors }; } return Ext.decode(response.responseText); @@ -428,40 +471,43 @@ Ext.override(Ext.form.Action.Submit,{ /* QTips to form fields */ Ext.form.Field.prototype.afterRender = Ext.form.Field.prototype.afterRender.createSequence(function() { - if (this.description && parseInt(MODx.config.manager_tooltip_enable)) { + if (this.description && parseInt(MODx.config.manager_tooltip_enable, 10)) { Ext.QuickTips.register({ - target: this.getEl() - ,text: this.description - ,enabled: true - ,dismissDelay: MODx.config.manager_tooltip_delay + target: this.getEl(), + text: this.description, + enabled: true, + dismissDelay: MODx.config.manager_tooltip_delay }); - var label = Ext.form.Field.findLabel(this); - if(label){ + const label = Ext.form.Field.findLabel(this); + if (label) { Ext.QuickTips.register({ - target: label - ,text: this.description - ,enabled: true - ,dismissDelay: MODx.config.manager_tooltip_delay + target: label, + text: this.description, + enabled: true, + dismissDelay: MODx.config.manager_tooltip_delay }); } } }); -Ext.applyIf(Ext.form.Field,{ + +Ext.applyIf(Ext.form.Field, { findLabel: function(field) { - var wrapDiv = null; - var label = null; + let + wrapDiv = null, + label = null + ; wrapDiv = field.getEl().up('div.x-form-element'); - if(wrapDiv){ + if (wrapDiv) { label = wrapDiv.child('label'); } - if(label){ + if (label) { return label; } wrapDiv = field.getEl().up('div.x-form-item'); - if(wrapDiv) { + if (wrapDiv) { label = wrapDiv.child('label'); } - if(label){ + if (label) { return label; } } @@ -469,23 +515,29 @@ Ext.applyIf(Ext.form.Field,{ MODx.util.Format = { dateFromTimestamp: function(timestamp, date, time, defaultValue) { - if (date === undefined) date = true; - if (time === undefined) time = true; - if (defaultValue === undefined) defaultValue = ''; - - timestamp = parseInt(timestamp); - if (!(timestamp > 0)) return defaultValue; - + if (date === undefined) { + date = true; + } + if (time === undefined) { + time = true; + } + if (defaultValue === undefined) { + defaultValue = ''; + } + timestamp = parseInt(timestamp, 10); + if (!(timestamp > 0)) { + return defaultValue; + } if (timestamp.toString().length === 10) { timestamp *= 1000; } - var format = []; + let format = []; - if (date === true) format.push(MODx.config.manager_date_format); - if (time === true) format.push(MODx.config.manager_time_format); + if (date === true) { format.push(MODx.config.manager_date_format); } + if (time === true) { format.push(MODx.config.manager_time_format); } - if (format.length === 0) return defaultValue; + if (format.length === 0) { return defaultValue; } format = format.join(' '); @@ -551,6 +603,13 @@ MODx.util.Format = { .replace(new RegExp(`[${separator}]{2,}`, 'g'), separator) ; return padListItems ? formattedList.replaceAll(separator, `${separator} `) : formattedList ; + }, + + firstToUpperCase: function(string) { + return typeof string === 'string' && string.length > 0 + ? string.charAt(0).toUpperCase() + string.substring(1) + : string + ; } }; @@ -561,21 +620,23 @@ MODx.util.getHeaderBreadCrumbs = function(header, trail) { xtype: 'modx-header' }; } - - if (trail === undefined) trail = []; - if (!Array.isArray(trail)) trail = [trail]; - + if (trail === undefined) { + trail = []; + } + if (!Array.isArray(trail)) { + trail = [trail]; + } return { xtype: 'modx-breadcrumbs-panel', id: 'modx-header-breadcrumbs', cls: 'modx-header-breadcrumbs', desc: '', - bdMarkup: '
    • ' + - '{text}' + - '{text}' + - '
    ', + bdMarkup: '
    • ' + + '{text}' + + '{text}' + + '
    ', init: function() { - this.tpl = new Ext.XTemplate(this.bdMarkup, {compiled: true}); + this.tpl = new Ext.XTemplate(this.bdMarkup, { compiled: true }); }, trail: trail, listeners: { @@ -583,27 +644,26 @@ MODx.util.getHeaderBreadCrumbs = function(header, trail) { this.renderTrail(); } }, - renderTrail: function () { - this.tpl.overwrite(this.body.dom.lastElementChild, {trail: this.trail}); + renderTrail: function() { + this.tpl.overwrite(this.body.dom.lastElementChild, { trail: this.trail }); }, + // eslint-disable-next-line no-shadow updateTrail: function(trail, replace) { - if (replace === undefined) replace = false; - + if (replace === undefined) { + replace = false; + } if (replace === true) { this.trail = (Array.isArray(trail)) ? trail : [trail]; this.renderTrail(); return true; } - if (Array.isArray(trail)) { - for (var i = 0; i < trail.length; i++) { + for (let i = 0; i < trail.length; i++) { this.trail.push(trail[i]); } - this.renderTrail(); return true; } - this.trail.push(trail); this.renderTrail(); return true; @@ -737,71 +797,237 @@ MODx.util.tree = { }; Ext.util.Format.trimCommas = function(s) { - s = s.replace(',,',','); - var len = s.length; - if (s.substr(len-1,1) == ",") { - s = s.substring(0,len-1); + s = s.replace(',,', ','); + const len = s.length; + if (s.substr(len - 1, 1) === ',') { + s = s.substring(0, len - 1); } - if (s.substr(0,1) == ",") { + if (s.substr(0, 1) === ',') { s = s.substring(1); } - if (s == ',') { s = ''; } + if (s === ',') { + s = ''; + } return s; }; /* rowactions plugin */ -Ext.ns('Ext.ux.grid');if('function'!==typeof RegExp.escape){RegExp.escape=function(s){if('string'!==typeof s){return s}return s.replace(/([.*+?\^=!:${}()|\[\]\/\\])/g,'\\$1')}}Ext.ux.grid.RowActions=function(a){Ext.apply(this,a);this.addEvents('beforeaction','action','beforegroupaction','groupaction');Ext.ux.grid.RowActions.superclass.constructor.call(this)};Ext.extend(Ext.ux.grid.RowActions,Ext.util.Observable,{actionEvent:'click',autoWidth:true,dataIndex:'',editable:false,header:'',isColumn:true,keepSelection:false,menuDisabled:true,sortable:false,tplGroup:''+'
    ux-action-right '+'{cls}" style="{style}" qtip="{qtip}">{text}
    '+'
    ',tplRow:'
    '+''+'
    '+'ux-row-action-text" style="{hide}{style}" qtip="{qtip}">'+'{text}
    '+'
    '+'
    ',hideMode:'visibility',widthIntercept:4,widthSlope:21,init:function(g){this.grid=g;this.id=this.id||Ext.id();var h=g.getColumnModel().lookup;delete(h[undefined]);h[this.id]=this;if(!this.tpl){this.tpl=this.processActions(this.actions)}if(this.autoWidth){this.width=this.widthSlope*this.actions.length+this.widthIntercept;this.fixed=true}var i=g.getView();var j={scope:this};j[this.actionEvent]=this.onClick;g.afterRender=g.afterRender.createSequence(function(){i.mainBody.on(j);g.on('destroy',this.purgeListeners,this)},this);if(!this.renderer){this.renderer=function(a,b,c,d,e,f){b.css+=(b.css?' ':'')+'ux-row-action-cell';return this.tpl.apply(this.getData(a,b,c,d,e,f))}.createDelegate(this)}if(i.groupTextTpl&&this.groupActions){i.interceptMouse=i.interceptMouse.createInterceptor(function(e){if(e.getTarget('.ux-grow-action-item')){return false}});i.groupTextTpl='
    '+i.groupTextTpl+'
    '+this.processActions(this.groupActions,this.tplGroup).apply()}if(true===this.keepSelection){g.processEvent=g.processEvent.createInterceptor(function(a,e){if('mousedown'===a){return!this.getAction(e)}},this)}},getData:function(a,b,c,d,e,f){return c.data||{}},processActions:function(b,c){var d=[];Ext.each(b,function(a,i){if(a.iconCls&&'function'===typeof(a.callback||a.cb)){this.callbacks=this.callbacks||{};this.callbacks[a.iconCls]=a.callback||a.cb}var o={cls:a.iconIndex?'{'+a.iconIndex+'}':(a.iconCls?a.iconCls:''),qtip:a.qtipIndex?'{'+a.qtipIndex+'}':(a.tooltip||a.qtip?a.tooltip||a.qtip:''),text:a.textIndex?'{'+a.textIndex+'}':(a.text?a.text:''),hide:a.hideIndex?''+('display'===this.hideMode?'display:none':'visibility:hidden')+';':(a.hide?('display'===this.hideMode?'display:none':'visibility:hidden;'):''),align:a.align||'right',style:a.style?a.style:''};d.push(o)},this);var e=new Ext.XTemplate(c||this.tplRow);return new Ext.XTemplate(e.apply({actions:d}))},getAction:function(e){var a=false;var t=e.getTarget('.ux-row-action-item');if(t){a=t.className.replace(/ux-row-action-item /,'');if(a){a=a.replace(/ ux-row-action-text/,'');a=a.trim()}}return a},onClick:function(e,a){var b=this.grid.getView();var c=e.getTarget('.x-grid3-row');var d=b.findCellIndex(a.parentNode.parentNode);var f=this.getAction(e);if(false!==c&&false!==d&&false!==f){var g=this.grid.store.getAt(c.rowIndex);if(this.callbacks&&'function'===typeof this.callbacks[f]){this.callbacks[f](this.grid,g,f,c.rowIndex,d)}if(true!==this.eventsSuspended&&false===this.fireEvent('beforeaction',this.grid,g,f,c.rowIndex,d)){return}else if(true!==this.eventsSuspended){this.fireEvent('action',this.grid,g,f,c.rowIndex,d)}}t=e.getTarget('.ux-grow-action-item');if(t){var h=b.findGroup(a);var i=h?h.id.replace(/ext-gen[0-9]+-gp-/,''):null;var j;if(i){var k=new RegExp(RegExp.escape(i));j=this.grid.store.queryBy(function(r){return r._groupId.match(k)});j=j?j.items:[]}f=t.className.replace(/ux-grow-action-item (ux-action-right )*/,'');if('function'===typeof this.callbacks[f]){this.callbacks[f](this.grid,j,f,i)}if(true!==this.eventsSuspended&&false===this.fireEvent('beforegroupaction',this.grid,j,f,i)){return false}this.fireEvent('groupaction',this.grid,j,f,i)}}});Ext.reg('rowactions',Ext.ux.grid.RowActions); +Ext.ns('Ext.ux.grid'); +if (typeof RegExp.escape !== 'function') { + RegExp.escape = function(s) { + if (typeof s !== 'string') { + return s; + } + return s.replace(/([.*+?\^=!:${}()|\[\]\/\\])/g, '\\$1'); + }; +} +Ext.ux.grid.RowActions = function(a) { + Ext.apply(this, a); + this.addEvents('beforeaction', 'action', 'beforegroupaction', 'groupaction'); + Ext.ux.grid.RowActions.superclass.constructor.call(this); +}; +Ext.extend(Ext.ux.grid.RowActions, Ext.util.Observable, { + actionEvent: 'click', + autoWidth: true, + dataIndex: '', + editable: false, + header: '', + isColumn: true, + keepSelection: false, + menuDisabled: true, + sortable: false, + tplGroup: '
    ux-action-right {cls}" style="{style}" qtip="{qtip}">{text}
    ', + tplRow: '
    ux-row-action-text" style="{hide}{style}" qtip="{qtip}">{text}
    ', + hideMode: 'visibility', + widthIntercept: 4, + widthSlope: 21, + init: function(g) { + this.grid = g; + this.id = this.id || Ext.id(); + const h = g.getColumnModel().lookup; + delete h[undefined]; + h[this.id] = this; + if (!this.tpl) { + this.tpl = this.processActions(this.actions); + } + if (this.autoWidth) { + this.width = this.widthSlope * this.actions.length + this.widthIntercept; + this.fixed = true; + } + const + i = g.getView(), + j = { scope: this } + ; + j[this.actionEvent] = this.onClick; + g.afterRender = g.afterRender.createSequence(function() { + i.mainBody.on(j); + g.on('destroy', this.purgeListeners, this); + }, this); + if (!this.renderer) { + this.renderer = function(a, b, c, d, e, f) { + b.css += `${b.css ? ' ' : ''}ux-row-action-cell`; + return this.tpl.apply(this.getData(a, b, c, d, e, f)); + }.createDelegate(this); + } + if (i.groupTextTpl && this.groupActions) { + i.interceptMouse = i.interceptMouse.createInterceptor(function(e) { + if (e.getTarget('.ux-grow-action-item')) { + return false; + } + }); + i.groupTextTpl = `
    ${i.groupTextTpl}
    ${this.processActions(this.groupActions, this.tplGroup).apply()}`; + } + if (this.keepSelection === true) { + g.processEvent = g.processEvent.createInterceptor(function(a, e) { + if (a === 'mousedown') { + return !this.getAction(e); + } + }, this); + } + }, + getData: function(a, b, c, d, e, f) { + return c.data || {}; + }, + processActions: function(b, c) { + const d = []; + Ext.each( + b, + function(a, i) { + if (a.iconCls && typeof (a.callback || a.cb) === 'function') { + this.callbacks = this.callbacks || {}; + this.callbacks[a.iconCls] = a.callback || a.cb; + } + const o = { + /* eslint-disable no-nested-ternary */ + cls: a.iconIndex ? `{${a.iconIndex}}` : a.iconCls ? a.iconCls : '', + qtip: a.qtipIndex ? `{${a.qtipIndex}}` : a.tooltip || a.qtip ? a.tooltip || a.qtip : '', + text: a.textIndex ? `{${a.textIndex}}` : a.text ? a.text : '', + hide: a.hideIndex + ? `${this.hideMode === 'display' ? 'display:none' : 'visibility:hidden'};` + : a.hide ? (this.hideMode === 'display' ? 'display:none' : 'visibility:hidden;') : '', + align: a.align || 'right', + style: a.style ? a.style : '' + }; + /* eslint-enable no-nested-ternary */ + d.push(o); + }, + this + ); + const e = new Ext.XTemplate(c || this.tplRow); + return new Ext.XTemplate(e.apply({ actions: d })); + }, + getAction: function(e) { + let a = false; + const t = e.getTarget('.ux-row-action-item'); + if (t) { + a = t.className.replace(/ux-row-action-item /, ''); + if (a) { + a = a.replace(/ ux-row-action-text/, ''); + a = a.trim(); + } + } + return a; + }, + onClick: function(e, a) { + const + b = this.grid.getView(), + c = e.getTarget('.x-grid3-row'), + d = b.findCellIndex(a.parentNode.parentNode) + ; + let f = this.getAction(e); + if (c !== false && d !== false && f !== false) { + const g = this.grid.store.getAt(c.rowIndex); + if (this.callbacks && typeof this.callbacks[f] === 'function') { + this.callbacks[f](this.grid, g, f, c.rowIndex, d); + } + if (this.eventsSuspended !== true && this.fireEvent('beforeaction', this.grid, g, f, c.rowIndex, d) === false) { + return; + } + if (this.eventsSuspended !== true) { + this.fireEvent('action', this.grid, g, f, c.rowIndex, d); + } + } + const t = e.getTarget('.ux-grow-action-item'); + if (t) { + const + h = b.findGroup(a), + i = h ? h.id.replace(/ext-gen[0-9]+-gp-/, '') : null + ; + let j; + if (i) { + const k = new RegExp(RegExp.escape(i)); + j = this.grid.store.queryBy(function(r) { + return r._groupId.match(k); + }); + j = j ? j.items : []; + } + f = t.className.replace(/ux-grow-action-item (ux-action-right )*/, ''); + if (typeof this.callbacks[f] === 'function') { + this.callbacks[f](this.grid, j, f, i); + } + if (this.eventsSuspended !== true && this.fireEvent('beforegroupaction', this.grid, j, f, i) === false) { + return false; + } + this.fireEvent('groupaction', this.grid, j, f, i); + } + } +}); +Ext.reg('rowactions', Ext.ux.grid.RowActions); -/* +/** * Ext JS Library 0.30 * Copyright(c) 2006-2009, Ext JS, LLC. * licensing@extjs.com * - * http://extjs.com/license + * @deprecated No use found in the core as of 3.x; remove? */ Ext.SwitchButton = Ext.extend(Ext.Component, { - initComponent : function(){ + initComponent: function() { Ext.SwitchButton.superclass.initComponent.call(this); - var mc = new Ext.util.MixedCollection(); + const mc = new Ext.util.MixedCollection(); mc.addAll(this.items); this.items = mc; this.addEvents('change'); - if(this.handler){ + if (this.handler) { this.on('change', this.handler, this.scope || this); } }, - onRender : function(ct, position){ - var el = document.createElement('table'); + onRender: function(ct, position) { + const el = document.createElement('table'); el.cellSpacing = 0; el.className = 'x-rbtn'; el.id = this.id; - var row = document.createElement('tr'); + const row = document.createElement('tr'); el.appendChild(document.createElement('tbody')).appendChild(row); - var count = this.items.length; - var last = count - 1; + const + count = this.items.length, + last = count - 1 + ; this.activeItem = this.items.get(this.activeItem); - for(var i = 0; i < count; i++){ - var item = this.items.itemAt(i); - - var cell = row.appendChild(document.createElement('td')); - cell.id = this.id + '-rbi-' + i; + for (let i = 0; i < count; i++) { + const + item = this.items.itemAt(i), + cell = row.appendChild(document.createElement('td')), + nextCls = i === last ? 'x-rbtn-last' : 'x-rbtn-item' + ; + cell.id = `${this.id}-rbi-${i}`; - var cls = i == 0 ? 'x-rbtn-first' : (i == last ? 'x-rbtn-last' : 'x-rbtn-item'); + let cls = i === 0 ? 'x-rbtn-first' : nextCls; item.baseCls = cls; - if(this.activeItem == item){ + if (this.activeItem === item) { cls += '-active'; } cell.className = cls; - var button = document.createElement('button'); + const button = document.createElement('button'); button.innerHTML = ' '; button.className = item.iconCls; button.qtip = item.tooltip; @@ -816,21 +1042,21 @@ Ext.SwitchButton = Ext.extend(Ext.Component, { this.el.on('click', this.onClick, this); }, - getActiveItem : function(){ + getActiveItem: function() { return this.activeItem; }, - setActiveItem : function(item){ - if(typeof item != 'object' && item !== null){ + setActiveItem: function(item) { + if (typeof item != 'object' && item !== null) { item = this.items.get(item); } - var current = this.getActiveItem(); - if(item != current){ - if(current){ - Ext.fly(current.cell).removeClass(current.baseCls + '-active'); + const current = this.getActiveItem(); + if (item !== current) { + if (current) { + Ext.fly(current.cell).removeClass(`${current.baseCls}-active`); } - if(item) { - Ext.fly(item.cell).addClass(item.baseCls + '-active'); + if (item) { + Ext.fly(item.cell).addClass(`${item.baseCls}-active`); } this.activeItem = item; this.fireEvent('change', this, item); @@ -838,14 +1064,13 @@ Ext.SwitchButton = Ext.extend(Ext.Component, { return item; }, - onClick : function(e){ - var target = e.getTarget('td', 2); - if(!this.disabled && target){ + onClick: function(e) { + const target = e.getTarget('td', 2); + if (!this.disabled && target) { this.setActiveItem(parseInt(target.id.split('-rbi-')[1], 10)); } } }); - Ext.reg('switch', Ext.SwitchButton); Ext.onReady(function() { @@ -853,12 +1078,217 @@ Ext.onReady(function() { MODx.form.Handler = MODx.load({ xtype: 'modx-form-handler' }); MODx.msg = MODx.load({ xtype: 'modx-msg' }); }); + /* always-submit checkboxes */ -Ext.form.XCheckbox=Ext.extend(Ext.form.Checkbox,{submitOffValue:0,submitOnValue:1,onRender:function(){this.inputValue=this.submitOnValue;Ext.form.XCheckbox.superclass.onRender.apply(this,arguments);this.hiddenField=this.wrap.insertFirst({tag:'input',type:'hidden'});if(this.tooltip){this.imageEl.set({qtip:this.tooltip})}this.updateHidden()},setValue:function(v){v=this.convertValue(v);this.updateHidden(v);Ext.form.XCheckbox.superclass.setValue.apply(this,arguments)},updateHidden:function(v){v=undefined!==v?v:this.checked;v=this.convertValue(v);if(this.hiddenField){this.hiddenField.dom.value=v?this.submitOnValue:this.submitOffValue;this.hiddenField.dom.name=v?'':this.el.dom.name}},convertValue:function(v){return(v===true||v==='true'||v===this.submitOnValue||String(v).toLowerCase()==='on')}});Ext.reg('xcheckbox',Ext.form.XCheckbox); +Ext.form.XCheckbox = Ext.extend(Ext.form.Checkbox, { + submitOffValue: 0, + submitOnValue: 1, + onRender: function() { + this.inputValue = this.submitOnValue; + Ext.form.XCheckbox.superclass.onRender.apply(this, arguments); + this.hiddenField = this.wrap.insertFirst({ + tag: 'input', + type: 'hidden' + }); + if (this.tooltip) { + this.imageEl.set({ qtip: this.tooltip }); + } + this.updateHidden(); + }, + setValue: function(v) { + v = this.convertValue(v); + this.updateHidden(v); + Ext.form.XCheckbox.superclass.setValue.apply(this, arguments); + }, + updateHidden: function(v) { + v = undefined !== v ? v : this.checked; + v = this.convertValue(v); + if (this.hiddenField) { + this.hiddenField.dom.value = v ? this.submitOnValue : this.submitOffValue; + this.hiddenField.dom.name = v ? '' : this.el.dom.name; + } + }, + convertValue: function(v) { + return v === true || v === 'true' || v === this.submitOnValue || String(v).toLowerCase() === 'on'; + } +}); +Ext.reg('xcheckbox', Ext.form.XCheckbox); /* drag/drop grids */ -Ext.namespace('Ext.ux.dd');Ext.ux.dd.GridDragDropRowOrder=Ext.extend(Ext.util.Observable,{copy:false,scrollable:false,constructor:function(config){if(config)Ext.apply(this,config);this.addEvents({beforerowmove:true,afterrowmove:true,beforerowcopy:true,afterrowcopy:true});Ext.ux.dd.GridDragDropRowOrder.superclass.constructor.call(this)},init:function(grid){this.grid=grid;grid.enableDragDrop=true;grid.on({render:{fn:this.onGridRender,scope:this,single:true}})},onGridRender:function(grid){var self=this;this.target=new Ext.dd.DropTarget(grid.getEl(),{ddGroup:grid.ddGroup||'GridDD',grid:grid,gridDropTarget:this,notifyDrop:function(dd,e,data){if(this.currentRowEl){this.currentRowEl.removeClass('grid-row-insert-below');this.currentRowEl.removeClass('grid-row-insert-above')}var t=Ext.lib.Event.getTarget(e);var rindex=this.grid.getView().findRowIndex(t);if(rindex===false||rindex==data.rowIndex){return false}if(this.gridDropTarget.fireEvent(self.copy?'beforerowcopy':'beforerowmove',this.gridDropTarget,data.rowIndex,rindex,data.selections,123)===false){return false}var ds=this.grid.getStore();var selections=new Array();var keys=ds.data.keys;for(var key in keys){for(var i=0;idata.rowIndex&&this.rowPosition<0){rindex--}if(rindex0){rindex++}if(rindex>data.rowIndex&&data.selections.length>1){rindex=rindex-(data.selections.length-1)}if(rindex==data.rowIndex){return false}if(!self.copy){for(var i=0;i=0;i--){var insertIndex=rindex;ds.insert(insertIndex,selections[i])}var sm=this.grid.getSelectionModel();if(sm){sm.selectRecords(data.selections)}this.gridDropTarget.fireEvent(self.copy?'afterrowcopy':'afterrowmove',this.gridDropTarget,data.rowIndex,rindex,data.selections);return true},notifyOver:function(dd,e,data){var t=Ext.lib.Event.getTarget(e);var rindex=this.grid.getView().findRowIndex(t);var ds=this.grid.getStore();var keys=ds.data.keys;for(var key in keys){for(var i=0;i0){this.currentRowEl=new Ext.Element(currentRow);this.currentRowEl.addClass('grid-row-insert-below')}else{if(rindex-1>=0){var previousRow=this.grid.getView().getRow(rindex-1);this.currentRowEl=new Ext.Element(previousRow);this.currentRowEl.addClass('grid-row-insert-below')}else{this.currentRowEl.addClass('grid-row-insert-above')}}}catch(err){console.warn(err);rindex=false}return(rindex===false)?this.dropNotAllowed:this.dropAllowed},notifyOut:function(dd,e,data){if(this.currentRowEl){this.currentRowEl.removeClass('grid-row-insert-above');this.currentRowEl.removeClass('grid-row-insert-below')}}});if(this.targetCfg){Ext.apply(this.target,this.targetCfg)}if(this.scrollable){Ext.dd.ScrollManager.register(grid.getView().getEditorParent());grid.on({beforedestroy:this.onBeforeDestroy,scope:this,single:true})}},getTarget:function(){return this.target},getGrid:function(){return this.grid},getCopy:function(){return this.copy?true:false},setCopy:function(b){this.copy=b?true:false},onBeforeDestroy:function(grid){Ext.dd.ScrollManager.unregister(grid.getView().getEditorParent())}}); +Ext.namespace('Ext.ux.dd'); +Ext.ux.dd.GridDragDropRowOrder = Ext.extend(Ext.util.Observable, { + copy: false, + scrollable: false, + constructor: function(config) { + if (config) { + Ext.apply(this, config); + } + this.addEvents({ + beforerowmove: true, + afterrowmove: true, + beforerowcopy: true, + afterrowcopy: true + }); + Ext.ux.dd.GridDragDropRowOrder.superclass.constructor.call(this); + }, + init: function(grid) { + this.grid = grid; + grid.enableDragDrop = true; + grid.on({ + render: { + fn: this.onGridRender, + scope: this, + single: true + } + }); + }, + onGridRender: function(grid) { + const self = this; + this.target = new Ext.dd.DropTarget(grid.getEl(), { + ddGroup: grid.ddGroup || 'GridDD', + grid: grid, + gridDropTarget: this, + notifyDrop: function(dd, e, data) { + if (this.currentRowEl) { + this.currentRowEl.removeClass('grid-row-insert-below'); + this.currentRowEl.removeClass('grid-row-insert-above'); + } + const target = Ext.lib.Event.getTarget(e); + let rindex = this.grid.getView().findRowIndex(target); + if (rindex === false || rindex === data.rowIndex) { + return false; + } + if (this.gridDropTarget.fireEvent(self.copy ? 'beforerowcopy' : 'beforerowmove', this.gridDropTarget, data.rowIndex, rindex, data.selections, 123) === false) { + return false; + } + const + ds = this.grid.getStore(), + selections = [], + { keys } = ds.data + ; + // eslint-disable-next-line guard-for-in, no-restricted-syntax + for (const key in keys) { + for (let i = 0; i < data.selections.length; i++) { + if (keys[key] === data.selections[i].id) { + if (rindex === key) { + return false; + } + selections.push(data.selections[i]); + } + } + } + if (rindex > data.rowIndex && this.rowPosition < 0) { + rindex--; + } + if (rindex < data.rowIndex && this.rowPosition > 0) { + rindex++; + } + if (rindex > data.rowIndex && data.selections.length > 1) { + rindex -= (data.selections.length - 1); + } + if (rindex === data.rowIndex) { + return false; + } + if (!self.copy) { + for (let i = 0; i < data.selections.length; i++) { + ds.remove(ds.getById(data.selections[i].id)); + } + } + for (let i = selections.length - 1; i >= 0; i--) { + const insertIndex = rindex; + ds.insert(insertIndex, selections[i]); + } + const sm = this.grid.getSelectionModel(); + if (sm) { + sm.selectRecords(data.selections); + } + this.gridDropTarget.fireEvent(self.copy ? 'afterrowcopy' : 'afterrowmove', this.gridDropTarget, data.rowIndex, rindex, data.selections); + return true; + }, + notifyOver: function(dd, e, data) { + const + target = Ext.lib.Event.getTarget(e), + ds = this.grid.getStore(), + { keys } = ds.data + ; + let rindex = this.grid.getView().findRowIndex(target); + // eslint-disable-next-line guard-for-in, no-restricted-syntax + for (const key in keys) { + for (let i = 0; i < data.selections.length; i++) { + if (keys[key] === data.selections[i].id) { + if (rindex === key) { + if (this.currentRowEl) { + this.currentRowEl.removeClass('grid-row-insert-below'); + this.currentRowEl.removeClass('grid-row-insert-above'); + } + return this.dropNotAllowed; + } + } + } + } + if (rindex < 0 || rindex === false) { + this.currentRowEl.removeClass('grid-row-insert-above'); + return this.dropNotAllowed; + } + try { + const + currentRow = this.grid.getView().getRow(rindex), + resolvedRow = new Ext.Element(currentRow).getY() - this.grid.getView().scroller.dom.scrollTop, + rowHeight = currentRow.offsetHeight + ; + this.rowPosition = e.getPageY() - resolvedRow - rowHeight / 2; + if (this.currentRowEl) { + this.currentRowEl.removeClass('grid-row-insert-below'); + this.currentRowEl.removeClass('grid-row-insert-above'); + } + if (this.rowPosition > 0) { + this.currentRowEl = new Ext.Element(currentRow); + this.currentRowEl.addClass('grid-row-insert-below'); + } else if (rindex - 1 >= 0) { + const previousRow = this.grid.getView().getRow(rindex - 1); + this.currentRowEl = new Ext.Element(previousRow); + this.currentRowEl.addClass('grid-row-insert-below'); + } else { + this.currentRowEl.addClass('grid-row-insert-above'); + } + } catch (err) { + console.warn(err); + rindex = false; + } + return rindex === false ? this.dropNotAllowed : this.dropAllowed; + }, + notifyOut: function(dd, e, data) { + if (this.currentRowEl) { + this.currentRowEl.removeClass('grid-row-insert-above'); + this.currentRowEl.removeClass('grid-row-insert-below'); + } + } + }); + if (this.targetCfg) { + Ext.apply(this.target, this.targetCfg); + } + if (this.scrollable) { + Ext.dd.ScrollManager.register(grid.getView().getEditorParent()); + grid.on({ beforedestroy: this.onBeforeDestroy, scope: this, single: true }); + } + }, + getTarget: function() { + return this.target; + }, + getGrid: function() { + return this.grid; + }, + getCopy: function() { + return this.copy; + }, + setCopy: function(copy) { + this.copy = copy; + }, + onBeforeDestroy: function(grid) { + Ext.dd.ScrollManager.unregister(grid.getView().getEditorParent()); + } +}); /** selectability in Ext grids */ if (!Ext.grid.GridView.prototype.templates) { @@ -872,20 +1302,22 @@ Ext.grid.GridView.prototype.templates.cell = new Ext.Template( /* combocolumn */ if (!MODx.grid) { MODx.grid = {}; } -MODx.grid.ComboColumn = Ext.extend(Ext.grid.Column,{ - gridId: undefined - ,constructor: function(cfg){ +MODx.grid.ComboColumn = Ext.extend(Ext.grid.Column, { + gridId: undefined, + constructor: function(cfg) { MODx.grid.ComboColumn.superclass.constructor.call(this, cfg); - this.renderer = (this.editor && this.editor.triggerAction) ? MODx.grid.ComboBoxRenderer(this.editor,this.gridId, cfg.renderer) : function(value) {return value;}; + this.renderer = (this.editor && this.editor.triggerAction) ? MODx.grid.ComboBoxRenderer(this.editor, this.gridId, cfg.renderer) : function(value) { return value; }; } }); -Ext.grid.Column.types['combocolumn'] = MODx.grid.ComboColumn; +Ext.grid.Column.types.combocolumn = MODx.grid.ComboColumn; MODx.grid.ComboBoxRenderer = function(combo, gridId, currentRenderer) { - var getValue = function(value) { - var idx = combo.store.find(combo.valueField, value); - var rec = combo.store.getAt(idx); - if (rec) { - return rec.get(combo.displayField); + const getValue = value => { + const + idx = combo.store.find(combo.valueField, value), + record = combo.store.getAt(idx) + ; + if (record) { + return record.get(combo.displayField); } return value; }; @@ -893,7 +1325,7 @@ MODx.grid.ComboBoxRenderer = function(combo, gridId, currentRenderer) { return function(value, metaData, record, rowIndex, colIndex, store) { if (currentRenderer) { if (typeof currentRenderer.fn === 'function') { - var scope = (currentRenderer.scope) ? currentRenderer.scope : false; + const scope = (currentRenderer.scope) ? currentRenderer.scope : false; currentRenderer = currentRenderer.fn.bind(scope); } @@ -902,23 +1334,19 @@ MODx.grid.ComboBoxRenderer = function(combo, gridId, currentRenderer) { } } - if (combo.store.getCount() == 0 && gridId) { - combo.store.on( - 'load', - function() { - var grid = Ext.getCmp(gridId); - if (grid) { - grid.getView().refresh(); - } - }, this, {single: true} - ); + if (combo.store.getCount() === 0 && gridId) { + combo.store.on('load', function() { + const grid = Ext.getCmp(gridId); + if (grid) { + grid.getView().refresh(); + } + }, this, { single: true }); return value; } return getValue(value); }; }; - Ext.Button.buttonTemplate = new Ext.Template( '' ); @@ -931,7 +1359,6 @@ Ext.TabPanel.prototype.itemTpl = new Ext.Template( Ext.TabPanel.prototype.itemTpl.disableFormats = true; Ext.TabPanel.prototype.itemTpl.compile(); - Ext.namespace('Ext.ux.form'); /** @@ -943,8 +1370,9 @@ Ext.ux.form.CheckboxGroup = Ext.extend(Ext.form.CheckboxGroup, { aggregateSubmitField: {}, initComponent: function() { - const me = this, - ct = this.ownerCt + const + me = this, + ct = this.ownerCt ; if (typeof this.name === 'string' && this.name.length > 0) { this.aggregateSubmitField = new Ext.form.Hidden({ @@ -953,12 +1381,13 @@ Ext.ux.form.CheckboxGroup = Ext.extend(Ext.form.CheckboxGroup, { Ext.ux.form.CheckboxGroup.superclass.initComponent.call(this); - this.cls = typeof this.cls === 'string' && this.cls.length > 0 ? 'aggregated-group ' + this.cls : 'aggregated-group' ; + this.cls = typeof this.cls === 'string' && this.cls.length > 0 ? `aggregated-group ${this.cls}` : 'aggregated-group' ; + // eslint-disable-next-line func-names, prefer-arrow-callback Ext.each(this.items, function(item) { if (typeof me.value === 'string' && me.value.length > 0) { const savedVals = me.value.split(','); - if (savedVals.find(function(v){ return v == item.inputValue; }) == item.inputValue) { + if (savedVals.find(function(v) { return v === item.inputValue; }) === item.inputValue) { item.checked = true; } me.aggregateSubmitField.setValue(me.value); @@ -968,7 +1397,7 @@ Ext.ux.form.CheckboxGroup = Ext.extend(Ext.form.CheckboxGroup, { fn: me.setHiddenSubmit, scope: me } - } + }; item.submitValue = false; }); ct.add(this.aggregateSubmitField); @@ -977,8 +1406,10 @@ Ext.ux.form.CheckboxGroup = Ext.extend(Ext.form.CheckboxGroup, { } }, setHiddenSubmit: function() { - const groupOpts = this.items.items; - let vals = []; + const + groupOpts = this.items.items, + vals = [] + ; Ext.each(groupOpts, function(item) { if (item.checked) { vals.push(item.inputValue); @@ -998,7 +1429,7 @@ Ext.reg('xcheckboxgroup', Ext.ux.form.CheckboxGroup); */ Ext.define('AddFieldUtilities.plugin.Class', { alias: 'plugin.fieldutilities', - init: function(cmp){ + init: function(cmp) { cmp.on('afterrender', this.afterRender, cmp); }, afterRender: function() { @@ -1009,7 +1440,7 @@ Ext.define('AddFieldUtilities.plugin.Class', { tag: 'a', title: _('field_reset'), cls: 'modx-field-utils modx-field-reset' - }).on('click', function(){ + }).on('click', function() { me.reset(); }, me); @@ -1018,8 +1449,8 @@ Ext.define('AddFieldUtilities.plugin.Class', { tag: 'a', title: _('field_clear'), cls: 'modx-field-utils modx-field-clear' - }).on('click', function(){ - switch(this.xtype) { + }).on('click', function() { + switch (this.xtype) { case 'xcheckboxgroup': case 'checkboxgroup': if (Ext.isArray(this.items.items)) { @@ -1060,43 +1491,71 @@ Ext.define('AddFieldUtilities.plugin.Class', { // setcookie($this->getProperty('cookieName'), 'true', time() + 10, '/'); // } -MODx.util.FileDownload = function (fields) { +MODx.util.FileDownload = function(fields) { if (!Ext.isObject(fields)) { return; } + let polling = fields.timeout * 10 || 300; + const + me = this, + cookieName = `fileDownload${me.randomHex(16)}`, + ident = fields.ident || `filedownload-${Ext.id()}`, + url = fields.url || MODx.config.connector_url, + params = fields.params || {}, + debug = fields.debug || false, + successCallback = fields.success || null, + failureCallback = fields.failure || null, + body = Ext.getBody(), + frame = body.createChild({ + tag: 'iframe', + cls: 'x-hidden', + id: `${ident}-iframe`, + name: `${ident}-iframe` + }), + form = body.createChild({ + tag: 'form', + cls: 'x-hidden', + id: `${ident}-form`, + action: url, + target: `${ident}-iframe`, + method: 'post' + }) + ; - var me = this; - me.clearCookie = function () { - Ext.util.Cookies.set(cookieName, null, new Date("January 1, 1970"), '/'); + me.clearCookie = function() { + Ext.util.Cookies.set(cookieName, null, new Date('January 1, 1970'), '/'); Ext.util.Cookies.clear(cookieName, '/'); - } - me.randomHex = function (len) { + }; + me.randomHex = function(len) { const hex = '0123456789ABCDEF'; let output = ''; for (let i = 0; i < len; ++i) { output += hex.charAt(Math.floor(Math.random() * hex.length)); } return output; - } - me.isFinished = function (successCallback, failureCallback) { + }; + me.isFinished = function(successCallback, failureCallback) { // Check if file is started downloading if (Ext.util.Cookies.get(cookieName) && Ext.util.Cookies.get(cookieName) === 'true') { me.clearCookie(); if (successCallback) { - successCallback({success: true, message: _('$file_msg_download_success')}); + successCallback({ + success: true, + message: _('$file_msg_download_success') + }); } return; } // Check for error / IF any error happens the frame will have content try { if (frame.dom.contentDocument.body.innerHTML.length > 0) { - var result = Ext.decode(frame.dom.contentDocument.body.innerHTML); - result = (result) ? result : {success: false, message: _('file_msg_download_error')}; + let result = Ext.decode(frame.dom.contentDocument.body.innerHTML); + result = result || { success: false, message: _('file_msg_download_error') }; me.clearCookie(); if (failureCallback) { failureCallback(result); } - frame.dom.contentDocument.body.innerHTML = ""; + frame.dom.contentDocument.body.innerHTML = ''; return; } } catch (e) { @@ -1105,10 +1564,10 @@ MODx.util.FileDownload = function (fields) { if (polling) { if (debug) { - console.log('polling ' + polling); + console.log(`polling ${polling}`); } // Download is not finished. Check again in 100 milliseconds. - window.setTimeout(function () { + window.setTimeout(function() { polling--; me.isFinished(successCallback, failureCallback); }, 100); @@ -1116,45 +1575,22 @@ MODx.util.FileDownload = function (fields) { // Polling timeout with no fileDownload cookie set me.clearCookie(); if (failureCallback) { - failureCallback({success: false, message: _('file_err_download_timeout')}); + failureCallback({ success: false, message: _('file_err_download_timeout') }); } } }; - var cookieName = 'fileDownload' + me.randomHex(16); - var polling = fields.timeout * 10 || 300; - var ident = fields.ident || 'filedownload-' + Ext.id(); - var url = fields.url || MODx.config.connector_url; - var params = fields.params || {}; - var debug = fields.debug || false; - var successCallback = fields.success || null; - var failureCallback = fields.failure || null; - - var body = Ext.getBody(); - var frame = body.createChild({ - tag: 'iframe', - cls: 'x-hidden', - id: ident + '-iframe', - name: ident + '-iframe', - }); - var form = body.createChild({ - tag: 'form', - cls: 'x-hidden', - id: ident + '-form', - action: url, - target: ident + '-iframe', - method: 'post', - }); params.HTTP_MODAUTH = MODx.siteId; if (typeof successCallback === 'function') { params.cookieName = cookieName; } - Ext.iterate(params, function (name, value) { + // eslint-disable-next-line func-names, prefer-arrow-callback + Ext.iterate(params, function(name, value) { form.createChild({ tag: 'input', type: 'text', cls: 'x-hidden', - id: ident + '-' + name, + id: `${ident}-${name}`, name: name, value: value }); diff --git a/manager/assets/modext/widgets/core/modx.grid.js b/manager/assets/modext/widgets/core/modx.grid.js index 7462cb4e123..19a9cff204d 100644 --- a/manager/assets/modext/widgets/core/modx.grid.js +++ b/manager/assets/modext/widgets/core/modx.grid.js @@ -1,107 +1,115 @@ Ext.namespace('MODx.grid'); -MODx.grid.Grid = function(config = {}) { +/** + * @class MODx.grid.GridBase + * @extends Ext.grid.EditorGridPanel + * @param {Object} config An object of configuration properties + */ +MODx.grid.GridBase = function GridBase(config = {}) { this.config = config; this._loadStore(); this._loadColumnModel(); + this._loadMenu(); - Ext.applyIf(config,{ - store: this.store - ,cm: this.cm - ,sm: new Ext.grid.RowSelectionModel({singleSelect:true}) - ,paging: (config.bbar ? true : false) - ,loadMask: true - ,autoHeight: true - ,collapsible: true - ,stripeRows: true - ,header: false - ,cls: 'modx-grid' - ,preventRender: true - ,preventSaveRefresh: true - ,showPerPage: true - ,stateful: false - ,showActionsColumn: true - ,disableContextMenuAction: false - ,menuConfig: { - defaultAlign: 'tl-b?' - ,enableScrolling: false - } - ,viewConfig: { - forceFit: true - ,enableRowBody: true - ,autoFill: true - ,showPreview: true - ,scrollOffset: 0 - ,emptyText: config.emptyText || _('ext_emptymsg') - } - ,groupingConfig: { - enableGroupingMenu: true - } - }); if (config.paging) { - var pgItms = config.showPerPage ? [_('per_page')+':',{ - xtype: 'textfield' - ,cls: 'x-tbar-page-size' - ,value: config.pageSize || (parseInt(MODx.config.default_per_page) || 20) - ,listeners: { - 'change': {fn:this.onChangePerPage,scope:this} - ,'render': {fn: function(cmp) { - new Ext.KeyMap(cmp.getEl(), { - key: Ext.EventObject.ENTER - ,fn: this.blur - ,scope: cmp - }); - },scope:this} + const pgItms = config.showPerPage ? [`${_('per_page')}:`, { + xtype: 'textfield', + cls: 'x-tbar-page-size', + value: config.pageSize || (parseInt(MODx.config.default_per_page, 10) || 20), + listeners: { + change: { + fn: this.onChangePerPage, + scope: this + }, + render: { + fn: function(cmp) { + new Ext.KeyMap(cmp.getEl(), { + key: Ext.EventObject.ENTER, + fn: this.blur, + scope: cmp + }); + }, + scope: this + } } }] : []; if (config.pagingItems) { - for (var i=0;i 1 ? "' - + (config.pluralText || _('records')) + '" : "' - + (config.singleText || _('record')) + '"]})' + const groupingConfig = { + forceFit: true, + scrollOffset: 0, + groupTextTpl: `{text} ({[values.rs.length]} {[values.rs.length > 1 ? '${config.pluralText || _('records')}' : '${config.singleText || _('record')}']})` }; Ext.applyIf(config.groupingConfig, groupingConfig); - Ext.applyIf(config,{ + if (Object.hasOwn(config, 'viewConfig') && Object.hasOwn(config.viewConfig, 'getRowClass')) { + Ext.applyIf(config.groupingConfig, { + getRowClass: config.viewConfig.getRowClass + }); + } + Ext.applyIf(config, { view: new Ext.grid.GroupingView(config.groupingConfig) }); } if (config.tbar) { - for (var ix = 0;ix 1)) { return false; } } - return true; }; @@ -113,10 +121,10 @@ MODx.grid.Grid = function(config = {}) { } config.columns.push({ - id: 'modx-actions' - ,width: config.actionsColumnWidth || defaultActionsColumnWidth - ,menuDisabled: true - ,renderer: this.actionsColumnRenderer.bind(this) + id: 'modx-actions', + width: config.actionsColumnWidth || defaultActionsColumnWidth, + menuDisabled: true, + renderer: this.actionsColumnRenderer.bind(this) }); } @@ -128,29 +136,21 @@ MODx.grid.Grid = function(config = {}) { } config.cm.columns.push({ - id: 'modx-actions' - ,width: config.actionsColumnWidth || defaultActionsColumnWidth - ,menuDisabled: true - ,renderer: this.actionsColumnRenderer.bind(this) + id: 'modx-actions', + width: config.actionsColumnWidth || defaultActionsColumnWidth, + menuDisabled: true, + renderer: this.actionsColumnRenderer.bind(this) }); } } - MODx.grid.Grid.superclass.constructor.call(this,config); - this._loadMenu(config); - this.addEvents('beforeRemoveRow','afterRemoveRow','afterAutoSave'); - if (this.autosave) { - this.on('afterAutoSave', this.onAfterAutoSave, this); - } - if (!config.preventRender) { this.render(); } + MODx.grid.GridBase.superclass.constructor.call(this, config); + + this.addEvents('beforeRemoveRow', 'afterRemoveRow'); + this.on({ - render: { - fn: function() { - const topToolbar = this.getTopToolbar(); - if (topToolbar && topToolbar.initialConfig.cls && topToolbar.initialConfig.cls == 'has-nested-filters') { - this.hasNestedFilters = true; - } - }, + click: { + fn: this.onClickHandler, scope: this }, rowcontextmenu: { @@ -158,323 +158,67 @@ MODx.grid.Grid = function(config = {}) { scope: this } }); - if (config.autosave) { - this.on('afteredit',this.saveRecord,this); - } - - if (config.paging && config.grouping) { - this.getBottomToolbar().bind(this.store); - } - - if (!config.paging && !config.hasOwnProperty('pageSize')) { - config.pageSize = 0; - } - - this.getStore().load({ - params: { - start: config.pageStart || 0 - ,limit: config.hasOwnProperty('pageSize') ? config.pageSize : (parseInt(MODx.config.default_per_page) || 20) - } - }); - this.getStore().on('exception',this.onStoreException,this); - this.config = config; - - this.on('click', this.onClickHandler, this); }; -Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ - windows: {} +Ext.extend(MODx.grid.GridBase, Ext.grid.EditorGridPanel, { + currentLanguage: MODx.config.cultureKey || 'en', - ,onStoreException: function(dataProxy, type, action, options, response) { - const responseStatusCode = response.status || 'Unknown', - responseStatusText = !Ext.isEmpty(response.statusText) ? `(${response.statusText})` : '' - ; - let output = '', - msg = '' - ; - if (Ext.isEmpty(response.responseText)) { - // When php display_error is off, responseText will likely be empty and only general status info will be available - output = responseStatusCode !== 200 ? `
    ${responseStatusCode} ${responseStatusText}
    ` : ''; - } else { - // When php display_error is on OR the error is caught and explicity sent from the MODx class triggering the error, responseText should contain error text or possibly an object containing message text - try { - const responseText = Ext.decode(response.responseText); - // In what scenario will responseText be an object with a message property? - if (responseText && responseText.message) { - output = responseText.message; - } - } catch (e) { - output = response.responseText; - } - } - if (output) { - if (MODx.config.debug > 0) { - output = MODx.util.safeHtml(output, '
    ', 'class,colspan,rowspan'); - msg = _('error_grid_get_content_toscreen', { - message: `
    ${output}
    ` - }); - } else { - msg = _('error_grid_get_content_tolog'); - output = Ext.util.Format.stripTags(output).replaceAll('>', '>').replaceAll('<', '<'); - console.error(output); - } - } else { - // With some scenarios, such as when php display_errors = 1 and MODx system setting debug = 0 (reporting off), the reponseText will be empty and the status will be 200 - msg = _('error_grid_get_content_no_msg'); - } - this.getView().emptyText = `
    ${msg}
    `; - this.getView().refresh(false); - } + windows: {}, - ,saveRecord: function(e) { - e.record.data.menu = null; - var p = this.config.saveParams || {}; - Ext.apply(e.record.data,p); - var d = Ext.util.JSON.encode(e.record.data); - var url = this.config.saveUrl || (this.config.url || this.config.connector); - MODx.Ajax.request({ - url: url - ,params: { - action: this.config.save_action || 'updateFromGrid' - ,data: d - } - ,listeners: { - success: { - fn: function(r) { - if (this.config.save_callback) { - Ext.callback(this.config.save_callback,this.config.scope || this,[r]); - } - e.record.commit(); - if (!this.config.preventSaveRefresh) { - const gridRefresh = new Ext.util.DelayedTask(() => this.refresh()); - gridRefresh.delay(200); - } - this.fireEvent('afterAutoSave',r); - } - ,scope: this - } - ,failure: { - fn: function(r) { - e.record.reject(); - this.fireEvent('afterAutoSave', r); - } - ,scope: this - } - } - }); - } + protectedIdentifiers: null, /** - * Method executed after a record has been edited/saved inline from within the grid - * - * @param {Object} response - The processor save response object. See modConnectorResponse::outputContent (PHP) + * @property {String} permissionsProviderProp Specifies which property within a record contains + * the permissions object ('data' or 'json'). Local grids use Array stores where only the + * data *values* are stored in a simple array (record.json); the permissions and other object + * data must be stored in record.data. Remote stores, however, store their non-form (derived) + * data such as permissions in record.json. */ - ,onAfterAutoSave: function(response) { - if (!response.success && response.message === '') { - var msg = ''; - if (response.data.length) { - // We get some data for specific field(s) error but not regular error message - Ext.each(response.data, function(data, index, list) { - msg += (msg != '' ? '
    ' : '') + data.msg; - }, this); - } - if (Ext.isEmpty(msg)) { - // Still no valid message so far, let's use some fallback - msg = this.autosaveErrorMsg || _('error'); - } - MODx.msg.alert(_('error'), msg); - } - } - - ,onChangePerPage: function(tf,nv) { - if (Ext.isEmpty(nv)) return false; - nv = parseInt(nv); - this.getBottomToolbar().pageSize = nv; - this.store.load({params:{ - start:0 - ,limit: nv - }}); - } + permissionsProviderProp: 'data', - ,loadWindow: function(btn,e,win,or) { - var r = this.menu.record; - if (!this.windows[win.xtype] || win.force) { - Ext.applyIf(win,{ - record: win.blankValues ? {} : r - ,grid: this - ,listeners: { - 'success': {fn:win.success || this.refresh,scope:win.scope || this} - } - }); - if (or) { - Ext.apply(win,or); - } - this.windows[win.xtype] = Ext.ComponentMgr.create(win); - } - if (this.windows[win.xtype].setValues && win.blankValues !== true && r != undefined) { - this.windows[win.xtype].setValues(r); - } - this.windows[win.xtype].show(e.target); - } + userCanEdit: false, - ,confirm: function(type,text) { - var p = { action: type }; - var k = this.config.primaryKey || 'id'; - p[k] = this.menu.record[k]; + userCanCreate: false, - MODx.msg.confirm({ - title: _(type) - ,text: _(text) || _('confirm_remove') - ,url: this.config.url - ,params: p - ,listeners: { - 'success': {fn:this.refresh,scope:this} - } - }); - } + userCanDelete: false, - ,remove: function(text, action) { - if (this.destroying) { - return MODx.grid.Grid.superclass.remove.apply(this, arguments); - } - var r = this.menu.record; - text = text || 'confirm_remove'; - var p = this.config.saveParams || {}; - Ext.apply(p,{ action: action || 'remove' }); - var k = this.config.primaryKey || 'id'; - p[k] = r[k]; + gridMenuActions: [], - if (this.fireEvent('beforeRemoveRow',r)) { - MODx.msg.confirm({ - title: _('warning') - ,text: _(text, r) - ,url: this.config.url - ,params: p - ,listeners: { - 'success': {fn:function() { - this.removeActiveRow(r); - },scope:this} - } - }); - } - } + /** + * @property {Boolean} hasNestedFilters - Indicates whether the top toolbar filter(s) are nested + * within a secondary container; they will be nested when they have labels and those labels are + * positioned above the filter's input. + */ + hasNestedFilters: false, - ,removeActiveRow: function(r) { - if (this.fireEvent('afterRemoveRow',r)) { - var rx = this.getSelectionModel().getSelected(); - this.getStore().remove(rx); - } - } + /** @property {Boolean} userHasPermissions Whether user has permissions of any kind to manipulate the current grid's data */ + userHasPermissions: false, - ,_loadMenu: function() { - this.menu = new Ext.menu.Menu(this.config.menuConfig); - } + /** @property {Boolean} userHasSavePermissions Whether user has the general ability to save (to either create or edit) */ + userHasSavePermissions: false, - ,_showMenu: function(g,ri,e) { - e.stopEvent(); - e.preventDefault(); - this.menu.record = this.getStore().getAt(ri).data; - if (!this.getSelectionModel().isSelected(ri)) { - this.getSelectionModel().selectRow(ri); - } - this.menu.removeAll(); - if (this.getMenu) { - var m = this.getMenu(g,ri,e); - if (m && m.length && m.length > 0) { - this.addContextMenuItem(m); - } - } - if ((!m || m.length <= 0) && this.menu.record.menu) { - this.addContextMenuItem(this.menu.record.menu); - } - if (this.menu.items.length > 0) { - this.menu.showAt(e.xy); - } - } + showActionsMenu: null, - ,_loadStore: function() { - if (this.config.grouping) { - this.store = new Ext.data.GroupingStore({ - url: this.config.url - ,baseParams: this.config.baseParams || { action: this.config.action || 'getList'} - ,reader: new Ext.data.JsonReader({ - totalProperty: 'total' - ,root: 'results' - ,fields: this.config.fields - }) - ,sortInfo:{ - field: this.config.sortBy || 'id' - ,direction: this.config.sortDir || 'ASC' - } - ,remoteSort: this.config.remoteSort || false - ,remoteGroup: this.config.remoteGroup || false - ,groupField: this.config.groupBy || 'name' - ,groupDir: this.config.groupDir || 'ASC' - ,storeId: this.config.storeId || Ext.id() - ,autoDestroy: true - ,listeners: { - beforeload: function(store, options) { - const changedGroupDir = store.groupField === store.sortInfo.field && store.groupDir !== store.sortInfo.direction; - if (changedGroupDir) { - store.groupDir = store.sortInfo.direction; - store.baseParams.groupDir = store.sortInfo.direction; - } - }, - load: function(store, records, options) { - const cmp = Ext.getCmp('modx-content'); - if (cmp) { - cmp.doLayout(); - } - }, - groupchange: { - fn: function(store, groupField) { - store.groupDir = this.config.groupDir || 'ASC'; - store.baseParams.groupDir = store.groupDir; - store.sortInfo.direction = this.config.sortDir || 'ASC'; - store.load(); - }, - scope: this - } - } - }); - } else { - this.store = new Ext.data.JsonStore({ - url: this.config.url - ,baseParams: this.config.baseParams || { action: this.config.action || 'getList' } - ,fields: this.config.fields - ,root: 'results' - ,totalProperty: 'total' - ,remoteSort: this.config.remoteSort || false - ,storeId: this.config.storeId || Ext.id() - ,autoDestroy: true - ,listeners:{ - load: function() { - const cmp = Ext.getCmp('modx-content'); - if (cmp) { - cmp.doLayout(); - } - } - } - }); - } - } + // -*-*-* LOADERS *-*-*- - ,_loadColumnModel: function() { + _loadColumnModel: function() { if (this.config.columns) { - var c = this.config.columns; - for (var i=0;i' + '' + '
      ' @@ -734,10 +367,51 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ + '', { compiled: true }); - } + }, + + actionsColumnRenderer: function(value, metaData, record, rowIndex, colIndex, store) { + /* + Note: To maintain backward compatibility for core grids that have not yet been updated + to the new permissions checks and for extras that may extend this class in their grids, + we check showActionsMenu for strict boolean values (which will only be set by grids using + the new checks); otherwise showActionsMenu will be null (its default value set above), + indicating the legacy checks are to be used. + */ + if (this.showActionsMenu === false) { + return; + } + /* + showActionsMenu will be true if at least one user group-level permission is granted, + excluding create/new permissions (since that is not executed by our context/actions menus). + */ + if (this.showActionsMenu) { + // Export is always available; only continue filtering if grid does not offer export + if (!this.gridMenuActions.includes('export')) { + const isProtected = record[this.permissionsProviderProp]?.isProtected || false; + if (!this.userHasSavePermissions && isProtected) { + return; + } + const hasPermissionsProp = Object.hasOwn(record[this.permissionsProviderProp], 'permissions'); + // Checking record-level permissions + /** @todo This block checking for 'cls' can be removed once all grids are updated */ + if (!hasPermissionsProp && Object.hasOwn(record.data, 'cls')) { + if (Ext.isEmpty(record.data.cls)) { + return; + } + } + if (hasPermissionsProp) { + if ( + Ext.isEmpty(record[this.permissionsProviderProp].permissions) + || Object.values(record[this.permissionsProviderProp].permissions).every(permission => !permission) + ) { + return; + } + } + } + } + // eslint-disable-next-line prefer-spread + const actions = this.getActions.apply(this, arguments); - ,actionsColumnRenderer: function(value, metaData, record, rowIndex, colIndex, store) { - var actions = this.getActions.apply(this, [record, rowIndex, colIndex, store]); if (this.config.disableContextMenuAction !== true) { actions.push({ text: _('context_menu'), @@ -745,36 +419,156 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ icon: 'gear' }); } - return this._getActionsColumnTpl().apply({ actions: actions }); - } + }, + + getActions: function(value, metaData, record, rowIndex, colIndex, store) { + return []; + }, + + /** + * Builds the menu activated by clicking an action column icon (typically gear menu) + * @param {*} record The selected row's record + * @param {*} rowIndex The selected row's zero-based index + * @param {Ext.EventObjectImpl} e The Ext extended event object + */ + actionContextMenu: function(record, rowIndex, e) { + this._showMenu(this, rowIndex, e); + }, + + addContextMenuItem: function(items) { + items.forEach(menuItem => { + if (menuItem === '-') { + this.menu.add('-'); + } else { + let handler = Ext.emptyFn; + if (menuItem.handler) { + // eslint-disable-next-line no-eval + handler = eval(menuItem.handler); + if (handler && typeof (handler) == 'object' && handler.xtype) { + handler = this.loadWindow.createDelegate(this, [handler], true); + } + } else { + handler = function(item) { + const + { options } = item, + { id } = this.menu.record, + // eslint-disable-next-line no-shadow + doAction = (id, options) => { + const + action = Ext.urlEncode(options.params || { action: options.action }), + query = `?${action}&id=${id}`, + content = Ext.get('modx_content') + ; + if (content === null) { + window.location.href = query; + } else { + content.dom.src = query; + } + } + ; + if (options.confirm) { + // eslint-disable-next-line prefer-arrow-callback, func-names + Ext.Msg.confirm('', options.confirm, function(e) { + if (e === 'yes') { + doAction(id, options); + } + }, this); + } else { + doAction(id, options); + } + }; + } + this.menu.add({ + id: menuItem.id || Ext.id(), + text: menuItem.text, + scope: menuItem.scope || this, + options: menuItem, + handler: handler + }); + } + }); + }, + + /** + * Based on properties set in the calling child class and the current user's + * permissions for actions taken within that class (create, edit, delete, etc), + * evaluates whether the actions menu trigger should appear and sets boolean value + * on the showActionsMenu property + * @param {String} action The permissions key to evaluate; typically keys matching + * crud actions (create, update, delete), and/or sometimes custom ones (e.g., updateTv, etc) + * @param {Array} permissions Optional custom list of permissions required to show actions + * + * @return void + */ + setShowActionsMenu: function(action = null, permissions = []) { + if (this.config.disableContextMenuAction === true) { + this.showActionsMenu = false; + return; + } + if (permissions.length > 0) { + this.showActionsMenu = this.setUserHasPermissions(action, permissions); + } else { + const permissionsValues = []; + this.gridMenuActions.forEach(mode => { + mode = mode === 'duplicate' ? 'userCanCreate' : `userCan${MODx.util.Format.firstToUpperCase(mode)}`; + const modePermission = mode === 'userCanExport' ? true : this[mode]; + if (['userCanCreate', 'userCanEdit'].includes(mode) && modePermission === true) { + this.userHasSavePermissions = true; + } + permissionsValues.push(modePermission); + }); + this.showActionsMenu = !(permissionsValues.length === 0 || permissionsValues.every(value => value === false) === true); + } + }, - ,renderLink: function(v,attr) { - var el = new Ext.Element(document.createElement('a')); - el.addClass('x-grid-link'); - el.dom.title = _('edit'); - for (var i in attr) { - el.dom[i] = attr[i]; + /** + * Displays a row's context menu + * @param {Object} grid The selected row's grid + * @param {Number} rowIndex The selected row's zero-based index + * @param {Ext.EventObjectImpl} e The Ext extended event object + */ + _showMenu: function(grid, rowIndex, e) { + e.stopEvent(); + e.preventDefault(); + this.menu.record = this.getStore().getAt(rowIndex).data; + this.menu.recordIndex = rowIndex; + if (!this.getSelectionModel().isSelected(rowIndex)) { + this.getSelectionModel().selectRow(rowIndex); } - el.dom.innerHTML = Ext.util.Format.htmlEncode(v); - return el.dom.outerHTML; - } + this.menu.removeAll(); + let menu; + if (this.getMenu) { + menu = this.getMenu(grid, rowIndex, e); + if (menu && menu.length && menu.length > 0) { + this.addContextMenuItem(menu); + } + } + if ((!menu || menu.length <= 0) && this.menu.record.menu) { + this.addContextMenuItem(this.menu.record.menu); + } + if (this.menu.items.length > 0) { + this.menu.showAt(e.xy); + } + }, + + // -*-*-* PERMISSIONS HANDLING *-*-*- /** * Deprecated; renamed checkCellIsEditable. Remove in 3.1 */ - ,checkEditable: function(e) { + checkEditable: function(e) { this.checkCellIsEditable(e); - } + }, /** * Disables cell editor under specified conditions * @param {Object} e - Ext event object containing references to grid, record, field, value, row (index), column (index), and cancel (set true to cancel edit). * @return {Boolean} Return false to cancel or true to commit the edit */ - ,checkCellIsEditable: function(e) { + checkCellIsEditable: function(e) { const permissions = e.record.data.perm || ''; if (permissions.indexOf('edit') === -1) { return false; @@ -784,7 +578,7 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ case 'modx-grid-role': { const isAuthorityField = e.field === 'authority', - roleIsAssigned = e.record.json.isAssigned + roleIsAssigned = e.record[this.permissionsProviderProp].isAssigned ; if (roleIsAssigned && isAuthorityField) { return false; @@ -794,20 +588,20 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ default: } return true; - } + }, /** * Add one or more classes to a specific Editor Grid cell, typically to indicate a level of restriction - * + * * @param {Object} record - The row's data record * @param {Array} lockConditions - A set of one or more Boolean values (or ones that cast correctly to the expected Boolean value) derived from the row record or other values that indicate whether or not the subject cell should be marked as locked * @param {String} lockedClasses - One or more css class names * @param {Boolean} conditionsRequireAll - Whether all passed lockConditions need to evaluate to true to apply the locked class(es) */ - ,setEditableCellClasses: function(record, lockConditions = [], lockedClasses = 'locked', conditionsRequireAll = true) { + setEditableCellClasses: function(record, lockConditions = [], lockedClasses = '', conditionsRequireAll = true) { const - permissions = record.data.perm.trim(), - hasEditPermission = permissions.split(' ').includes('edit') + userCanEditRecord = this.userCanEditRecord(record), + lockedCSS = lockedClasses || 'locked' ; let classes = '', @@ -819,110 +613,148 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ : lockConditions.some(condition => Boolean(condition) === true) ; } - if (Ext.isEmpty(permissions)) { + if (!this.userCanEdit || !this.userHasRecordPermissions(record) || !userCanEditRecord) { classes = 'editor-disabled'; - } else if (hasEditPermission && shouldLock) { - classes = lockedClasses; + } else if (userCanEditRecord && shouldLock) { + classes = lockedCSS; } return classes; - } + }, + + // -> User- /User Group-Level Permissions Checks for the calling "class" object /** - * @property {Function} getLinkTemplate - Adds a link on a grid column's value based on the passed params. - * Usage of this method is necessary for grouping grids, where usage of renderers on its column model - * interfere with the grouping functionality. + * Assesses whether user can take the given action on an object or + * has been granted one of a custom list of permissions * - * @param {String} controllerPath - The initial part of the URL query indicating the controller action - * @param {String} displayValueIndex - The data index used as the link's text - * @param {Object} options - Additional URL query parameters (linkParams) and attributes for the link's anchor tag - * @return {Ext.Template} + * @param {String} action Identifies the action (create, edit, delete, or custom action) + * being evaluated. This applies to only a single object type and not to grids + * that have mixed object types displayed (in which case a custom list of permissions + * should be supplied to setShowActionsMenu, which in turn calls this method). + * @param {Array} permissions The list of permissions keys to be evaluated + * @returns {Boolean} Whether the user has permissions for this action or a set of custom set of permissions. */ - ,getLinkTemplate: function(controllerPath, displayValueIndex, options = {}) { - /* - linkParams, if given, should be an array of objects in the following format: - [{ key: 'paramKey', valueIndex: 'paramValue' }, ...{}] - */ - Ext.applyIf(options, { - linkParams: [], - linkClass: 'x-grid-link', - linkTitle: _('edit'), - linkTarget: '_blank' - }); - let params = ''; - controllerPath = controllerPath.indexOf('?a=') === 0 ? controllerPath : `?a=${controllerPath}` ; - if (options.linkParams.length > 0) { - params = []; - options.linkParams.forEach(param => { - params.push(`${param.key}={${param.valueIndex}}`); - }); - params = `&${params.join('&')}`; + setUserHasPermissions: function(action, permissions) { + const + permissionsList = permissions.map(item => item.trim()), + hasPermissions = action + ? permissionsList.every(permission => MODx.perm[permission]) + : permissionsList.some(permission => MODx.perm[permission]) + ; + if (action) { + this[`userCan${MODx.util.Format.firstToUpperCase(action)}`] = hasPermissions; } - return new Ext.Template( - `{${displayValueIndex}:htmlEncode}`, - { compiled: true } - ); - } + // Conditional needed, as we only want to change userHasPermissions if true + if (hasPermissions) { + this.userHasPermissions = true; + } + return hasPermissions; + }, - ,getActions: function(record, rowIndex, colIndex, store) { - return []; - } + /** + * Assigns a value to userCanEdit property based on the user's permissions; + * used to adjust which menu items are available, whether to render links + * to and item's editing page, and css cues across many grid classes + * + * @param {Array} permissions - A set of permissions keys to evaluate; note that many areas currently + * rely on a pair of permissions (save_x and edit_x), both of which must be enabled to edit a grid item + * + * @return void + */ + setUserCanEdit: function(permissions) { + this.setUserHasPermissions('edit', permissions); + }, - ,onClickHandler: function(e) { - var target = e.getTarget(); - if (!target.classList.contains('x-grid-action')) return; - if (!target.dataset.action) return; + /** + * Assigns a value to userCanCreate property based on the user's permissions; + * used to adjust which menu items are available (namely the Duplicate item) + * and whether to render the Create button in the grid's toolbar + * + * @param {Array} permissions - A set of permissions keys to evaluate; note that many areas currently + * rely on a pair of permissions (save_x and new_x), both of which must be enabled to create/duplicate a grid item + * + * @return void + */ + setUserCanCreate: function(permissions) { + this.setUserHasPermissions('create', permissions); + }, - var actionHandler = 'action' + target.dataset.action.charAt(0).toUpperCase() + target.dataset.action.slice(1); - if (!this[actionHandler] || (typeof this[actionHandler] !== 'function')) { - actionHandler = target.dataset.action; - if (!this[actionHandler] || (typeof this[actionHandler] !== 'function')) { - return; - } + /** + * Assigns a value to userCanDelete property based on the user's permissions; + * used to adjust which menu items are available in the context menus + * and whether to render the Delete menu item within a grid toolbar's Batch button + * + * @param {Array} permissions - A set of permissions keys to evaluate + * + * @return void + */ + setUserCanDelete: function(permissions) { + this.setUserHasPermissions('delete', permissions); + }, + + // -> Record-Level Permissions Checks, for objects with specific policies + + userHasRecordPermissions: function(record) { + const objPermissions = record[this.permissionsProviderProp].permissions; + if (Ext.isEmpty(objPermissions)) { + return false; } + return Object.values(objPermissions).some(permission => Boolean(permission) === true); + }, - var record = this.getSelectionModel().getSelected(); - var recordIndex = this.store.indexOf(record); - this.menu.record = record.data; + userCanEditRecord: function(record, action = 'update') { + const objPermissions = record[this.permissionsProviderProp].permissions; + return !Ext.isEmpty(objPermissions) && objPermissions[action] === true; + }, - this[actionHandler](record, recordIndex, e); - } + userCanDeleteRecords: function(records) { + return records.some(record => this.userCanDeleteRecord(record)); + }, - ,actionContextMenu: function(record, recordIndex, e) { - this._showMenu(this, recordIndex, e); - } + userCanDeleteRecord: function(record, action = 'delete') { + const objPermissions = record[this.permissionsProviderProp].permissions; + return !Ext.isEmpty(objPermissions) && !record[this.permissionsProviderProp].isProtected && objPermissions[action] === true; + }, - ,makeUrl: function () { - if (Array.isArray(this.config.urlFilters) && this.config.urlFilters.length > 0) { - var s = this.getStore(); - var p = { - a: MODx.request.a - } - if (MODx.request.id) { - p['id'] = MODx.request.id; - } - if (MODx.request.key) { - p['key'] = MODx.request.key; - } - for (var i = 0; i < this.config.urlFilters.length; ++i) { - if (s.baseParams.hasOwnProperty(this.config.urlFilters[i]) && s.baseParams[this.config.urlFilters[i]]) { - if (this.config.urlFilters[i] === 'namespace') { - p['ns'] = s.baseParams[this.config.urlFilters[i]]; - } else { - p[this.config.urlFilters[i]] = s.baseParams[this.config.urlFilters[i]]; - } - } - } - return Ext.urlAppend(MODx.config.manager_url, Ext.urlEncode(p).replace(/%2F/g, '/')); + userCanDuplicateRecord: function(record) { + const objPermissions = record[this.permissionsProviderProp].permissions; + return !Ext.isEmpty(objPermissions) && objPermissions.duplicate === true; + }, + + /** + * @property {Function} recordIsProtected - Used to remove the ability to delete + * specific record rows, regardless of permissions levels, based on a given record identifier + * + * @param {Number} subject - The value of the current record's identifier + * @param {Number} protectedIdentifiers - The record identifiers to be protected (making them non-editable/deletable) + * + * @return {Boolean} + */ + recordIsProtected: function(subject, protectedIdentifiers) { + if (Ext.isEmpty(protectedIdentifiers)) { + return false; } - } + protectedIdentifiers = protectedIdentifiers.map(identifier => (typeof identifier === 'string' ? identifier.trim() : identifier)); + return protectedIdentifiers.includes(subject); + }, - ,replaceState: function () { - if (typeof window.history.replaceState !== 'undefined' && - Array.isArray(this.config.urlFilters) && this.config.urlFilters.length > 0 - ) { - window.history.replaceState(this.getStore().baseParams, document.title, this.makeUrl()); + /** + * @property {Function} valueIsReserved - Wraps a grid value with a real or simulated link — a trigger that appears + * like an anchor link, usually to access a dropdown chooser or other control + * + * @param {Array|String} reservedValues - A set of values that can not be used for a particular object's field + * @param {Object} value - The submitted value being tested + * + * @return {Boolean} + */ + valueIsReserved: function(reservedValues, value) { + if (!Array.isArray(reservedValues)) { + reservedValues = reservedValues.split(','); } - } + return reservedValues.some(reserved => reserved.toLowerCase() === value.toLowerCase()); + }, + + // -*-*-* GRID FILTERING *-*-*- /** * @property {Function} findTabPanel - Recursively search ownerCts for this component's enclosing TabPanel @@ -930,28 +762,19 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ * @param {Object} referenceCmp - A child component of the TabPanel we're looking for * @return Ext.TabPanel */ - ,findTabPanel: function(referenceCmp) { - if (!referenceCmp.hasOwnProperty('ownerCt')) { - console.error('MODx.grid.Grid::findTabPanel: This component must have an ownerCt to find its tab panel.'); + findTabPanel: function(referenceCmp) { + if (!Object.hasOwn(referenceCmp, 'ownerCt')) { + console.error('MODx.grid.GridBase::findTabPanel: This component must have an ownerCt to find its tab panel.'); return false; } const container = referenceCmp.ownerCt, - isTabPanel = container.hasOwnProperty('xtype') && container.xtype.includes('tabs') + isTabPanel = Object.hasOwn(container, 'xtype') && container.xtype.includes('tabs') ; if (isTabPanel) { return container; } return this.findTabPanel(container); - } - - /** - * @property {Boolean} hasNestedFilters - Indicates whether the top toolbar filter(s) are nested - * within a secondary container; they will be nested when they have labels and those labels are - * positioned above the filter's input. - */ - ,hasNestedFilters: false - - ,currentLanguage: MODx.config.cultureKey || 'en' // removed MODx.request.language + }, /** * Applies a value persisted via URL (MODx.request) for use in grid and filter params. Used when multiple @@ -965,15 +788,15 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ * when no value is present. Set this to true for components that prefer an empty string * @returns {Number|String} Decoded param value */ - ,applyRequestFilter: function(tabPanelIndex, requestKey = 'policy', tabPanelType = 'vtab', setEmptyToString = false) { - const emptyVal = setEmptyToString ? '' : null ; + applyRequestFilter: function(tabPanelIndex, requestKey = 'policy', tabPanelType = 'vtab', setEmptyToString = false) { + const emptyVal = setEmptyToString ? '' : null; return Object.prototype.hasOwnProperty.call(MODx.request, tabPanelType) && parseInt(MODx.request[tabPanelType], 10) === tabPanelIndex && Object.prototype.hasOwnProperty.call(MODx.request, requestKey) - ? MODx.util.url.getParamValue(requestKey) - : emptyVal + ? MODx.util.url.getParamValue(requestKey) + : emptyVal ; - } + }, /** * Filters the grid data by the passed filter component (field) @@ -982,7 +805,7 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ * @param {String} param - The record index to apply the filter on; * may also be the general query/search field name. */ - ,applyGridFilter: function(cmp, param = 'query') { + applyGridFilter: function(cmp, param = 'query') { const filterValue = cmp.getValue(), store = this.getStore(), urlParams = {}, @@ -1005,8 +828,8 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ } else { MODx.util.url.clearParam(cmp); } - if (param == 'ns') { - store.baseParams['namespace'] = filterValue; + if (param === 'ns') { + store.baseParams.namespace = filterValue; } else { store.baseParams[param] = filterValue; } @@ -1015,7 +838,7 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ Determine if this is a vertical tab panel; if so there will also be a horizontal parent tab panel that needs to be accounted for */ - if (tabPanel.xtype == 'modx-vtabs') { + if (tabPanel.xtype === 'modx-vtabs') { const parentTabPanel = this.findTabPanel(tabPanel); if (parentTabPanel) { const activeParentTab = parentTabPanel.getActiveTab(); @@ -1036,18 +859,16 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ if (parentTabItems.length > 1) { urlParams.tab = activeParentTabIdx; } - } else { - if (tabItems.length > 1) { - urlParams.tab = activeTabIdx; - } + } else if (tabItems.length > 1) { + urlParams.tab = activeTabIdx; } } store.load(); - MODx.util.url.setParams(urlParams) + MODx.util.url.setParams(urlParams); if (bottomToolbar) { bottomToolbar.changePage(1); } - } + }, /** * @property {Function} clearGridFilters - Clears all grid filters and sets them to their default value @@ -1058,7 +879,7 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ * 'filter-category:3', where '3' is the filter's default value to be applied (instead of setting to an empty value) * */ - ,clearGridFilters: function(items) { + clearGridFilters: function(items) { const store = this.getStore(), bottomToolbar = this.getBottomToolbar(), data = Array.isArray(items) ? items : items.split(',') @@ -1066,9 +887,9 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ data.forEach(item => { const itemData = item.replace(/\s+/g, '').split(':'), itemId = itemData[0], - itemDefaultVal = itemData.length == 2 ? itemData[1] : null , + itemDefaultVal = itemData.length === 2 ? itemData[1] : null, cmp = this.getFilterComponent(itemId), - param = MODx.util.url.getParamNameFromCmp(cmp), + cmpParam = MODx.util.url.getParamNameFromCmp(cmp), isCombo = cmp?.xtype?.includes('combo') ; if (isCombo) { @@ -1083,13 +904,14 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ if (!Ext.isEmpty(itemDefaultVal)) { const paramsList = Object.keys(cmp.baseParams); paramsList.forEach(param => { - switch(param) { + switch (param) { case 'namespace': cmp.baseParams[param] = 'core'; break; case 'topic': cmp.baseParams[param] = 'default'; break; + // no default } }); } @@ -1098,21 +920,14 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ cmp.getStore().load(); } } - store.baseParams[param] = itemDefaultVal; + store.baseParams[cmpParam] = itemDefaultVal; }); store.load(); MODx.util.url.clearAllParams(); if (bottomToolbar) { bottomToolbar.changePage(1); } - } - - /** - * @property {Boolean} hasNestedFilters - Indicates whether the top toolbar filter(s) are nested - * within a secondary container; they will be nested when they have labels and those labels are - * positioned above the filter's input. - */ - ,hasNestedFilters: false + }, /** * @property {Function} getFilterComponent - Gets a filter component from the top toolbar by its itemId @@ -1120,17 +935,17 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ * @param {String} filterId - The Ext itemId of the filter component to fetch * @return {Ext.Component} */ - ,getFilterComponent: function(filterId) { + getFilterComponent: function(filterId) { const topToolbar = this.getTopToolbar(), cmp = this.hasNestedFilters && filterId !== 'filter-query' - ? topToolbar.find('itemId', `${filterId}-container`)[0].getComponent(filterId) - : topToolbar.getComponent(filterId) + ? topToolbar.find('itemId', `${filterId}-container`)[0].getComponent(filterId) + : topToolbar.getComponent(filterId) ; if (typeof cmp !== 'undefined') { return cmp; } console.error(`getFilterComponent: The filter component with itemId '${filterId}' could not be retrieved.`); - } + }, /** * @property {Function} refreshFilterOptions - Used to syncronize a filter's store options to those available in its target grid @@ -1138,7 +953,7 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ * @param {Array} filterData - An array of objects containing info needed to refresh each filter * @param {Boolean} clearDependentParams - If true, will clear values of dependentParams specified in the filterData */ - ,refreshFilterOptions: function(filterData = [], clearDependentParams = true) { + refreshFilterOptions: function(filterData = [], clearDependentParams = true) { if (filterData.length > 0) { filterData.forEach(data => { const filter = this.getFilterComponent(data.filterId); @@ -1146,10 +961,13 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ const store = filter.getStore(); filter.setValue(''); if (store) { - if (data.hasOwnProperty('dependentParams')) { - const dependentParams = Array.isArray(data.dependentParams) ? data.dependentParams : data.dependentParams.split(','); + if (Object.hasOwn(data, 'dependentParams')) { + const dependentParams = Array.isArray(data.dependentParams) + ? data.dependentParams + : data.dependentParams.split(',') + ; dependentParams.forEach(param => { - if (clearDependentParams && store.baseParams.hasOwnProperty(param)) { + if (clearDependentParams && Object.hasOwn(store.baseParams, param)) { store.baseParams[param] = ''; } }); @@ -1158,9 +976,9 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ } } }); - this.refresh(); + this.refresh(); } - } + }, /** * @property {Function} updateDependentFilter - Reloads a related filter's store based on the current filter's selected item @@ -1170,7 +988,7 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ * @param {Mixed} paramValue - Filter baseParams value for the paramKey * @param {Boolean} clearValue - Set true to clear filter's selected value */ - ,updateDependentFilter: function(filterId, paramKey, paramValue, clearValue = false) { + updateDependentFilter: function(filterId, paramKey, paramValue, clearValue = false) { const filter = this.getFilterComponent(filterId), filterStore = filter ? filter.getStore() : null ; @@ -1181,7 +999,320 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ filterStore.baseParams[paramKey] = paramValue; filterStore.load(); } - } + }, + + // -*-*-* RENDERERS & ENCODING *-*-*- + + renderEditableColumn: function(renderer) { + return function(value, metaData, record, rowIndex, colIndex, store) { + if (renderer) { + if (typeof renderer.fn === 'function') { + const scope = (renderer.scope) ? renderer.scope : false; + renderer = renderer.fn.bind(scope); + } + if (typeof renderer === 'function') { + value = renderer(value, metaData, record, rowIndex, colIndex, store); + } + } + metaData.css = ['x-editable-column', metaData.css || ''].join(' '); + + return value; + }; + }, + + /** + * @property {Function} renderLink - Wraps a grid value with a real or simulated link — a trigger that appears + * like an anchor link, usually to access a dropdown chooser or other control + * + * @param {String} content - The value being wrapped + * @param {Object} attributes - Html attributes to add to the link's tag + * @param {Boolean} isSimulated - Indicates whether the link is real (anchor tag) or not (simulated) + * @param {String} isSimulatedTag - The html tag name to wrap the content with + * + * @return {String} + */ + renderLink: function(content, attributes = {}, isSimulated = false, isSimulatedTag = 'span') { + const + tag = isSimulated ? isSimulatedTag : 'a', + classes = isSimulated ? 'x-grid-link simulated-link' : 'x-grid-link', + el = new Ext.Element(document.createElement(tag)) + ; + el.addClass(classes); + // Add default title if none given in attributes + if (!Object.hasOwn(attributes, 'title')) { + attributes.title = _('edit'); + } + Object.entries(attributes).forEach(([attr, value]) => { + el.dom[attr] = value; + }); + el.dom.innerHTML = Ext.util.Format.htmlEncode(content); + return el.dom.outerHTML; + }, + + rendYesNo: function(v, metaData) { + if (v === 1 || v === '1') { v = true; } + if (v === 0 || v === '0') { v = false; } + switch (v) { + case true: + case 'true': + case 1: + metaData.css += ' green'; + return _('yes'); + case false: + case 'false': + case '': + case 0: + metaData.css += ' red'; + return _('no'); + // no default + } + }, + + rendPassword: function(v) { + let z = ''; + for (let i = 0; i < v.length; i++) { + z = `${z}*`; + } + return z; + }, + + /** + * @todo Implement encodeURIComponent to fix issues with passing particluar + * chars via URL (e.g., # [pound/hash] used in color values, etc.) + */ + encode: function() { + const p = this.getStore().getRange(), + rs = {}; + for (let i = 0; i < p.length; i++) { + rs[p[i].data[this.config.primaryKey || 'id']] = p[i].data; + } + return Ext.encode(rs); + }, + + /** + * @property {Function} getLinkTemplate - Adds a link on a grid column's value based on the passed params. + * Usage of this method is necessary for grouping grids, where usage of renderers on its column model + * interfere with the grouping functionality. + * + * @param {String} controllerPath - The initial part of the URL query indicating the controller action + * @param {String} displayValueIndex - The data index used as the link's text + * @param {Object} options - Additional URL query parameters (linkParams) and attributes for the link's anchor tag + * @return {Ext.Template} + */ + getLinkTemplate: function(controllerPath, displayValueIndex, options = {}) { + /* + linkParams, if given, should be an array of objects in the following format: + [{ key: 'paramKey', valueIndex: 'paramValue' }, ...{}] + */ + Ext.applyIf(options, { + linkParams: [], + linkClass: 'x-grid-link', + linkTitle: _('edit'), + linkTarget: '_blank' + }); + let params = ''; + controllerPath = controllerPath.indexOf('?a=') === 0 ? controllerPath : `?a=${controllerPath}`; + if (options.linkParams.length > 0) { + params = []; + options.linkParams.forEach(param => { + params.push(`${param.key}={${param.valueIndex}}`); + }); + params = `&${params.join('&')}`; + } + return new Ext.Template( + `{${displayValueIndex}:htmlEncode}`, + { compiled: true } + ); + }, + + // -*-*-* CONFIG & COMPONENT BUILDERS *-*-*- + + /** + * Gets the view configuration for grids having row-specific editing permissions + * @param {Boolean} hasBulkActions Whether the grid has a bulk actions option + * (uses the checkbox selection model to select multiple rows) + * @param {Boolean} hasObjectLevelPermissions Whether individual rows might have + * differing permissions, based on the specific object they represent + * @param {Boolean} markActiveRows Whether classes should be added for objects + * whose records that can be activated or deactivated (e.g., Form Customization, Users, etc.) + * @returns {Object} The complete view config + */ + getViewConfig: function(hasBulkActions = true, hasObjectLevelPermissions = true, markActiveRows = false) { + return { + forceFit: true, + scrollOffset: 0, + enableRowBody: true, + showPreview: true, + getRowClass: function(record, index, rowParams, store) { + const + canDeleteRecord = this.grid.userCanDeleteRecord(record), + rowClasses = [] + ; + // Initial class required for grids utilizing the row expander + if (this.cm && Object.hasOwn(this.cm.config[0], 'expandRow')) { + rowClasses.push('x-grid3-row-collapsed'); + } + /* + Objects whose records can be activated/deactivated do not depend upon + permission to delete; 'visible' prop is used in Form Customization grids, + 'active' in others + */ + if (markActiveRows && (Object.hasOwn(record.data, 'active') || Object.hasOwn(record.data, 'visible'))) { + const activeClass = record.data.active || record.data.visible ? 'grid-row-active' : 'grid-row-inactive'; + rowClasses.push(activeClass); + } + // Early return if no deletion restrictions are in effect + if (hasObjectLevelPermissions && canDeleteRecord) { + return rowClasses.length ? rowClasses.join(' ') : '' ; + } + // Add various classes marking a row as protected + if (hasBulkActions && !canDeleteRecord && !markActiveRows) { + rowClasses.push('disable-selection'); + } + if (record[this.grid.permissionsProviderProp].isProtected) { + rowClasses.push('modx-protected-row'); + } + return rowClasses.length ? rowClasses.join(' ') : '' ; + } + }; + }, + + /** + * Builds the top toolbar's create/add button + * @param {String} objectType Identifier for object being worked with + * @param {String|Object} createHandler The name of the handler method or an object containing + * a custom configuration (typically a form window config used to create a new record) + * @param {String|Boolean} createPermission Name of the grid property that specifies whether the + * current user has necessary permissions to create new records. Set to true|false to override. + * @returns {Object} An Ext button config object + */ + getCreateButton: function(objectType, createHandler = 'create', createPermission = 'userCanCreate') { + const + handler = typeof createHandler === 'string' + ? this[createHandler] + : createHandler, + text = _(`${objectType.toLowerCase()}_create`) || _('create') + ; + return { + text: text, + cls: 'primary-button', + handler: handler, + scope: this, + listeners: { + /* + Note that because this method is typically called from a grid's + tbar config object, the permissions properties are not yet available; + thus it is important that the Create permission be assessed within the + button's render (or later) event, as is done below. + */ + render: { + fn: function(btn) { + const hasPermission = typeof createPermission === 'boolean' + ? createPermission + : this[createPermission] + ; + if (!hasPermission) { + btn.hide(); + } + }, + scope: this + } + } + }; + }, + + /** + * Builds the top toolbar's bulk actions button, containing a menu of various actions + * (typically only contains a delete action) + * @param {String} objectType Identifier for object being worked with + * @param {String} deleteAction Processor path for the removal action + * @param {String} pkType Specifies the object's primary key type (int or string) + * @param {...any} moreActions Additional button identifiers or config objects + * to add to the bulk actions menu + * @returns {Object} The complete bulk actions config + */ + getBulkActionsButton: function(objectType, deleteAction, pkType = 'int', ...moreActions) { + const + menuItems = [], + additionalMenuItems = [], + hasMoreActions = moreActions.length > 0 + ; + if (hasMoreActions) { + /** @var standardButtons Button configs for actions that are used in select grids, such as the Users and Form Customization (Sets) grids */ + const standardButtons = { + activate: { + text: _('selected_activate'), + itemId: 'modx-bulk-menu-opt-activate', + handler: this.activateSelected, + scope: this + }, + deactivate: { + text: _('selected_deactivate'), + itemId: 'modx-bulk-menu-opt-deactivate', + handler: this.deactivateSelected, + scope: this + } + }; + moreActions.forEach(action => { + if (typeof action === 'string') { + const key = action.toLowerCase(); + if (Object.hasOwn(standardButtons, key)) { + additionalMenuItems.push(standardButtons[key]); + } + } + }); + menuItems.push(...additionalMenuItems); + menuItems.push('-'); + } + menuItems.push({ + text: _('selected_remove'), + itemId: 'modx-bulk-menu-opt-remove', + handler: this.removeSelected.createDelegate(this, [objectType, deleteAction, pkType]), + scope: this + }); + return { + text: _('bulk_actions'), + menu: menuItems, + listeners: { + render: { + fn: function(btn) { + if ( + (!this.userCanDelete && !hasMoreActions) + || (!this.userCanDelete && !this.userCanEdit && hasMoreActions) + ) { + btn.hide(); + } + }, + scope: this + }, + click: { + fn: function(btn) { + const + removableItems = this.getRemovableItemsFromSelection(pkType), + menuOptRemove = btn.menu.getComponent('modx-bulk-menu-opt-remove') + ; + if (removableItems.length === 0) { + menuOptRemove.disable(); + } else { + menuOptRemove.enable(); + } + if (hasMoreActions) { + const selections = this.getSelectionModel().getSelections(); + additionalMenuItems.forEach(item => { + const itemCmp = btn.menu.getComponent(item.itemId); + if (selections.length === 0) { + itemCmp.disable(); + } else { + itemCmp.enable(); + } + }); + } + }, + scope: this + } + } + }; + }, /** * @property {Function} getQueryFilterField - Creates the query field component configuration @@ -1192,16 +1323,17 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ * @param {String} implementation - Optional, an identifier used to assign grid-specific behavior * @return {Object} */ - ,getQueryFilterField: function(filterSpec = 'filter-query', implementation = 'default') { + getQueryFilterField: function(filterSpec = 'filter-query', implementation = 'default') { let queryValue = ''; const filterSpecs = filterSpec.split(':'), filterId = filterSpecs[0].trim() ; if (filterSpecs.length === 2) { + // eslint-disable-next-line prefer-destructuring queryValue = filterSpecs[1]; } else { - queryValue = MODx.request.query ? MODx.util.url.decodeParamValue(MODx.request.query) : '' ; + queryValue = MODx.request.query ? MODx.util.url.decodeParamValue(MODx.request.query) : ''; } return { xtype: 'textfield', @@ -1213,7 +1345,7 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ change: { fn: function(cmp, newValue, oldValue) { this.applyGridFilter(cmp); - const usergroupTree = Ext.getCmp('modx-tree-usergroup') + const usergroupTree = Ext.getCmp('modx-tree-usergroup'); if (implementation === 'user-group-users' && usergroupTree) { /* When the user group users grid is shown in the primary ACLs panel, @@ -1223,7 +1355,7 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ const selectedNode = usergroupTree.getSelectionModel().getSelectedNode(), groupId = MODx.util.tree.getGroupIdFromNode(selectedNode) ; - MODx.util.url.setParams({group: groupId}); + MODx.util.url.setParams({ group: groupId }); } }, scope: this @@ -1243,12 +1375,12 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ fn: this.blur, scope: cmp }); - } - ,scope: this + }, + scope: this } } - } - } + }; + }, /** * @property {Function} getClearFiltersButton - Creates the clear filter button component configuration @@ -1258,7 +1390,7 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ * in the following format: 'filterItemId:relatedBaseParam, [filterItemId:relatedBaseParam,] ...' * @return {Object} */ - ,getClearFiltersButton: function(filters = 'filter-query', dependentFilterResets = null) { + getClearFiltersButton: function(filters = 'filter-query', dependentFilterResets = null) { if (Ext.isEmpty(filters)) { console.error('MODx.grid.Grid::getClearFiltersButton: There was a problem creating the Clear Filter button because the supplied filters list is invalid.'); return {}; @@ -1286,474 +1418,638 @@ Ext.extend(MODx.grid.Grid,Ext.grid.EditorGridPanel,{ } } } - } + }; if (dependentFilterResets) { config.dependentResets = dependentFilterResets; } return config; - } + }, + + editorYesNo: function(record = {}) { + Ext.applyIf(record, { + store: new Ext.data.SimpleStore({ + fields: ['d', 'v'], + data: [[_('yes'), true], [_('no'), false]] + }), + displayField: 'd', + valueField: 'v', + mode: 'local', + triggerAction: 'all', + editable: false, + selectOnFocus: false + }); + return new Ext.form.ComboBox(record); + }, + + // -*-*-* ACTION HANDLING *-*-*- /** - * Get the request value for a grid's category filtering. Derives whether the category param is to be applied to a - * grid and its category filter based on the existence of the tab param in the GET request. Needed where the same - * category processor is used for different purposes within the same editing panel (notably the Template and TV panels). + * @deprecated Remove once all grids with bulk deletion capability have been converted */ - ,getCategoryFilterValue: () => { - if (typeof MODx.request.tab === 'undefined' || typeof MODx.request.category === 'undefined') { - return null; + getSelectedAsList: function() { + const sels = this.getSelectionModel().getSelections(); + if (sels.length <= 0) { return false; } + + let cs = ''; + for (let i = 0; i < sels.length; i++) { + cs += `,${sels[i].data[this.config.primaryKey || 'id']}`; } - return Math.abs(parseInt(MODx.request.category, 10)); - } -}); -/* local grid */ -MODx.grid.LocalGrid = function(config) { - config = config || {}; + if (cs[0] === ',') { + cs = cs.substr(1); + } + return cs; + }, - if (config.grouping) { - Ext.applyIf(config,{ - view: new Ext.grid.GroupingView({ - forceFit: true - ,scrollOffset: 0 - ,hideGroupedColumn: config.hideGroupedColumn ? true : false - ,groupTextTpl: config.groupTextTpl || ('{text} ({[values.rs.length]} {[values.rs.length > 1 ? "' - +(config.pluralText || _('records')) + '" : "' - +(config.singleText || _('record'))+'"]})' ) - }) - }); - } - if (config.tbar) { - for (var i = 0;i { + const deletableRecord = record[this.permissionsProviderProp].permissions.delete; + if (!record[this.permissionsProviderProp].isProtected && deletableRecord) { + const item = itemIdType === 'string' ? record.data[pk] : parseInt(record.data[pk], 10); + removableItems.push(item); } - if (!itm.scope) { itm.scope = this; } + }); + return removableItems; + }, + + /** + * Performs the removal of one or more items selected + * + * @param {String} gridName The object identifier (e.g., 'source', 'context', etc) + * @param {String} removeAction The remove processor to call + * @param {String} pkType Indicates the primary key data type (string or int) + */ + removeSelected: function(gridName, removeAction, pkType = 'int') { + const removableSelections = this.getRemovableItemsFromSelection(pkType); + let + modalText, + actionKey + ; + if (removableSelections.length === 0) { + return false; } - } - Ext.applyIf(config,{ - title: '' - ,store: this._loadStore(config) - ,sm: new Ext.grid.RowSelectionModel({singleSelect:false}) - ,loadMask: true - ,collapsible: true - ,stripeRows: true - ,enableColumnMove: true - ,header: false - ,cls: 'modx-grid' - ,showActionsColumn: true - ,actionsColumnWidth: 50 - ,disableContextMenuAction: false - ,viewConfig: { - forceFit: true - ,enableRowBody: true - ,autoFill: true - ,showPreview: true - ,scrollOffset: 0 - ,emptyText: config.emptyText || _('ext_emptymsg') - } - ,menuConfig: { defaultAlign: 'tl-b?' ,enableScrolling: false } - }); + if (removableSelections.length === 1) { + modalText = _(`${gridName}_remove_confirm`, { name: removableSelections[0] }) || _('confirm_remove'); + } else { + modalText = _(`${gridName}_remove_multiple_confirm`) || _('confirm_remove_multiple'); + } + switch (gridName) { + case 'policy_template': + actionKey = 'templates'; + break; + default: + actionKey = gridName.endsWith('y') + ? `${gridName.substring(0, gridName.length - 1)}ies` + : `${gridName}s` + ; + } + MODx.msg.confirm({ + title: _('selected_remove'), + text: modalText, + url: this.config.url, + params: { + action: removeAction, + [actionKey]: removableSelections.join(',') + }, + listeners: { + success: { + fn: function(response) { + this.getSelectionModel().clearSelections(true); + this.refresh(); + this.fireEvent('afterRemoveRow', { ...response, itemsRemoved: removableSelections }); + }, + scope: this + } + } + }); + return true; + }, - this.menu = new Ext.menu.Menu(config.menuConfig); - this.config = config; - this._loadColumnModel(); + confirm: function(type, text) { + const + p = { action: type }, + k = this.config.primaryKey || 'id' + ; + p[k] = this.menu.record[k]; - if (config.showActionsColumn && config.columns && Array.isArray(config.columns)) { - config.columns.push({ - width: config.actionsColumnWidth || 50 - ,menuDisabled: true - ,renderer: { - fn: this.actionsColumnRenderer, - scope: this + MODx.msg.confirm({ + title: _(type), + text: _(text) || _('confirm_remove'), + url: this.config.url, + params: p, + listeners: { + success: { fn: this.refresh, scope: this } } }); - } - - MODx.grid.LocalGrid.superclass.constructor.call(this,config); - this.addEvents({ - beforeRemoveRow: true, - afterRemoveRow: true - }); - this.on('rowcontextmenu',this._showMenu,this); -}; + }, -Ext.extend(MODx.grid.LocalGrid,Ext.grid.EditorGridPanel,{ - windows: {} + remove: function(text, action) { + if (this.destroying) { + return MODx.grid.Grid.superclass.remove.apply(this, arguments); + } + const + { record } = this.menu, + saveParams = this.config.saveParams || {}, + primaryKey = this.config.primaryKey || 'id' + ; + text = text || 'confirm_remove'; + Ext.apply(saveParams, { action: action || 'remove' }); + saveParams[primaryKey] = record[primaryKey]; - ,_loadStore: function(config) { - if (config.grouping) { - this.store = new Ext.data.GroupingStore({ - data: config.data || [] - ,reader: new Ext.data.ArrayReader({},config.fields || []) - ,sortInfo: config.sortInfo || { - field: config.sortBy || 'name' - ,direction: config.sortDir || 'ASC' + if (this.fireEvent('beforeRemoveRow', record)) { + MODx.msg.confirm({ + title: _('warning'), + text: _(text, record), + url: this.config.url, + params: saveParams, + listeners: { + success: { + fn: function() { + this.removeActiveRow(record); + }, + scope: this + } } - ,groupField: config.groupBy || 'name' }); - } else { - this.store = new Ext.data.SimpleStore({ - fields: config.fields - ,data: config.data || [] - }) } - return this.store; - } + }, - ,loadWindow: function(btn,e,win,or) { - var r = this.menu.record; - if (!this.windows[win.xtype]) { - Ext.applyIf(win,{ - scope: this - ,success: this.refresh - ,record: win.blankValues ? {} : r - }); - if (or) { - Ext.apply(win,or); + removeActiveRow: function(record) { + if (this.fireEvent('afterRemoveRow', record)) { + const selection = this.getSelectionModel().getSelected(); + this.getStore().remove(selection); + } + }, + + refresh: function() { + this.getStore().reload(); + }, + + // -*-*-* EVENT HANDLERS *-*-*- + + onClickHandler: function(e) { + const target = e.getTarget(); + if (!target.classList.contains('x-grid-action')) { + return; + } + if (!target.dataset.action) { + return; + } + let actionHandler = `action${target.dataset.action.charAt(0).toUpperCase()}${target.dataset.action.slice(1)}`; + + if (!this[actionHandler] || (typeof this[actionHandler] !== 'function')) { + actionHandler = target.dataset.action; + if (!this[actionHandler] || (typeof this[actionHandler] !== 'function')) { + return; } - this.windows[win.xtype] = Ext.ComponentMgr.create(win); } - if (this.windows[win.xtype].setValues && win.blankValues !== true && r != undefined) { - this.windows[win.xtype].setValues(r); + const + record = this.getSelectionModel().getSelected(), + recordIndex = this.store.indexOf(record) + ; + this.menu.record = record.data; + this[actionHandler](record, recordIndex, e); + }, + + onChangePerPage: function(field, newValue) { + if (Ext.isEmpty(newValue)) { + return false; } - this.windows[win.xtype].show(e.target); + newValue = parseInt(newValue, 10); + this.getBottomToolbar().pageSize = newValue; + this.store.load({ + params: { + start: 0, + limit: newValue + } + }); } - ,_loadColumnModel: function() { - if (this.config.columns) { - var c = this.config.columns; - for (var i=0;i${responseStatusCode} ${responseStatusText}
    ` : ''; + } else { + // When php display_error is on OR the error is caught and explicity sent from the MODx class triggering the error, responseText should contain error text or possibly an object containing message text + try { + const responseText = Ext.decode(response.responseText); + // In what scenario will responseText be an object with a message property? + if (responseText && responseText.message) { + output = responseText.message; } + } catch (e) { + output = response.responseText; } - this.cm = new Ext.grid.ColumnModel(c); } - } + if (output) { + if (MODx.config.debug > 0) { + output = MODx.util.safeHtml(output, '
    ', 'class,colspan,rowspan'); + msg = _('error_grid_get_content_toscreen', { + message: `
    ${output}
    ` + }); + } else { + msg = _('error_grid_get_content_tolog'); + output = Ext.util.Format.stripTags(output).replaceAll('>', '>').replaceAll('<', '<'); + console.error(output); + } + } else { + // With some scenarios, such as when php display_errors = 1 and MODx system setting debug = 0 (reporting off), the reponseText will be empty and the status will be 200 + msg = _('error_grid_get_content_no_msg'); + } + this.getView().emptyText = `
    ${msg}
    `; + this.getView().refresh(false); + }, - ,renderEditableColumn: function(renderer) { - return function(value, metaData, record, rowIndex, colIndex, store) { - if (renderer) { - if (typeof renderer.fn === 'function') { - var scope = (renderer.scope) ? renderer.scope : false; - renderer = renderer.fn.bind(scope); + /** + * Executes auto save of the row after edits are complete and optional success callback + * @param {Ext.Event} e Extended event data including: + * * column + * * row + * * field (name) + * * grid (full grid object) + * * record (full Ext record object including store, data, json, etc.) + * * originalValue + * * value (current) + */ + saveRecord: function(e) { + e.record.data.menu = null; + const p = this.config.saveParams || {}; + Ext.apply(e.record.data, p); + const + data = Ext.util.JSON.encode(e.record.data), + url = this.config.saveUrl || (this.config.url || this.config.connector) + ; + MODx.Ajax.request({ + url: url, + params: { + action: this.config.save_action || 'updateFromGrid', + data: data + }, + listeners: { + success: { + fn: function(response) { + if (this.config.save_callback) { + Ext.callback(this.config.save_callback, this.config.scope || this, [response]); + } + e.record.commit(); + if (!this.config.preventSaveRefresh) { + const gridRefresh = new Ext.util.DelayedTask(() => this.refresh()); + gridRefresh.delay(200); + } + const + /** @var {Object} eventData Plucking only the needed event props to forward in the post-save event */ + eventData = { field: e.field, originalValue: e.originalValue, value: e.value }, + responseData = { ...response, eventData } + ; + this.fireEvent('afterAutoSave', responseData); + }, + scope: this + }, + failure: { + fn: function(response) { + e.record.reject(); + this.fireEvent('afterAutoSave', response); + }, + scope: this } + } + }); + }, - if (typeof renderer === 'function') { - value = renderer(value, metaData, record, rowIndex, colIndex, store); - } + /** + * Method executed after a record has been edited/saved inline from within the grid + * + * @param {Object} response - The processor save response object. See modConnectorResponse::outputContent (PHP) + */ + onAfterAutoSave: function(response) { + if (!response.success && response.message === '') { + let msg = ''; + if (response.data.length) { + // We get some data for specific field(s) error but not regular error message + Ext.each(response.data, function(data, index, list) { + msg += (msg !== '' ? '
    ' : '') + data.msg; + }, this); } - metaData.css = ['x-editable-column', metaData.css || ''].join(' '); - - return value; + if (Ext.isEmpty(msg)) { + // Still no valid message so far, let's use some fallback + msg = this.autosaveErrorMsg || _('error'); + } + MODx.msg.alert(_('error'), msg); } - } + }, - ,_showMenu: function(g,ri,e) { - e.stopEvent(); - e.preventDefault(); - this.menu.recordIndex = ri; - this.menu.record = this.getStore().getAt(ri).data; - if (!this.getSelectionModel().isSelected(ri)) { - this.getSelectionModel().selectRow(ri); - } - this.menu.removeAll(); - var m = this.getMenu(g,ri); - if (m) { - this.addContextMenuItem(m); - this.menu.showAt(e.xy); + encodeModified: function() { + const p = this.getStore().getModifiedRecords(), + rs = {} + ; + for (let i = 0; i < p.length; i++) { + rs[p[i].data[this.config.primaryKey || 'id']] = p[i].data; } - } - - ,getMenu: function() { - return this.menu.record.menu; - } - - ,addContextMenuItem: function(items) { - var l = items.length; - for(var i = 0; i < l; i++) { - var options = items[i]; + return Ext.encode(rs); + }, - if (options == '-') { - this.menu.add('-'); - continue; + makeUrl: function() { + if (Array.isArray(this.config.urlFilters) && this.config.urlFilters.length > 0) { + const s = this.getStore(), + p = { + a: MODx.request.a + }; + if (MODx.request.id) { + p.id = MODx.request.id; } - var h = Ext.emptyFn; - if (options.handler) { - h = eval(options.handler); - if (h && typeof(h) == 'object' && h.xtype) { - h = this.loadWindow.createDelegate(this,[h],true); - } - } else { - h = function(itm) { - var o = itm.options; - var id = this.menu.record.id; - var w = Ext.get('modx_content'); - if (o.confirm) { - Ext.Msg.confirm('',o.confirm,function(e) { - if (e == 'yes') { - var a = Ext.urlEncode(o.params || {action: o.action}); - var s = '?id='+id+'&'+a; - if (w === null) { - location.href = s; - } else { w.dom.src = s; } - } - },this); + if (MODx.request.key) { + p.key = MODx.request.key; + } + for (let i = 0; i < this.config.urlFilters.length; ++i) { + if (Object.hasOwn(s.baseParams, this.config.urlFilters[i]) && s.baseParams[this.config.urlFilters[i]]) { + if (this.config.urlFilters[i] === 'namespace') { + p.ns = s.baseParams[this.config.urlFilters[i]]; } else { - var a = Ext.urlEncode(o.params || {action: o.action}); - var s = '?id='+id+'&'+a; - if (w === null) { - location.href = s; - } else { w.dom.src = s; } + p[this.config.urlFilters[i]] = s.baseParams[this.config.urlFilters[i]]; } - }; - } - this.menu.add({ - id: options.id || Ext.id() - ,text: options.text - ,scope: this - ,options: options - ,handler: h - }); - } - } - - - ,remove: function(config) { - if (this.destroying) { - return MODx.grid.LocalGrid.superclass.remove.apply(this, arguments); - } - var r = this.getSelectionModel().getSelected(); - if (this.fireEvent('beforeRemoveRow',r)) { - Ext.Msg.confirm(config.title || '',config.text || '',function(e) { - if (e == 'yes') { - this.getStore().remove(r); - this.fireEvent('afterRemoveRow',r); } - },this); - } - } - - ,encode: function() { - var s = this.getStore(); - var ct = s.getCount(); - var rs = this.config.encodeByPk ? {} : []; - var r; - for (var j=0;j 0 + ) { + window.history.replaceState(this.getStore().baseParams, document.title, this.makeUrl()); } - - return true; - } + }, /** - * Returns first found expander plugin - * @param plugins + * Builds the standard "Creator" column model object. This column displays for + * objects that have built-in system values as well as values installed/entered + * by Extras and/or Users + * @param {String} objectType Identifier for object being worked with + * @returns {Object} The configuration for the "Creator" column */ - ,findExpanderPlugin: function (plugins) { - - if (Ext.isObject(plugins)) { - plugins = [plugins]; - } - - var index = Ext.each(plugins, function (item) { - if (item.id !== undefined && item.id === 'expander') { - return false; - } - }); - - return plugins[index]; - } + getCreatorColumnConfig: function(objectType) { + return { + header: _('grid_column_creator_header'), + dataIndex: 'creator', + id: `modx-${objectType}--creator`, + width: 70, + align: 'center', + tooltip: _('grid_column_creator_description'), + menuDisabled: true + }; + }, - ,rendYesNo: function(d,c) { - switch(d) { - case '': - return '-'; - case false: - c.css = 'red'; - return _('no'); - case true: - c.css = 'green'; - return _('yes'); + /** + * Get the request value for a grid's category filtering. Derives whether the category param is to be applied to a + * grid and its category filter based on the existence of the tab param in the GET request. Needed where the same + * category processor is used for different purposes within the same editing panel (notably the Template and TV panels). + */ + getCategoryFilterValue: () => { + if (typeof MODx.request.tab === 'undefined' || typeof MODx.request.category === 'undefined') { + return null; } + return Math.abs(parseInt(MODx.request.category, 10)); } +}); - ,rendPassword: function(v) { - var z = ''; - for (var i=0;i' - + '' - + '
      ' - + '' - + '
    • ' - + '
      ' - + '
    ' - + '
    ' - + '', { - compiled: true - }); - } + }); + MODx.grid.LocalGrid.superclass.constructor.call(this, config); +}; - ,actionsColumnRenderer: function(value, metaData, record, rowIndex, colIndex, store) { - var actions = this.getActions.apply(this, arguments); +Ext.extend(MODx.grid.LocalGrid, MODx.grid.GridBase, { - if (this.config.disableContextMenuAction !== true) { - actions.push({ - text: _('context_menu'), - action: 'contextMenu', - icon: 'gear' + _loadStore: function() { + if (this.config.grouping) { + this.store = new Ext.data.GroupingStore({ + data: this.config.data || [], + reader: new Ext.data.ArrayReader({}, this.config.fields || []), + sortInfo: this.config.sortInfo || { + field: this.config.sortBy || 'name', + direction: this.config.sortDir || 'ASC' + }, + groupField: this.config.groupBy || 'name' + }); + } else { + this.store = new Ext.data.SimpleStore({ + fields: this.config.fields, + data: this.config.data || [] }); } + return this.store; + }, - return this._getActionsColumnTpl().apply({ - actions: actions - }); - } - - ,renderLink: function(v,attr) { - var el = new Ext.Element(document.createElement('a')); - el.addClass('x-grid-link'); - el.dom.title = _('edit'); - for (var i in attr) { - el.dom[i] = attr[i]; + /** + * @override + */ + remove: function(config) { + if (this.destroying) { + return MODx.grid.LocalGrid.superclass.remove.apply(this, arguments); } - el.dom.innerHTML = Ext.util.Format.htmlEncode(v); - return el.dom.outerHTML; - } - - ,getActions: function(value, metaData, record, rowIndex, colIndex, store) { - return []; - } - - ,onClick: function(e) { - var target = e.getTarget(); - if (!target.classList.contains('x-grid-action')) return; - if (!target.dataset.action) return; + const r = this.getSelectionModel().getSelected(); + if (this.fireEvent('beforeRemoveRow', r)) { + Ext.Msg.confirm(config.title || '', config.text || '', function(e) { + if (e === 'yes') { + this.getStore().remove(r); + this.fireEvent('afterRemoveRow', r); + } + }, this); + } + }, - var actionHandler = 'action' + target.dataset.action.charAt(0).toUpperCase() + target.dataset.action.slice(1); - if (!this[actionHandler] || (typeof this[actionHandler] !== 'function')) { - actionHandler = target.dataset.action; - if (!this[actionHandler] || (typeof this[actionHandler] !== 'function')) { - return; + /** + * @override + * @todo Implement encodeURIComponent to fix issues with passing particluar + * chars via URL (e.g., # [pound/hash] used in color values, etc.) + */ + encode: function() { + const s = this.getStore(), + ct = s.getCount(), + rs = this.config.encodeByPk ? {} : []; + let r; + for (let j = 0; j < ct; j++) { + r = s.getAt(j).data; + r.menu = null; + r.permissions = null; + if (this.config.encodeAssoc) { + rs[r[this.config.encodeByPk || 'id']] = r; + } else { + rs.push(r); } } - var record = this.getSelectionModel().getSelected(); - var recordIndex = this.store.indexOf(record); - this.menu.record = record.data; - - this[actionHandler](record, recordIndex, e); - }, - - actionContextMenu: function(record, recordIndex, e) { - this._showMenu(this, recordIndex, e); + return Ext.encode(rs); } }); -Ext.reg('grid-local',MODx.grid.LocalGrid); -Ext.reg('modx-grid-local',MODx.grid.LocalGrid); +Ext.reg('grid-local', MODx.grid.LocalGrid); +Ext.reg('modx-grid-local', MODx.grid.LocalGrid); /* grid extensions */ /*! @@ -1779,26 +2075,26 @@ Ext.ux.grid.RowExpander = Ext.extend(Ext.util.Observable, { * true to toggle selected row(s) between expanded/collapsed when the enter * key is pressed (defaults to true). */ - expandOnEnter : true, + expandOnEnter: true, /** * @cfg {Boolean} expandOnDblClick * true to toggle a row between expanded/collapsed when double clicked * (defaults to true). */ - expandOnDblClick : true, + expandOnDblClick: true, - header : '', - width : 20, - sortable : false, - fixed : true, + header: '', + width: 25, + sortable: false, + fixed: true, hideable: false, - menuDisabled : true, - dataIndex : '', - id : 'expander', - lazyRender : true, - enableCaching : true, + menuDisabled: true, + dataIndex: '', + id: 'expander', + lazyRender: true, + enableCaching: true, - constructor: function(config){ + constructor: function(config) { Ext.apply(this, config); this.addEvents({ @@ -1842,8 +2138,8 @@ Ext.ux.grid.RowExpander = Ext.extend(Ext.util.Observable, { Ext.ux.grid.RowExpander.superclass.constructor.call(this); - if(this.tpl){ - if(typeof this.tpl == 'string'){ + if (this.tpl) { + if (typeof this.tpl == 'string') { this.tpl = new Ext.Template(this.tpl); } this.tpl.compile(); @@ -1853,39 +2149,40 @@ Ext.ux.grid.RowExpander = Ext.extend(Ext.util.Observable, { this.bodyContent = {}; }, - getRowClass : function(record, rowIndex, p, ds){ - p.cols = p.cols-1; - var content = this.bodyContent[record.id]; - if(!content && !this.lazyRender){ + getRowClass: function(record, rowIndex, p, ds) { + p.cols -= 1; + let content = this.bodyContent[record.id]; + if (!content && !this.lazyRender) { content = this.getBodyContent(record, rowIndex); } - if(content){ + if (content) { p.body = content; } return this.state[record.id] ? 'x-grid3-row-expanded' : 'x-grid3-row-collapsed'; }, - init : function(grid){ + init: function(grid) { this.grid = grid; - var view = grid.getView(); + const view = grid.getView(); view.getRowClass = this.getRowClass.createDelegate(this); view.enableRowBody = true; - grid.on('render', this.onRender, this); grid.on('destroy', this.onDestroy, this); }, // @private onRender: function() { - var grid = this.grid; - var mainBody = grid.getView().mainBody; - mainBody.on('mousedown', this.onMouseDown, this, {delegate: '.x-grid3-row-expander'}); + const + { grid } = this, + { mainBody } = grid.getView() + ; + mainBody.on('mousedown', this.onMouseDown, this, { delegate: '.x-grid3-row-expander' }); if (this.expandOnEnter) { this.keyNav = new Ext.KeyNav(this.grid.getGridEl(), { - 'enter' : this.onEnter, + enter: this.onEnter, scope: this }); } @@ -1896,7 +2193,7 @@ Ext.ux.grid.RowExpander = Ext.extend(Ext.util.Observable, { // @private onDestroy: function() { - if(this.keyNav){ + if (this.keyNav) { this.keyNav.disable(); delete this.keyNav; } @@ -1905,8 +2202,8 @@ Ext.ux.grid.RowExpander = Ext.extend(Ext.util.Observable, { * which means the mainBody won't be available. On the off chance that the plugin * isn't destroyed with the grid, take care of removing the listener. */ - var mainBody = this.grid.getView().mainBody; - if(mainBody){ + const { mainBody } = this.grid.getView(); + if (mainBody) { mainBody.un('mousedown', this.onMouseDown, this); } }, @@ -1916,76 +2213,75 @@ Ext.ux.grid.RowExpander = Ext.extend(Ext.util.Observable, { }, onEnter: function(e) { - var g = this.grid; - var sm = g.getSelectionModel(); - var sels = sm.getSelections(); - for (var i = 0, len = sels.length; i < len; i++) { - var rowIdx = g.getStore().indexOf(sels[i]); + const g = this.grid, + sm = g.getSelectionModel(), + sels = sm.getSelections(); + for (let i = 0, len = sels.length; i < len; i++) { + const rowIdx = g.getStore().indexOf(sels[i]); this.toggleRow(rowIdx); } }, - getBodyContent : function(record, index){ - if(!this.enableCaching){ + getBodyContent: function(record, index) { + if (!this.enableCaching) { return this.tpl.apply(record.data); } - var content = this.bodyContent[record.id]; - if(!content){ + let content = this.bodyContent[record.id]; + if (!content) { content = this.tpl.apply(record.data); this.bodyContent[record.id] = content; } return content; }, - onMouseDown : function(e, t){ + onMouseDown: function(e, t) { e.stopEvent(); - var row = e.getTarget('.x-grid3-row'); + const row = e.getTarget('.x-grid3-row'); this.toggleRow(row); }, - renderer : function(v, p, record){ + renderer: function(v, p, record) { p.cellAttr = 'rowspan="2"'; return '
     
    '; }, - beforeExpand : function(record, body, rowIndex){ - if(this.fireEvent('beforeexpand', this, record, body, rowIndex) !== false){ - if(this.tpl && this.lazyRender){ + beforeExpand: function(record, body, rowIndex) { + if (this.fireEvent('beforeexpand', this, record, body, rowIndex) !== false) { + if (this.tpl && this.lazyRender) { body.innerHTML = this.getBodyContent(record, rowIndex); } return true; - }else{ - return false; } + return false; }, - toggleRow : function(row){ - if(typeof row == 'number'){ + toggleRow: function(row) { + if (typeof row == 'number') { row = this.grid.view.getRow(row); } this[Ext.fly(row).hasClass('x-grid3-row-collapsed') ? 'expandRow' : 'collapseRow'](row); }, - expandRow : function(row){ - if(typeof row == 'number'){ + expandRow: function(row) { + if (typeof row == 'number') { row = this.grid.view.getRow(row); } - var record = this.grid.store.getAt(row.rowIndex); - var body = Ext.DomQuery.selectNode('tr:nth(2) div.x-grid3-row-body', row); - if(this.beforeExpand(record, body, row.rowIndex)){ + const record = this.grid.store.getAt(row.rowIndex), + body = Ext.DomQuery.selectNode('tr:nth(2) div.x-grid3-row-body', row); + if (this.beforeExpand(record, body, row.rowIndex)) { this.state[record.id] = true; Ext.fly(row).replaceClass('x-grid3-row-collapsed', 'x-grid3-row-expanded'); this.fireEvent('expand', this, record, body, row.rowIndex); } }, - collapseRow : function(row){ - if(typeof row == 'number'){ + collapseRow: function(row) { + if (typeof row == 'number') { row = this.grid.view.getRow(row); } - var record = this.grid.store.getAt(row.rowIndex); - var body = Ext.fly(row).child('tr:nth(1) div.x-grid3-row-body', true); - if(this.fireEvent('beforecollapse', this, record, body, row.rowIndex) !== false){ + const record = this.grid.store.getAt(row.rowIndex), + body = Ext.fly(row).child('tr:nth(1) div.x-grid3-row-body', true); + if (this.fireEvent('beforecollapse', this, record, body, row.rowIndex) !== false) { this.state[record.id] = false; Ext.fly(row).replaceClass('x-grid3-row-expanded', 'x-grid3-row-collapsed'); this.fireEvent('collapse', this, record, body, row.rowIndex); @@ -1995,33 +2291,34 @@ Ext.ux.grid.RowExpander = Ext.extend(Ext.util.Observable, { Ext.preg('rowexpander', Ext.ux.grid.RowExpander); -//backwards compat +// backwards compat Ext.grid.RowExpander = Ext.ux.grid.RowExpander; Ext.ns('Ext.ux.grid'); -Ext.ux.grid.CheckColumn = function (a) { +Ext.ux.grid.CheckColumn = function(a) { Ext.apply(this, a); if (!this.id) { - this.id = Ext.id() + this.id = Ext.id(); } - this.renderer = this.renderer.createDelegate(this) + this.renderer = this.renderer.createDelegate(this); }; Ext.ux.grid.CheckColumn.prototype = { - init: function (b) { + init: function(b) { this.grid = b; - this.grid.on('render', function () { - var a = this.grid.getView(); - a.mainBody.on('mousedown', this.onMouseDown, this) + this.grid.on('render', function() { + const a = this.grid.getView(); + a.mainBody.on('mousedown', this.onMouseDown, this); }, this); - this.grid.on('destroy', this.onDestroy, this) - }, onMouseDown: function (e, t) { + this.grid.on('destroy', this.onDestroy, this); + }, + onMouseDown: function(e, t) { this.grid.fireEvent('rowclick'); - if (t.className && t.className.indexOf('x-grid3-cc-' + this.id) != -1) { + if (t.className && t.className.indexOf(`x-grid3-cc-${this.id}`) !== -1) { e.stopEvent(); - var a = this.grid.getView().findRowIndex(t); - var b = this.grid.store.getAt(a); - var sv = b.data[this.dataIndex]; + const a = this.grid.getView().findRowIndex(t), + b = this.grid.store.getAt(a), + sv = b.data[this.dataIndex]; b.set(this.dataIndex, !sv); this.grid.fireEvent('afteredit', { grid: this.grid, @@ -2032,11 +2329,13 @@ Ext.ux.grid.CheckColumn.prototype = { cancel: false }); } - }, renderer: function (v, p, a) { + }, + renderer: function(v, p, a) { p.css += ' x-grid3-check-col-td'; - return '
     
    ' - }, onDestroy: function () { - var mainBody = this.grid.getView().mainBody; + return `
     
    `; + }, + onDestroy: function() { + const { mainBody } = this.grid.getView(); if (mainBody) { mainBody.un('mousedown', this.onMouseDown, this); } @@ -2045,7 +2344,115 @@ Ext.ux.grid.CheckColumn.prototype = { Ext.preg('checkcolumn', Ext.ux.grid.CheckColumn); Ext.grid.CheckColumn = Ext.ux.grid.CheckColumn; -Ext.grid.PropertyColumnModel=function(a,b){var g=Ext.grid,f=Ext.form;this.grid=a;g.PropertyColumnModel.superclass.constructor.call(this,[{header:this.nameText,width:50,sortable:true,dataIndex:'name',id:'name',menuDisabled:true},{header:this.valueText,width:50,resizable:false,dataIndex:'value',id:'value',menuDisabled:true}]);this.store=b;var c=new f.Field({autoCreate:{tag:'select',children:[{tag:'option',value:'true',html:'true'},{tag:'option',value:'false',html:'false'}]},getValue:function(){return this.el.dom.value=='true'}});this.editors={'date':new g.GridEditor(new f.DateField({selectOnFocus:true})),'string':new g.GridEditor(new f.TextField({selectOnFocus:true})),'number':new g.GridEditor(new f.NumberField({selectOnFocus:true,style:'text-align:left;'})),'boolean':new g.GridEditor(c)};this.renderCellDelegate=this.renderCell.createDelegate(this);this.renderPropDelegate=this.renderProp.createDelegate(this)};Ext.extend(Ext.grid.PropertyColumnModel,Ext.grid.ColumnModel,{nameText:'Name',valueText:'Value',dateFormat:'m/j/Y',renderDate:function(a){return a.dateFormat(this.dateFormat)},renderBool:function(a){return a?'true':'false'},isCellEditable:function(a,b){return a==1},getRenderer:function(a){return a==1?this.renderCellDelegate:this.renderPropDelegate},renderProp:function(v){return this.getPropertyName(v)},renderCell:function(a){var b=a;if(Ext.isDate(a)){b=this.renderDate(a)}else if(typeof a=='boolean'){b=this.renderBool(a)}return Ext.util.Format.htmlEncode(b)},getPropertyName:function(a){var b=this.grid.propertyNames;return b&&b[a]?b[a]:a},getCellEditor:function(a,b){var p=this.store.getProperty(b),n=p.data.name,val=p.data.value;if(this.grid.customEditors[n]){return this.grid.customEditors[n]}if(Ext.isDate(val)){return this.editors.date}else if(typeof val=='number'){return this.editors.number}else if(typeof val=='boolean'){return this.editors['boolean']}else{return this.editors.string}},destroy:function(){Ext.grid.PropertyColumnModel.superclass.destroy.call(this);for(var a in this.editors){Ext.destroy(a)}}}); +Ext.grid.PropertyColumnModel = function(a, b) { + const + g = Ext.grid, + f = Ext.form + ; + this.grid = a; + g.PropertyColumnModel.superclass.constructor.call(this, [ + { + header: this.nameText, + width: 50, + sortable: true, + dataIndex: 'name', + id: 'name', + menuDisabled: true + }, + { + header: this.valueText, + width: 50, + resizable: false, + dataIndex: 'value', + id: 'value', + menuDisabled: true + } + ]); + this.store = b; + const c = new f.Field({ + autoCreate: { + tag: 'select', + children: [ + { tag: 'option', value: 'true', html: 'true' }, + { tag: 'option', value: 'false', html: 'false' } + ] + }, + getValue: function() { + // eslint-disable-next-line eqeqeq + return this.el.dom.value == 'true'; + } + }); + this.editors = { + date: new g.GridEditor(new f.DateField({ selectOnFocus: true })), + string: new g.GridEditor(new f.TextField({ selectOnFocus: true })), + number: new g.GridEditor(new f.NumberField({ selectOnFocus: true, style: 'text-align:left;' })), + boolean: new g.GridEditor(c) + }; + this.renderCellDelegate = this.renderCell.createDelegate(this); + this.renderPropDelegate = this.renderProp.createDelegate(this); +}; +Ext.extend(Ext.grid.PropertyColumnModel, Ext.grid.ColumnModel, { + nameText: 'Name', + valueText: 'Value', + dateFormat: 'm/j/Y', + renderDate: function(a) { + return a.dateFormat(this.dateFormat); + }, + renderBool: function(a) { + return a ? 'true' : 'false'; + }, + isCellEditable: function(a, b) { + // eslint-disable-next-line eqeqeq + return a == 1; + }, + getRenderer: function(a) { + // eslint-disable-next-line eqeqeq + return a == 1 ? this.renderCellDelegate : this.renderPropDelegate; + }, + renderProp: function(v) { + return this.getPropertyName(v); + }, + renderCell: function(a) { + let b = a; + if (Ext.isDate(a)) { + b = this.renderDate(a); + } else if (typeof a == 'boolean') { + b = this.renderBool(a); + } + return Ext.util.Format.htmlEncode(b); + }, + getPropertyName: function(a) { + const b = this.grid.propertyNames; + return b && b[a] ? b[a] : a; + }, + getCellEditor: function(a, b) { + const + p = this.store.getProperty(b), + n = p.data.name, + val = p.data.value + ; + if (this.grid.customEditors[n]) { + return this.grid.customEditors[n]; + } + if (Ext.isDate(val)) { + return this.editors.date; + } + if (typeof val == 'number') { + return this.editors.number; + } + if (typeof val == 'boolean') { + return this.editors.boolean; + } + return this.editors.string; + }, + destroy: function() { + Ext.grid.PropertyColumnModel.superclass.destroy.call(this); + // eslint-disable-next-line guard-for-in, no-restricted-syntax + for (const a in this.editors) { + Ext.destroy(a); + } + } +}); /** * MODx JSON Grid @@ -2066,18 +2473,17 @@ Ext.grid.PropertyColumnModel=function(a,b){var g=Ext.grid,f=Ext.form;this.grid=a * * [{name: 'key'}, {name: 'value'}] */ -MODx.grid.JsonGrid = function (config) { - config = config || {}; - this.ident = config.ident || 'jsongrid-mecitem' + Ext.id(); +MODx.grid.JsonGrid = function(config = {}) { + this.ident = config.ident || `jsongrid-mecitem${Ext.id()}`; this.hiddenField = new Ext.form.TextArea({ name: config.hiddenName || config.name, hidden: true }); - this.fieldConfig = config.fieldConfig || [{name: 'key'}, {name: 'value'}]; - this.fieldConfig.push({name: 'id', hidden: true}); + this.fieldConfig = config.fieldConfig || [{ name: 'key' }, { name: 'value' }]; + this.fieldConfig.push({ name: 'id', hidden: true }); this.fieldColumns = []; this.fieldNames = []; - Ext.each(this.fieldConfig, function (el) { + Ext.each(this.fieldConfig, function(el) { this.fieldNames.push(el.name); this.fieldColumns.push({ header: el.header || _(el.name), @@ -2096,8 +2502,8 @@ MODx.grid.JsonGrid = function (config) { scope: this }, keyup: { - fn: function (sb) { - var record = this.getSelectionModel().getSelected(); + fn: function(sb) { + const record = this.getSelectionModel().getSelected(); if (record) { record.set(sb.fieldname, sb.el.dom.value); this.saveValue(); @@ -2115,7 +2521,7 @@ MODx.grid.JsonGrid = function (config) { }); }, this); Ext.applyIf(config, { - id: this.ident + '-json-grid', + id: `${this.ident}-json-grid`, fields: this.fieldNames, autoHeight: true, store: new Ext.data.JsonStore({ @@ -2123,12 +2529,12 @@ MODx.grid.JsonGrid = function (config) { data: this.loadValue(config.value) }), enableDragDrop: true, - ddGroup: this.ident + '-json-grid-dd', + ddGroup: `${this.ident}-json-grid-dd`, labelStyle: 'position: absolute', columns: this.fieldColumns, disableContextMenuAction: true, tbar: ['->', { - text: ' ' + _('add'), + text: ` ${_('add')}`, cls: 'primary-button', handler: this.addElement, scope: this @@ -2140,50 +2546,59 @@ MODx.grid.JsonGrid = function (config) { } } }); - MODx.grid.JsonGrid.superclass.constructor.call(this, config) + MODx.grid.JsonGrid.superclass.constructor.call(this, config); }; Ext.extend(MODx.grid.JsonGrid, MODx.grid.LocalGrid, { - getMenu: function () { - var m = []; - m.push({ + getMenu: function() { + const menu = []; + menu.push({ text: _('remove'), handler: this.removeElement }); - return m; + return menu; }, - getActions: function () { + + /** + * @override + */ + getActions: function() { return [{ action: 'removeElement', icon: 'trash-o', text: _('remove') - }] + }]; }, - addElement: function () { - var ds = this.getStore(); - var row = {}; - Ext.each(this.fieldNames, function (fieldname) { + + addElement: function() { + const ds = this.getStore(), + row = {}; + Ext.each(this.fieldNames, function(fieldname) { row[fieldname] = ''; }); - row['id'] = this.getStore().getCount(); + row.id = this.getStore().getCount(); + // eslint-disable-next-line new-cap this.getStore().insert(this.getStore().getCount(), new ds.recordType(row)); this.getView().refresh(); this.getSelectionModel().selectRow(0); }, - removeElement: function () { - Ext.Msg.confirm(_('remove') || '', _('confirm_remove') || '', function (e) { + + removeElement: function() { + Ext.Msg.confirm(_('remove') || '', _('confirm_remove') || '', function(e) { if (e === 'yes') { - var ds = this.getStore(); - var rows = this.getSelectionModel().getSelections(); + const ds = this.getStore(), + rows = this.getSelectionModel().getSelections(); if (!rows.length) { return false; } - for (var i = 0; i < rows.length; i++) { - var id = rows[i].id; - var index = ds.findBy(function (record) { - if (record.id === id) { - return true; - } - }); + for (let i = 0; i < rows.length; i++) { + const + { id } = rows[i], + index = ds.findBy(function(record) { + if (record.id === id) { + return true; + } + }) + ; ds.removeAt(index); } this.getView().refresh(); @@ -2191,20 +2606,22 @@ Ext.extend(MODx.grid.JsonGrid, MODx.grid.LocalGrid, { } }, this); }, - renderListener: function (grid) { + + renderListener: function(grid) { + // eslint-disable-next-line no-new new Ext.dd.DropTarget(grid.container, { copy: false, - ddGroup: this.ident + '-json-grid-dd', - notifyDrop: function (dd, e, data) { - var ds = grid.store; - var sm = grid.getSelectionModel(); - var rows = sm.getSelections(); + ddGroup: `${this.ident}-json-grid-dd`, + notifyDrop: function(dd, e, data) { + const ds = grid.store, + sm = grid.getSelectionModel(), + rows = sm.getSelections(), - var dragData = dd.getDragData(e); + dragData = dd.getDragData(e); if (dragData) { - var cindex = dragData.rowIndex; - if (typeof (cindex) !== "undefined") { - for (var i = 0; i < rows.length; i++) { + const cindex = dragData.rowIndex; + if (typeof (cindex) !== 'undefined') { + for (let i = 0; i < rows.length; i++) { ds.remove(ds.getById(rows[i].id)); } ds.insert(cindex, data.selections); @@ -2218,22 +2635,24 @@ Ext.extend(MODx.grid.JsonGrid, MODx.grid.LocalGrid, { this.add(this.hiddenField); this.saveValue(); }, - loadValue: function (value) { + + loadValue: function(value) { value = Ext.util.JSON.decode(value); if (value && Array.isArray(value)) { - Ext.each(value, function (record, idx) { - value[idx]['id'] = idx; + Ext.each(value, function(record, idx) { + value[idx].id = idx; }); } else { value = []; } return value; }, - saveValue: function () { - var value = []; - Ext.each(this.getStore().getRange(), function (record) { - var row = {}; - Ext.each(this.fieldNames, function (fieldname) { + + saveValue: function() { + const value = []; + Ext.each(this.getStore().getRange(), function(record) { + const row = {}; + Ext.each(this.fieldNames, function(fieldname) { if (fieldname !== 'id') { row[fieldname] = record.data[fieldname]; } @@ -2241,43 +2660,6 @@ Ext.extend(MODx.grid.JsonGrid, MODx.grid.LocalGrid, { value.push(row); }, this); this.hiddenField.setValue(Ext.util.JSON.encode(value)); - }, - _getActionsColumnTpl: function () { - return new Ext.XTemplate('' - + '' - + '
      ' - + '' - + '
    • ' - + '
      ' - + '
    ' - + '
    ' - + '
    ', { - compiled: true - }); - }, - actionsColumnRenderer: function (value, metaData, record, rowIndex, colIndex, store) { - return this._getActionsColumnTpl().apply({ - actions: this.getActions() - }); - }, - onClick: function (e) { - var target = e.getTarget(); - if (!target.classList.contains('x-grid-action')) return; - if (!target.dataset.action) return; - - var actionHandler = 'action' + target.dataset.action.charAt(0).toUpperCase() + target.dataset.action.slice(1); - if (!this[actionHandler] || (typeof this[actionHandler] !== 'function')) { - actionHandler = target.dataset.action; - if (!this[actionHandler] || (typeof this[actionHandler] !== 'function')) { - return; - } - } - - var record = this.getSelectionModel().getSelected(); - var recordIndex = this.store.indexOf(record); - this.menu.record = record.data; - - this[actionHandler](record, recordIndex, e); } }); Ext.reg('grid-json', MODx.grid.JsonGrid); diff --git a/manager/assets/modext/widgets/core/modx.grid.local.property.js b/manager/assets/modext/widgets/core/modx.grid.local.property.js index 9b5b7a3235f..c06a7f61632 100644 --- a/manager/assets/modext/widgets/core/modx.grid.local.property.js +++ b/manager/assets/modext/widgets/core/modx.grid.local.property.js @@ -1,119 +1,142 @@ -MODx.grid.LocalProperty = function(config) { - config = config || {}; - Ext.applyIf(config,{ - dynProperty: 'xtype' - ,dynField: 'value' - ,propertyRecord: [{name: 'name'},{name: 'value'}] - ,data: [] +MODx.grid.LocalProperty = function(config = {}) { + Ext.applyIf(config, { + dynProperty: 'xtype', + dynField: 'value', + propertyRecord: [ + { name: 'name' }, + { name: 'value' } + ], + data: [] }); - MODx.grid.LocalProperty.superclass.constructor.call(this,config); + MODx.grid.LocalProperty.superclass.constructor.call(this, config); this.propRecord = Ext.data.Record.create(config.propertyRecord); }; -Ext.extend(MODx.grid.LocalProperty,MODx.grid.LocalGrid,{ - onCellDblClick: function(g,ri,ci,e) { - var cm = this.getColumnModel(); - if (cm.getColumnId(ci) == this.config.dynField) { +Ext.extend(MODx.grid.LocalProperty, MODx.grid.LocalGrid, { + onCellDblClick: function(grid, rowIndex, colIndex, e) { + const colModel = this.getColumnModel(); + if (colModel.getColumnId(colIndex) === this.config.dynField) { e.preventDefault(); - var r = this.getStore().getAt(ri).data; - this.initEditor(cm,ci,ri,r); - this.startEditing(ri,ci); + const record = this.getStore().getAt(rowIndex).data; + this.initEditor(colModel, colIndex, rowIndex, record); + this.startEditing(rowIndex, colIndex); } - } + }, - ,initEditor: function(cm,ci,ri,r) { - cm.setEditable(ci,true); - var xtype = this.config.dynProperty; - var o; - if (r[xtype] == 'list') { - o = this.createCombo(r); + initEditor: function(colModel, colIndex, rowIndex, record) { + colModel.setEditable(colIndex, true); + const fieldType = record[this.config.dynProperty]; + let fieldCmp; + if (fieldType === 'list') { + fieldCmp = this.createCombo(record); } else { - var z = {}; - z[xtype] = r[xtype] || 'textfield'; + const config = {}; + config[this.config.dynProperty] = fieldType || 'textfield'; try { - o = Ext.ComponentMgr.create(z); + fieldCmp = Ext.ComponentMgr.create(config); } catch (e) { - z[xtype] = 'textfield'; - o = MODx.load(z); + config[this.config.dynProperty] = 'textfield'; + fieldCmp = MODx.load(config); } } - var ed = new Ext.grid.GridEditor(o); - cm.setEditor(ci,ed); - return ed; - } + const editor = new Ext.grid.GridEditor(fieldCmp); + colModel.setEditor(colIndex, editor); + return editor; + }, + + renderDynField: function(value, metaData, record, rowIndex, colIndex, store, grid) { + const + { data } = record, + fieldType = data[this.config.dynProperty], + encodedValue = Ext.util.Format.htmlEncode(value), + rendererArgs = [encodedValue, metaData, record, rowIndex, colIndex, store, grid] + ; + let renderFn; + + metaData.css = this.setEditableCellClasses(record); - ,renderDynField: function(v,md,rec,ri,ci,s,g) { - var r = s.getAt(ri).data; - var f,idx; - var oz = v; - var xtype = this.config.dynProperty; - if (!r[xtype] || r[xtype] == 'combo-boolean') { - f = MODx.grid.Grid.prototype.rendYesNo; - return this.renderEditableColumn(f)(Ext.util.Format.htmlEncode(v),md,rec,ri,ci,s,g); - } else if (r[xtype] === 'datefield') { - f = Ext.util.Format.dateRenderer('Y-m-d'); - return this.renderEditableColumn(f)(Ext.util.Format.htmlEncode(v),md,rec,ri,ci,s,g); - } else if (r[xtype] === 'password') { - f = this.rendPassword; - return this.renderEditableColumn(f)(Ext.util.Format.htmlEncode(v),md,rec,ri,ci,s,g); - } else if (r[xtype].substr(0,5) == 'combo' || r[xtype] == 'list' || r[xtype].substr(0,9) == 'modx-combo') { - var cm = g.getColumnModel(); - var ed = cm.getCellEditor(ci,ri); - var cb; - if (!ed) { - r.xtype = r.xtype || 'combo-boolean'; - cb = this.createCombo(r); - ed = new Ext.grid.GridEditor(cb); - cm.setEditor(ci,ed); - } else if (ed && ed.field && ed.field.xtype == 'modx-combo') { - cb = ed.field; + if (!fieldType || fieldType === 'combo-boolean') { + renderFn = MODx.grid.Grid.prototype.rendYesNo; + return this.renderEditableColumn(renderFn)(...rendererArgs); + } + if (fieldType === 'datefield') { + renderFn = Ext.util.Format.dateRenderer('Y-m-d'); + return this.renderEditableColumn(renderFn)(...rendererArgs); + } + if (fieldType === 'password') { + renderFn = this.rendPassword; + return this.renderEditableColumn(renderFn)(...rendererArgs); + } + if (fieldType.includes('combo') || fieldType === 'list') { + const colModel = grid.getColumnModel(); + let + editor = colModel.getCellEditor(colIndex, rowIndex), + comboCmp + ; + if (!editor) { + data.xtype = data.xtype || 'combo-boolean'; + comboCmp = this.createCombo(data); + editor = new Ext.grid.GridEditor(comboCmp); + colModel.setEditor(colIndex, editor); + } else if (editor?.field?.xtype === 'modx-combo') { + comboCmp = editor.field; } - if (r[xtype] != 'list') { - f = Ext.util.Format.comboRenderer(ed.field); - return this.renderEditableColumn(f)(Ext.util.Format.htmlEncode(v),md,rec,ri,ci,s,g); - } else if (cb) { - idx = cb.getStore().find(cb.valueField,v); - rec = cb.getStore().getAt(idx); - if (rec) { - oz = rec.get(cb.displayField); - } else { - oz = v; + if (fieldType !== 'list') { + renderFn = Ext.util.Format.comboRenderer(editor.field); + return this.renderEditableColumn(renderFn)(...rendererArgs); + } + if (comboCmp) { + const + valueIndex = comboCmp.getStore().find(comboCmp.valueField, value), + comboRecord = comboCmp.getStore().getAt(valueIndex) + ; + if (comboRecord) { + const displayValue = comboRecord.get(comboCmp.displayField); + // override args in upper scope with this combo's value and record + rendererArgs[0] = Ext.util.Format.htmlEncode(displayValue); + rendererArgs[2] = comboRecord; } } } + return this.renderEditableColumn()(...rendererArgs); + }, - return this.renderEditableColumn()(Ext.util.Format.htmlEncode(oz),md,rec,ri,ci,s,g); - } - - ,createCombo: function(p) { - var obj; + createCombo: function(record) { + let combo; try { - obj = Ext.ComponentMgr.create({ xtype: r.xtype, id: Ext.id() }); - } catch(e) { + combo = Ext.ComponentMgr.create({ + xtype: record.xtype, + id: Ext.id() + }); + } catch (e) { try { - var flds = p.options; - var data = []; - for (var i=0;i data.push([option.name, option.value, option.text])); + + combo = MODx.load({ + xtype: 'modx-combo', + store: new Ext.data.SimpleStore({ + fields: ['d', 'v', 't'], + data: data + }), + displayField: 'd', + valueField: 'v', + mode: 'local', + triggerAction: 'all', + editable: false, + selectOnFocus: false, + preventRender: true }); } catch (e2) { - obj = Ext.ComponentMgr.create({ xtype: 'combo-boolean', id: Ext.id() }); + combo = Ext.ComponentMgr.create({ + xtype: 'combo-boolean', + id: Ext.id() + }); } } - return obj; + return combo; } }); -Ext.reg('grid-local-property',MODx.grid.LocalProperty); +Ext.reg('grid-local-property', MODx.grid.LocalProperty); diff --git a/manager/assets/modext/widgets/element/modx.grid.element.properties.js b/manager/assets/modext/widgets/element/modx.grid.element.properties.js index 92e04f45f6b..dca956a366d 100644 --- a/manager/assets/modext/widgets/element/modx.grid.element.properties.js +++ b/manager/assets/modext/widgets/element/modx.grid.element.properties.js @@ -1,238 +1,305 @@ -MODx.panel.ElementProperties = function(config) { - config = config || {}; - Ext.applyIf(config,{ - id: 'modx-panel-element-properties' - ,title: _('properties') - ,header: false - ,defaults: { collapsible: false ,autoHeight: true ,border: false } - ,layout: 'form' - ,items: [{ - html: '

    '+_('element_properties_desc')+'

    ' - ,itemId: 'desc-properties' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-element-properties' - ,cls:'main-wrapper' - ,id: 'modx-grid-element-properties' - ,itemId: 'grid-properties' - ,autoHeight: true - ,border: true - ,panel: config.elementPanel - ,elementId: config.elementId - ,elementType: config.elementType - },{ - layout: 'form' - ,labelAlign: 'top' - ,border: false - ,cls: 'main-wrapper' - ,items: [{ - xtype: 'xcheckbox' - ,boxLabel: _('property_preprocess') - ,description: MODx.expandHelp ? '' : _('property_preprocess_msg') - ,name: 'property_preprocess' - ,id: 'modx-element-property-preprocess' - ,inputValue: true - ,hideLabel: true - ,checked: config.record.property_preprocess || 0 - ,listeners: { - 'check':{fn:function() {Ext.getCmp(this.config.elementPanel).markDirty();},scope:this} +MODx.panel.ElementProperties = function(config = {}) { + Ext.applyIf(config, { + id: 'modx-panel-element-properties', + title: _('properties'), + header: false, + defaults: { + collapsible: false, + autoHeight: true, + border: false + }, + layout: 'form', + items: [{ + html: `

    ${_('element_properties_desc')}

    `, + itemId: 'desc-properties', + xtype: 'modx-description' + }, { + xtype: 'modx-grid-element-properties', + cls: 'main-wrapper', + id: 'modx-grid-element-properties', + itemId: 'grid-properties', + autoHeight: true, + border: true, + panel: config.elementPanel, + elementId: config.elementId, + elementType: config.elementType + }, { + layout: 'form', + labelAlign: 'top', + border: false, + cls: 'main-wrapper', + items: [{ + xtype: 'xcheckbox', + boxLabel: _('property_preprocess'), + description: MODx.expandHelp ? '' : _('property_preprocess_msg'), + name: 'property_preprocess', + inputValue: true, + hideLabel: true, + checked: config.record.property_preprocess || 0, + listeners: { + check: { + fn: function() { + Ext.getCmp(this.config.elementPanel).markDirty(); + }, + scope: this + } } - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-element-property-preprocess' - ,html: _('property_preprocess_msg') - ,cls: 'desc-under' + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('property_preprocess_msg'), + cls: 'desc-under' }] }] }); - MODx.panel.ElementProperties.superclass.constructor.call(this,config); + MODx.panel.ElementProperties.superclass.constructor.call(this, config); }; -Ext.extend(MODx.panel.ElementProperties,MODx.Panel); -Ext.reg('modx-panel-element-properties',MODx.panel.ElementProperties); - +Ext.extend(MODx.panel.ElementProperties, MODx.Panel); +Ext.reg('modx-panel-element-properties', MODx.panel.ElementProperties); -MODx.grid.ElementProperties = function(config) { - config = config || {}; +MODx.grid.ElementProperties = function(config = {}) { this.exp = new Ext.grid.RowExpander({ - tpl : new Ext.Template( + tpl: new Ext.Template( '

    {desc_trans}

    ' ) }); - Ext.applyIf(config,{ - title: _('properties') - ,id: 'modx-grid-element-properties' - ,maxHeight: 300 - ,fields: ['name','desc','xtype','options','value','lexicon','overridden','desc_trans','area','area_trans'] - ,autoExpandColumn: 'value' - ,sortBy: 'name' - ,anchor: '100%' - ,sm: new Ext.grid.RowSelectionModel({singleSelect:false}) - ,loadMask: true - ,lockProperties: true - ,plugins: [this.exp] - ,grouping: true - ,groupBy: 'area_trans' - ,singleText: _('property') - ,pluralText: _('properties') - ,columns: [this.exp,{ - header: _('name') - ,dataIndex: 'name' - ,width: 200 - ,sortable: true - ,renderer: this._renderName - },{ - header: _('type') - ,dataIndex: 'xtype' - ,width: 100 - ,renderer: this._renderType - ,sortable: true - },{ - header: _('value') - ,dataIndex: 'value' - ,id: 'value' - ,width: 250 - ,renderer: this.renderDynField.createDelegate(this,[this],true) - ,sortable: true - },{ - header: _('area') - ,dataIndex: 'area_trans' - ,id: 'area' - ,width: 150 - ,sortable: true - ,hidden: true - }] - ,tbar: [{ - text: _('property_create') - ,id: 'modx-btn-property-create' - ,handler: this.create - ,scope: this - ,disabled: true - },{ - text: _('properties_default_locked') - ,id: 'modx-btn-propset-lock' - ,handler: this.togglePropertiesLock - ,enableToggle: true - ,pressed: true - ,disabled: MODx.perm.unlock_element_properties ? false : true - ,scope: this - },'->',{ - xtype: 'modx-combo-property-set' - ,id: 'modx-combo-property-set' - ,baseParams: { - action: 'Element/PropertySet/GetList' - ,showAssociated: true - ,elementId: config.elementId - ,elementType: config.elementType - } - ,value: 0 - ,listeners: { - 'select': {fn:this.changePropertySet,scope:this} + Ext.applyIf(config, { + title: _('properties'), + id: 'modx-grid-element-properties', + maxHeight: 300, + fields: [ + 'name', + 'desc', + 'xtype', + 'options', + 'value', + 'lexicon', + 'overridden', + 'desc_trans', + 'area', + 'area_trans', + 'permissions' + ], + autoExpandColumn: 'value', + sortBy: 'name', + anchor: '100%', + sm: new Ext.grid.RowSelectionModel({ + singleSelect: false + }), + loadMask: true, + lockProperties: true, + plugins: [this.exp], + grouping: true, + groupBy: 'area_trans', + singleText: _('property'), + pluralText: _('properties'), + columns: [this.exp, { + header: _('name'), + dataIndex: 'name', + width: 200, + sortable: true, + renderer: this._renderName + }, { + header: _('type'), + dataIndex: 'xtype', + width: 100, + renderer: this._renderType, + sortable: true + }, { + header: _('value'), + dataIndex: 'value', + id: 'value', + width: 250, + renderer: this.renderDynField.createDelegate(this, [this], true), + sortable: true + }, { + header: _('area'), + dataIndex: 'area_trans', + id: 'area', + width: 150, + sortable: true, + hidden: true + }], + tbar: [{ + text: _('property_create'), + id: 'modx-btn-property-create', + handler: this.create, + scope: this, + disabled: true + }, { + text: _('properties_default_locked'), + id: 'modx-btn-propset-lock', + handler: this.togglePropertiesLock, + enableToggle: true, + pressed: true, + disabled: !MODx.perm.unlock_element_properties, + scope: this + }, '->', { + xtype: 'modx-combo-property-set', + id: 'modx-combo-property-set', + baseParams: { + action: 'Element/PropertySet/GetList', + showAssociated: true, + elementId: config.elementId, + elementType: config.elementType, + combo: true + }, + value: 0, + listeners: { + select: { + fn: this.changePropertySet, + scope: this + } } - },{ - text: _('propertyset_add') - ,handler: this.addPropertySet - ,scope: this - },{ - text: _('propertyset_save') - ,cls: 'primary-button' - ,handler: this.save - ,scope: this - ,hidden: MODx.request.id ? false : true - }] - ,bbar: [{ - text: _('property_revert_all') - ,id: 'modx-btn-property-revert-all' - ,handler: this.revertAll - ,scope:this - ,disabled: true - },{ - text: _('import') - ,handler: this.importProperties - ,scope: this - },{ - text: _('export') - ,handler: this.exportProperties - ,scope: this - }] - ,collapseFirst: false - ,tools: [{ - id: 'plus' - ,qtip: _('expand_all') - ,handler: this.expandAll - ,scope: this - },{ - id: 'minus' - ,hidden: true - ,qtip: _('collapse_all') - ,handler: this.collapseAll - ,scope: this + }, { + text: _('propertyset_add'), + id: 'modx-btn-property-set-add', + handler: this.addPropertySet, + scope: this + }, { + text: _('propertyset_save'), + id: 'modx-btn-property-set-save', + cls: 'primary-button', + handler: this.save, + scope: this, + hidden: !MODx.request.id + }], + bbar: [{ + text: _('property_revert_all'), + id: 'modx-btn-property-revert-all', + handler: this.revertAll, + scope: this, + disabled: true + }, { + text: _('import'), + id: 'modx-btn-property-import', + handler: this.importProperties, + scope: this + }, { + text: _('export'), + handler: this.exportProperties, + scope: this + }], + collapseFirst: false, + tools: [{ + id: 'plus', + qtip: _('expand_all'), + handler: this.expandAll, + scope: this + }, { + id: 'minus', + hidden: true, + qtip: _('collapse_all'), + handler: this.collapseAll, + scope: this }] }); - MODx.grid.ElementProperties.superclass.constructor.call(this,config); - this.on('afteredit', this.propertyChanged, this); - this.on('afterRemoveRow', this.propertyChanged, this); - this.on('render',function() { - this.mask = new Ext.LoadMask(this.getEl()); - },this); + MODx.grid.ElementProperties.superclass.constructor.call(this, config); - if (this.config.lockProperties) { - this.on('render',function() { - this.lockMask = MODx.load({ - xtype: 'modx-lockmask' - ,el: this.getGridEl() - ,msg: _('properties_default_locked') - }); - this.lockMask.toggle(); - },this); - } + // Omitting 'revert' action, as it is effectively the same as 'edit' + this.gridMenuActions = ['edit', 'delete']; + + // Note there are currently no action-specific permissions for Dashboards + this.setUserCanEdit(['edit_propertyset', 'save_propertyset']); + this.setUserCanCreate(['new_propertyset', 'save_propertyset']); + this.setUserCanDelete(['delete_propertyset']); + this.setShowActionsMenu(); + + this.on({ + render: grid => { + const buttonsToHide = []; + this.mask = new Ext.LoadMask(this.getEl()); + if (this.config.lockProperties) { + this.lockMask = MODx.load({ + xtype: 'modx-lockmask', + el: this.getGridEl(), + msg: _('properties_default_locked') + }); + this.lockMask.toggle(); + } + if (!this.userCanCreate) { + buttonsToHide.push('modx-btn-property-set-add', 'modx-btn-property-import'); + } + if (!this.userCanEdit) { + buttonsToHide.push('modx-btn-property-create', 'modx-btn-property-revert-all'); + if (!this.userCanCreate) { + buttonsToHide.push('modx-btn-property-set-save'); + } + } + if ( + !MODx.perm.unlock_element_properties + && !this.id === 'modx-grid-element-properties' + ) { + buttonsToHide.push('modx-btn-propset-lock'); + } + if (buttonsToHide.length > 0) { + buttonsToHide.forEach(btnId => Ext.getCmp(btnId)?.hide()); + } + }, + beforeedit: e => { + if (e.record[this.permissionsProviderProp].isProtected || !this.userCanEditRecord(e.record)) { + return false; + } + }, + afteredit: e => { + this.propertyChanged(); + }, + afterRemoveRow: record => { + this.propertyChanged(); + } + }); }; -Ext.extend(MODx.grid.ElementProperties,MODx.grid.LocalProperty,{ - defaultProperties: [] +Ext.extend(MODx.grid.ElementProperties, MODx.grid.LocalProperty, { + defaultProperties: [], - ,onDirty: function() { + onDirty: function() { if (this.config.panel) { Ext.getCmp(this.config.panel).fireEvent('fieldChange'); } - } + }, - ,_renderType: function(v,md,rec,ri) { - switch (v) { - case 'combo-boolean': return _('yesno'); break; - case 'datefield': return _('date'); break; - case 'numberfield': return _('integer'); break; - case 'file': return _('file'); break; - case 'color': return _('color'); break; + _renderType: function(value, metaData, record, rowIndex) { + switch (value) { + case 'combo-boolean': return _('yesno'); + case 'datefield': return _('date'); + case 'numberfield': return _('integer'); + case 'file': return _('file'); + case 'color': return _('color'); + // no default } - return _(v); - } - ,_renderName: function(v,md,rec,ri) { - switch (rec.data.overridden) { + return _(value); + }, + + _renderName: function(value, metaData, record, rowIndex) { + switch (record.data.overridden) { case 1: - return ''+v+''; break; + return `${value}`; case 2: - return ''+v+''; + return `${value}`; default: - return ''+v+''; + return `${value}`; } - } + }, - ,save: function() { - var d = this.encode(); - var cb = Ext.getCmp('modx-combo-property-set'); - if (!cb) { + save: function() { + const + data = this.encode(), + propSetCombo = Ext.getCmp('modx-combo-property-set') + ; + if (!propSetCombo) { this.getStore().commitChanges(); this.onDirty(); return true; } - var p = { - action: 'Element/PropertySet/UpdateFromElement' - ,id: cb.getValue() - ,data: d + const params = { + action: 'Element/PropertySet/UpdateFromElement', + id: propSetCombo.getValue(), + data: data }; if (this.config.elementId) { - Ext.apply(p,{ - elementId: this.config.elementId - ,elementType: this.config.elementType + Ext.apply(params, { + elementId: this.config.elementId, + elementType: this.config.elementType }); } try { @@ -240,361 +307,425 @@ Ext.extend(MODx.grid.ElementProperties,MODx.grid.LocalProperty,{ this.mask = new Ext.LoadMask(this.getEl()); } if (this.mask) { this.mask.show(); } - } catch (e) { } + // eslint-disable-next-line no-empty + } catch (e) {} MODx.Ajax.request({ - url: MODx.config.connector_url - ,params: p - ,listeners: { - 'success': {fn:function(r) { - this.getStore().commitChanges(); - this.changePropertySet(cb); - this.onDirty(); - if (this.mask) { this.mask.hide(); } - MODx.msg.status({ - title: _('success') - ,message: _('save_successful') - ,dontHide: r.message != '' ? true : false - }); - },scope:this} + url: MODx.config.connector_url, + params: params, + listeners: { + success: { + fn: function(response) { + this.getStore().commitChanges(); + this.changePropertySet(propSetCombo); + this.onDirty(); + if (this.mask) { this.mask.hide(); } + MODx.msg.status({ + title: _('success'), + message: _('save_successful'), + dontHide: !Ext.isEmpty(response.message) + }); + }, + scope: this + } } }); - } + }, - ,addPropertySet: function(btn,e) { - this.loadWindow(btn,e,{ - xtype: 'modx-window-element-property-set-add' - ,record: { - elementId: this.config.elementId != 0 ? this.config.elementId : '' - ,elementType: this.config.elementType - } - ,listeners: { - 'success': {fn:function(o) { - var cb = Ext.getCmp('modx-combo-property-set'); - cb.store.reload({ - callback: function() { - cb.setValue(o.a.result.object.id); - this.changePropertySet(cb); - } - ,scope: this - }); - this.onDirty(); - },scope:this} + addPropertySet: function(btn, e) { + this.loadWindow(btn, e, { + xtype: 'modx-window-element-property-set-add', + record: { + elementId: this.config.elementId !== 0 ? this.config.elementId : '', + elementType: this.config.elementType + }, + listeners: { + success: { + fn: function(response) { + const propSetCombo = Ext.getCmp('modx-combo-property-set'); + propSetCombo.store.reload({ + callback: function() { + propSetCombo.setValue(response.a.result.object.id); + this.changePropertySet(propSetCombo); + }, + scope: this + }); + this.onDirty(); + }, + scope: this + } } }); - } + }, - ,togglePropertiesLock: function() { - var ps = Ext.getCmp('modx-combo-property-set').getValue(); - if (ps == 0 || ps == _('default')) { - Ext.getCmp('modx-btn-propset-lock').setText(this.lockMask.locked ? _('properties_default_unlocked') : _('properties_default_locked')); + togglePropertiesLock: function() { + const propSetId = Ext.getCmp('modx-combo-property-set').getValue(); + if (propSetId === 0 || propSetId === _('default')) { + Ext.getCmp('modx-btn-propset-lock').setText(this.lockMask.locked + ? _('properties_default_unlocked') + : _('properties_default_locked')) + ; this.lockMask.toggle(); this.toggleButtons(this.lockMask.locked); } - } + }, - ,toggleButtons: function(v) { - var btn = Ext.getCmp('modx-btn-property-create'); + toggleButtons: function(value) { + const btn = Ext.getCmp('modx-btn-property-create'); if (btn) { - Ext.getCmp('modx-btn-property-create').setDisabled(v); - Ext.getCmp('modx-btn-property-revert-all').setDisabled(v); + Ext.getCmp('modx-btn-property-create').setDisabled(value); + Ext.getCmp('modx-btn-property-revert-all').setDisabled(value); } - } + }, - ,changePropertySet: function(cb) { - var ps = cb.getValue(); - var lockbtn = Ext.getCmp('modx-btn-propset-lock'); - if (ps == 0 || ps == _('default')) { + changePropertySet: function(propSetCombo) { + const + propSetId = propSetCombo.getValue(), + lockbtn = Ext.getCmp('modx-btn-propset-lock') + ; + if (propSetId === 0 || propSetId === _('default')) { if (MODx.perm.unlock_element_properties) { - if (lockbtn) { lockbtn.setDisabled(false); } + if (lockbtn) { + lockbtn.setDisabled(false); + } } if (this.lockMask && this.lockMask.locked) { this.lockMask.show(); this.toggleButtons(true); } } else { - if (lockbtn) { lockbtn.setDisabled(true); } - if (this.lockMask) this.lockMask.hide(); + if (lockbtn) { + lockbtn.setDisabled(true); + } + if (this.lockMask) { + this.lockMask.hide(); + } this.toggleButtons(false); } MODx.Ajax.request({ - url: MODx.config.connector_url - ,params: { - action: 'Element/PropertySet/Get' - ,id: ps - ,elementId: this.config.elementId - ,elementType: this.config.elementType - } - ,listeners: { - 'success': {fn:function(r) { - var s = this.getStore(); - var data = Ext.decode(r.object.data); - s.removeAll(); - s.loadData(data); - },scope:this} + url: MODx.config.connector_url, + params: { + action: 'Element/PropertySet/Get', + id: propSetId, + elementId: this.config.elementId, + elementType: this.config.elementType + }, + listeners: { + success: { + fn: function(response) { + const + store = this.getStore(), + data = Ext.decode(response.object.data) + ; + store.removeAll(); + store.loadData(data); + }, + scope: this + } } }); - } + }, - ,create: function(btn,e) { - this.loadWindow(btn,e,{ - xtype: 'modx-window-element-property-create' - ,blankValues: true - ,listeners: { - 'success': {fn:function(r) { - - var rec = new this.propRecord({ - name: r.name - ,desc: r.desc - ,desc_trans: r.desc - ,xtype: r.xtype - ,options: r.options - ,value: r.value - ,lexicon: r.lexicon - ,overridden: this.isDefaultPropSet() ? 0 : 2 - ,area: r.area - ,area_trans: r.area - }); - this.getStore().add(rec); - this.propertyChanged(); - this.onDirty(); - },scope:this} + create: function(btn, e) { + this.loadWindow(btn, e, { + xtype: 'modx-window-element-property-create', + blankValues: true, + listeners: { + success: { + fn: function(response) { + const record = new this.propRecord({ + name: response.name, + desc: response.desc, + desc_trans: response.desc, + xtype: response.xtype, + options: response.options, + value: response.value, + lexicon: response.lexicon, + overridden: this.isDefaultPropSet() ? 0 : 2, + area: response.area, + area_trans: response.area + }); + this.getStore().add(record); + this.propertyChanged(); + this.onDirty(); + }, + scope: this + } } }); - } + }, - ,update: function(btn,e) { - this.loadWindow(btn,e,{ - xtype: 'modx-window-element-property-update' - ,record: this.menu.record - ,listeners: { - 'success': {fn:function(r) { - var def = this.isDefaultPropSet(); - var s = this.getStore(); - var rec = s.getAt(this.menu.recordIndex); - rec.set('name',r.name); - rec.set('desc',r.desc); - rec.set('desc_trans', r.desc); - rec.set('xtype',r.xtype); - rec.set('options',r.options); - rec.set('value',r.value); - rec.set('lexicon',r.lexicon); - rec.set('overridden',r.overridden == 2 ? 2 : (!def ? 1 : 0)); - rec.set('area',r.area); - rec.set('area_trans',r.area); - this.getView().refresh(); - this.onDirty(); - },scope:this} + update: function(btn, e) { + this.loadWindow(btn, e, { + xtype: 'modx-window-element-property-update', + record: this.menu.record, + listeners: { + success: { + fn: function(response) { + const + isDefaultSet = this.isDefaultPropSet(), + store = this.getStore(), + record = store.getAt(this.menu.recordIndex) + ; + record.set('name', response.name); + record.set('desc', response.desc); + record.set('desc_trans', response.desc); + record.set('xtype', response.xtype); + record.set('options', response.options); + record.set('value', response.value); + record.set('lexicon', response.lexicon); + // eslint-disable-next-line no-nested-ternary + record.set('overridden', response.overridden === 2 ? 2 : (!isDefaultSet ? 1 : 0)); + record.set('area', response.area); + record.set('area_trans', response.area); + this.getView().refresh(); + this.onDirty(); + }, + scope: this + } } }); - } + }, - ,revert: function(btn,e) { - Ext.Msg.confirm(_('warning'),_('property_revert_confirm'),function(e) { - if (e == 'yes') { - var ri = this.menu.recordIndex; - var d = this.defaultProperties[ri]; - if (d) { - var rec = this.getStore().getAt(ri); - rec.set('name',d[0]); - rec.set('desc',d[1]); - rec.set('desc_trans',d[1]); - rec.set('xtype',d[2]); - rec.set('options',d[3]); - rec.set('value',d[4]); - rec.set('overridden',0); - rec.set('area',d[5]); - rec.set('area_trans',d[5]); - rec.commit(); + revert: function(btn, e) { + Ext.Msg.confirm(_('warning'), _('property_revert_confirm'), function(e) { + if (e === 'yes') { + const + { recordIndex } = this.menu, + propData = this.defaultProperties[recordIndex] + ; + if (propData) { + const record = this.getStore().getAt(recordIndex); + record.set('name', propData[0]); + record.set('desc', propData[1]); + record.set('desc_trans', propData[1]); + record.set('xtype', propData[2]); + record.set('options', propData[3]); + record.set('value', propData[4]); + record.set('overridden', 0); + record.set('area', propData[5]); + record.set('area_trans', propData[5]); + record.commit(); } } - },this); - } + }, this); + }, - ,revertAll: function(btn,e) { - Ext.Msg.confirm(_('warning'),_('property_revert_all_confirm'),function(e) { - if (e == 'yes') { + revertAll: function(btn, e) { + Ext.Msg.confirm(_('warning'), _('property_revert_all_confirm'), function(e) { + if (e === 'yes') { this.getStore().loadData(this.defaultProperties); } - },this); - } + }, this); + }, - ,removeMultiple: function(btn,e) { - var rows = this.getSelectionModel().getSelections(); - var rids = []; - for (var i=0;i in values, desc */ - for (var i in data) { - if (data[i][4]) { data[i][4] = data[i][4].replace(/>/g,'>').replace(/</g,'<'); } - if (data[i][5]) { data[i][5] = data[i][5].replace(/>/g,'>').replace(/</g,'<'); } - if (data[i][1]) { data[i][1] = data[i][1].replace(/>/g,'>').replace(/</g,'<'); } - } - s.loadData(data); - /* mark fields dirty */ - var recs = s.getRange(0,s.getTotalCount()); - for (var i=0;i { + [4, 5, 1].forEach(index => { + if (record[index]) { + record[index] = record[index].replace(/>/g, '>').replace(/</g, '<'); + } + }); + }); + store.loadData(data); + const newRecords = store.getRange(0, store.getTotalCount()); + newRecords.forEach(record => record.markDirty()); + this.getView().refresh(); + }, + scope: this + } } }); - } - - ,_showMenu: function(g,ri,e) { - var sm = this.getSelectionModel(); - if (sm.getSelections().length > 1) { - e.stopEvent(); - e.preventDefault(); - this.menu.removeAll(); - this.addContextMenuItem([{ - text: _('properties_remove') - ,handler: this.removeMultiple - ,scope: this - }]); - this.menu.show(e.target); - } else { - MODx.grid.ElementProperties.superclass._showMenu.call(this,g,ri,e); - } - } + }, - ,isDefaultPropSet: function() { - var ps = Ext.getCmp('modx-combo-property-set').getValue(); - return (ps == 0 || ps == _('default')); - } - - ,getMenu: function() { - var def = this.isDefaultPropSet(); - - var r = this.menu.record; - var m = []; - m.push({ - text: _('property_update') - ,scope: this - ,handler: this.update - }); + isDefaultPropSet: function() { + const propSetId = Ext.getCmp('modx-combo-property-set').getValue(); + return (propSetId === 0 || propSetId === _('default')); + }, - if (r.overridden) { - m.push({ - text: _('property_revert') - ,scope: this - ,handler: this.revert - }); - } - if ((r.overridden == 2 && !def) || (r.overridden != 1 && def) || (!r.overridden && !def)) { - m.push({ - text: _('property_remove') - ,scope: this - ,handler: this.remove.createDelegate(this,[{ - title: _('warning') - ,text: _('property_remove_confirm') - }]) + getMenu: function() { + const + isDefaultSet = this.isDefaultPropSet(), + model = this.getSelectionModel(), + record = model.getSelected(), + propIsCustom = record.data.overridden === 2, + propIsOverriden = record.data.overridden === 1, + propUnchanged = [0, false].includes(record.data.overridden), + menu = [] + ; + if (model.getCount() > 1 && this.userCanDelete) { + menu.push({ + text: _('properties_remove'), + handler: this.removeMultiple, + scope: this }); + } else { + if (this.userCanEdit) { + menu.push({ + text: _('property_update'), + scope: this, + handler: this.update + }); + if (propIsOverriden) { + menu.push({ + text: _('property_revert'), + scope: this, + handler: this.revert + }); + } + } + if ( + this.userCanDelete + && ((!isDefaultSet && (propUnchanged || propIsCustom)) + || (isDefaultSet && !propIsOverriden)) + ) { + if (menu.length > 0) { + menu.push('-'); + } + menu.push({ + text: _('property_remove'), + scope: this, + handler: this.remove.createDelegate(this, [{ + title: _('warning'), + text: _('property_remove_confirm') + }]) + }); + } } + return menu; + }, - return m; - } - - ,propertyChanged: function() { - var ep = Ext.getCmp(this.config.panel); - if (!ep) return false; - var hf = this.config.hiddenPropField || 'props'; - ep.getForm().findField(hf).setValue('1'); - ep.fireEvent('fieldChange',{ - field: hf - ,form: ep.getForm() + /** + * Updates hidden field with the current set of serialized properties to + * be persisted to the database. Only applies to an Element's editing panel + * (in its Properties tab), not to the standalone Property Sets editor. + */ + propertyChanged: function() { + const elementPanel = Ext.getCmp(this.config.panel); + if (!elementPanel) { + return false; + } + const propsValueField = this.config.hiddenPropField || 'props'; + elementPanel.getForm().findField(propsValueField).setValue('1'); + elementPanel.fireEvent('fieldChange', { + field: propsValueField, + form: elementPanel.getForm() }); return true; } }); -Ext.reg('modx-grid-element-properties',MODx.grid.ElementProperties); +Ext.reg('modx-grid-element-properties', MODx.grid.ElementProperties); - -MODx.grid.ElementPropertyOption = function(config) { - config = config || {}; - Ext.applyIf(config,{ - title: _('property_options') - ,id: 'modx-grid-element-property-options' - ,autoHeight: true - ,maxHeight: 300 - ,width: '100%' - ,fields: ['text','value','name'] - ,data: [] - ,columns: [{ - header: _('name') - ,dataIndex: 'text' - ,width: 150 - ,editor: { xtype: 'textfield' ,allowBlank: false } - },{ - header: _('value') - ,dataIndex: 'value' - ,id: 'value' - ,width: 250 - ,editor: { xtype: 'textfield' ,allowBlank: true } - }] - ,tbar: [{ - text: _('property_option_create') - ,cls: 'primary-button' - ,handler: this.create - ,scope: this +MODx.grid.ElementPropertyOption = function(config = {}) { + Ext.applyIf(config, { + title: _('property_options'), + id: 'modx-grid-element-property-options', + autoHeight: true, + maxHeight: 300, + width: '100%', + fields: [ + 'text', + 'value', + 'name' + ], + data: [], + columns: [{ + header: _('name'), + dataIndex: 'text', + width: 150, + editor: { + xtype: 'textfield', + allowBlank: false + } + }, { + header: _('value'), + dataIndex: 'value', + id: 'value', + width: 250, + editor: { + xtype: 'textfield' + } + }], + tbar: [{ + text: _('property_option_create'), + cls: 'primary-button', + handler: this.create, + scope: this }] }); - MODx.grid.ElementPropertyOption.superclass.constructor.call(this,config); - this.optRecord = Ext.data.Record.create([{name: 'text'},{name: 'value'}]); + MODx.grid.ElementPropertyOption.superclass.constructor.call(this, config); + this.optRecord = Ext.data.Record.create([ + { name: 'text' }, + { name: 'value' } + ]); }; -Ext.extend(MODx.grid.ElementPropertyOption,MODx.grid.LocalGrid,{ - create: function(btn,e) { - this.loadWindow(btn,e,{ - xtype: 'modx-window-element-property-option-create' - ,listeners: { - 'success': {fn:function(r) { - var rec = new this.optRecord({ - text: r.text - ,value: r.value - }); - this.getStore().add(rec); - },scope:this} +Ext.extend(MODx.grid.ElementPropertyOption, MODx.grid.LocalGrid, { + create: function(btn, e) { + this.loadWindow(btn, e, { + xtype: 'modx-window-element-property-option-create', + listeners: { + success: { + fn: function(response) { + const record = new this.optRecord({ + text: response.text, + value: response.value + }); + this.getStore().add(record); + }, + scope: this + } } }); - } + }, - ,getMenu: function() { + getMenu: function() { return [{ - text: _('property_option_remove') - ,scope: this - ,handler: this.remove.createDelegate(this,[{ - title: _('warning') - ,text: _('property_option_remove_confirm') + text: _('property_option_remove'), + scope: this, + handler: this.remove.createDelegate(this, [{ + title: _('warning'), + text: _('property_option_remove_confirm') }]) }]; } }); -Ext.reg('modx-grid-element-property-options',MODx.grid.ElementPropertyOption); +Ext.reg('modx-grid-element-property-options', MODx.grid.ElementPropertyOption); /** * @class MODx.window.CreateElementProperty @@ -602,322 +733,190 @@ Ext.reg('modx-grid-element-property-options',MODx.grid.ElementPropertyOption); * @param {Object} config An object of configuration properties * @xtype modx-window-element-property-create */ -MODx.window.CreateElementProperty = function(config) { - config = config || {}; - Ext.applyIf(config,{ - title: _('property_create') - ,id: 'modx-window-element-property-create' - ,width: 600 - ,saveBtnText: _('done') - ,fields: [{ - layout: 'column' - ,border: false - ,defaults: { - layout: 'form' - ,labelAlign: 'top' - ,anchor: '100%' - ,border: false - } - ,items: [{ - columnWidth: .6 - ,items: [{ - fieldLabel: _('name') - ,description: MODx.expandHelp ? '' : _('property_name_desc') - ,name: 'name' - ,id: 'modx-cep-name' - ,xtype: 'textfield' - ,anchor: '100%' - ,allowBlank: false - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-cep-name' - ,html: _('property_name_desc') - ,cls: 'desc-under' - },{ - fieldLabel: _('description') - ,description: MODx.expandHelp ? '' : _('property_description_desc') - ,name: 'desc' - ,id: 'modx-cep-desc' - ,xtype: 'textarea' - ,anchor: '100%' - ,height: 120 - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-cep-description' - ,html: _('property_description_desc') - ,cls: 'desc-under' +MODx.window.CreateElementProperty = function(config = {}) { + const + id = Ext.id(), + action = config.isUpdate ? 'update' : 'create' + ; + this.id = `modx-window-${action}-property-${id}`; + Ext.applyIf(config, { + title: _('property_create'), + width: 600, + saveBtnText: _('done'), + fields: [{ + layout: 'column', + border: false, + defaults: { + layout: 'form', + labelAlign: 'top', + anchor: '100%', + border: false + }, + items: [{ + columnWidth: 0.6, + items: [{ + fieldLabel: _('name'), + description: MODx.expandHelp ? '' : _('property_name_desc'), + name: 'name', + xtype: 'textfield', + anchor: '100%', + allowBlank: false + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('property_name_desc'), + cls: 'desc-under' + }, { + fieldLabel: _('description'), + description: MODx.expandHelp ? '' : _('property_description_desc'), + name: 'desc', + xtype: 'textarea', + anchor: '100%', + height: 120 + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('property_description_desc'), + cls: 'desc-under' }] - },{ - columnWidth: .4 - ,items: [{ - fieldLabel: _('type') - ,description: MODx.expandHelp ? '' : _('property_xtype_desc') - ,name: 'xtype' - ,id: 'modx-cep-xtype' - ,xtype: 'modx-combo-xtype' - ,anchor: '100%' - ,listeners: { - 'select': {fn:function(cb) { - var g = Ext.getCmp('modx-cep-grid-element-property-options'); - if (!g) return; - if (cb.getValue() == 'list' || cb.getValue() == 'color') { - g.show(); - } else { - g.hide(); - } - this.syncSize(); - },scope:this} + }, { + columnWidth: 0.4, + items: [{ + fieldLabel: _('type'), + description: MODx.expandHelp ? '' : _('property_xtype_desc'), + name: 'xtype', + id: `modx-property-xtype--${this.id}`, + xtype: 'modx-combo-xtype', + anchor: '100%', + listeners: { + select: { + fn: function(combo) { + const optsGrid = Ext.getCmp(`modx-grid--property-options--${this.id}`); + if (!optsGrid) { + return; + } + if (['list', 'color'].includes(combo.getValue())) { + optsGrid.show(); + } else { + optsGrid.hide(); + } + this.syncSize(); + }, + scope: this + } } - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-cep-xtype' - ,html: _('property_xtype_desc') - ,cls: 'desc-under' - },{ - xtype: 'textfield' - ,fieldLabel: _('lexicon') - ,description: MODx.expandHelp ? '' : _('property_lexicon_desc') - ,name: 'lexicon' - ,id: 'modx-cep-lexicon' - ,anchor: '100%' - ,allowBlank: true - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-cep-lexicon' - ,html: _('property_lexicon_desc') - ,cls: 'desc-under' - },{ - xtype: 'textfield' - ,fieldLabel: _('area') - ,description: MODx.expandHelp ? '' : _('property_area_desc') - ,name: 'area' - ,id: 'modx-cep-area' - ,anchor: '100%' - ,allowBlank: true - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-cep-area' - ,html: _('property_area_desc') - ,cls: 'desc-under' + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('property_xtype_desc'), + cls: 'desc-under' + }, { + xtype: 'textfield', + fieldLabel: _('lexicon'), + description: MODx.expandHelp ? '' : _('property_lexicon_desc'), + name: 'lexicon', + anchor: '100%', + allowBlank: true + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('property_lexicon_desc'), + cls: 'desc-under' + }, { + xtype: 'textfield', + fieldLabel: _('area'), + description: MODx.expandHelp ? '' : _('property_area_desc'), + name: 'area', + anchor: '100%', + allowBlank: true + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('property_area_desc'), + cls: 'desc-under' }] }] - },{ - xtype: 'modx-element-value-field' - ,xtypeField: 'modx-cep-xtype' - ,id: 'modx-cep-value' - ,anchor: '100%' - },{ - xtype: 'modx-grid-element-property-options' - ,id: 'modx-cep-grid-element-property-options' - ,anchor: '100%' - }] - ,keys: [] + }, { + xtype: 'modx-element-value-field', + xtypeField: `modx-property-xtype--${this.id}`, + anchor: '100%' + }, { + xtype: 'modx-grid-element-property-options', + id: `modx-grid--property-options--${this.id}`, + anchor: '100%' + }], + keys: [] }); - MODx.window.CreateElementProperty.superclass.constructor.call(this,config); - this.on('show',this.onShow,this); + MODx.window.CreateElementProperty.superclass.constructor.call(this, config); + this.on('show', this.onShow, this); }; -Ext.extend(MODx.window.CreateElementProperty,MODx.Window,{ +Ext.extend(MODx.window.CreateElementProperty, MODx.Window, { submit: function() { - var v = this.fp.getForm().getValues(); - - var g = Ext.getCmp('modx-cep-grid-element-property-options'); - var opt = eval(g.encode()); - Ext.apply(v,{ - options: opt + const + values = this.fp.getForm().getValues(), + optsGrid = Ext.getCmp(`modx-grid--property-options--${this.id}`), + // eslint-disable-next-line no-eval + options = eval(optsGrid.encode()) + ; + Ext.apply(values, { + options: options }); - if (this.fp.getForm().isValid()) { - if (this.fireEvent('success',v)) { + if (this.fireEvent('success', values)) { this.fp.getForm().reset(); this.hide(); return true; } } return false; - } - ,onShow: function() { - var g = Ext.getCmp('modx-cep-grid-element-property-options'); - g.getStore().removeAll(); - g.hide(); + }, + + onShow: function() { + const optsGrid = Ext.getCmp(`modx-grid--property-options--${this.id}`); + if (!optsGrid) { + return; + } + optsGrid.getStore().removeAll(); + optsGrid.hide(); + if ( + this.config.isUpdate + && ['list', 'color'].includes(this.fp.getForm().findField('xtype').getValue()) + ) { + const + propsGrid = Ext.getCmp('modx-grid-element-properties'), + selectedRecord = propsGrid.getSelectionModel().getSelected() + ; + if (selectedRecord) { + const + { options } = selectedRecord.data, + optionsData = [] + ; + options.forEach(option => optionsData.push([option.text, option.value])); + optsGrid.getStore().loadData(optionsData); + optsGrid.show(); + } + } this.syncSize(); this.center(); } }); -Ext.reg('modx-window-element-property-create',MODx.window.CreateElementProperty); - - +Ext.reg('modx-window-element-property-create', MODx.window.CreateElementProperty); /** * @class MODx.window.UpdateElementProperty - * @extends MODx.Window + * @extends MODx.window.CreateElementProperty * @param {Object} config An object of configuration properties * @xtype modx-window-element-property-update */ -MODx.window.UpdateElementProperty = function(config) { - config = config || {}; - Ext.applyIf(config,{ - title: _('property_update') - ,id: 'modx-window-element-property-update' - ,width: 600 - ,saveBtnText: _('done') - ,forceLayout: true - ,fields: [{ - layout: 'column' - ,border: false - ,defaults: { - layout: 'form' - ,labelAlign: 'top' - ,anchor: '100%' - ,border: false - } - ,items: [{ - columnWidth: .6 - ,items: [{ - fieldLabel: _('name') - ,description: MODx.expandHelp ? '' : _('property_name_desc') - ,name: 'name' - ,id: 'modx-uep-name' - ,xtype: 'textfield' - ,anchor: '100%' - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-uep-name' - ,html: _('property_name_desc') - ,cls: 'desc-under' - },{ - fieldLabel: _('description') - ,description: MODx.expandHelp ? '' : _('property_description_desc') - ,name: 'desc' - ,id: 'modx-uep-desc' - ,xtype: 'textarea' - ,anchor: '100%' - ,height: 120 - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-uep-description' - ,html: _('property_description_desc') - ,cls: 'desc-under' - }] - },{ - columnWidth: .4 - ,items: [{ - fieldLabel: _('type') - ,description: MODx.expandHelp ? '' : _('property_xtype_desc') - ,name: 'xtype' - ,xtype: 'modx-combo-xtype' - ,id: 'modx-uep-xtype' - ,anchor: '100%' - ,listeners: { - 'select': {fn:function(cb) { - var g = Ext.getCmp('modx-uep-grid-element-property-options'); - if (!g) return; - var v = cb.getValue(); - if (v == 'list' || v == 'color') { - g.show(); - } else { - g.hide(); - } - this.syncSize(); - },scope:this} - } - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-uep-xtype' - ,html: _('property_xtype_desc') - ,cls: 'desc-under' - },{ - xtype: 'textfield' - ,fieldLabel: _('lexicon') - ,description: MODx.expandHelp ? '' : _('property_lexicon_desc') - ,name: 'lexicon' - ,id: 'modx-uep-lexicon' - ,anchor: '100%' - ,allowBlank: true - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-uep-lexicon' - ,html: _('property_lexicon_desc') - ,cls: 'desc-under' - },{ - xtype: 'textfield' - ,fieldLabel: _('area') - ,description: MODx.expandHelp ? '' : _('property_area_desc') - ,name: 'area' - ,id: 'modx-uep-area' - ,anchor: '100%' - ,allowBlank: true - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-uep-area' - ,html: _('property_area_desc') - ,cls: 'desc-under' - }] - }] - },{ - xtype: 'hidden' - ,name: 'overridden' - ,id: 'modx-uep-overridden' - },{ - xtype: 'modx-element-value-field' - ,xtypeField: 'modx-uep-xtype' - ,name: 'value' - ,id: 'modx-uep-value' - ,anchor: '100%' - },{ - id: 'modx-uep-grid-element-property-options' - ,xtype: 'modx-grid-element-property-options' - ,autoHeight: true - }] - ,keys: [] +MODx.window.UpdateElementProperty = function(config = {}) { + Ext.applyIf(config, { + title: _('property_update'), + isUpdate: true }); - MODx.window.UpdateElementProperty.superclass.constructor.call(this,config); - this.on('show',this.onShow,this); + MODx.window.UpdateElementProperty.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.UpdateElementProperty,MODx.Window,{ - submit: function() { - var v = this.fp.getForm().getValues(); - - var g = Ext.getCmp('modx-uep-grid-element-property-options'); - var opt = eval(g.encode()); - Ext.apply(v,{ - options: opt - }); - - if (this.fp.getForm().isValid()) { - if (this.fireEvent('success',v)) { - this.fp.getForm().reset(); - this.hide(); - return true; - } - } - return false; - } - ,onShow: function() { - var g = Ext.getCmp('modx-uep-grid-element-property-options'); - if (!g) return; - if (this.fp.getForm().findField('xtype').getValue() == 'list' || this.fp.getForm().findField('xtype').getValue() == 'color') { - g.show(); - } else { - g.hide(); - } - g.getStore().removeAll(); - var gp = Ext.getCmp('modx-grid-element-properties'); - var rec = gp.getSelectionModel().getSelected(); - if (rec) { - var opt = rec.data.options; - var opts = []; - for (var x in opt) { - if (opt.hasOwnProperty(x)) { - opts.push([opt[x].text,opt[x].value]); - } - } - g.getStore().loadData(opts); - } - this.syncSize(); - this.center(); - } -}); -Ext.reg('modx-window-element-property-update',MODx.window.UpdateElementProperty); +Ext.extend(MODx.window.UpdateElementProperty, MODx.window.CreateElementProperty); +Ext.reg('modx-window-element-property-update', MODx.window.UpdateElementProperty); /** * @class MODx.window.CreateElementPropertyOption @@ -925,32 +924,31 @@ Ext.reg('modx-window-element-property-update',MODx.window.UpdateElementProperty) * @param {Object} config An object of configuration properties * @xtype modx-window-element-property-option-create */ -MODx.window.CreateElementPropertyOption = function(config) { - config = config || {}; - Ext.applyIf(config,{ - title: _('property_option_create') - ,id: 'modx-window-element-property-option-create' - ,saveBtnText: _('done') - ,fields: [{ - fieldLabel: _('name') - ,name: 'text' - ,id: 'modx-cepo-text' - ,xtype: 'textfield' - ,anchor: '100%' - },{ - fieldLabel: _('value') - ,name: 'value' - ,id: 'modx-cepo-value' - ,xtype: 'textfield' - ,anchor: '100%' +MODx.window.CreateElementPropertyOption = function(config = {}) { + Ext.applyIf(config, { + title: _('property_option_create'), + id: 'modx-window-element-property-option-create', + saveBtnText: _('done'), + fields: [{ + fieldLabel: _('name'), + name: 'text', + id: 'modx-cepo-text', + xtype: 'textfield', + anchor: '100%' + }, { + fieldLabel: _('value'), + name: 'value', + id: 'modx-cepo-value', + xtype: 'textfield', + anchor: '100%' }] }); - MODx.window.CreateElementPropertyOption.superclass.constructor.call(this,config); + MODx.window.CreateElementPropertyOption.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.CreateElementPropertyOption,MODx.Window,{ +Ext.extend(MODx.window.CreateElementPropertyOption, MODx.Window, { submit: function() { if (this.fp.getForm().isValid()) { - if (this.fireEvent('success',this.fp.getForm().getValues())) { + if (this.fireEvent('success', this.fp.getForm().getValues())) { this.fp.getForm().reset(); this.hide(); return true; @@ -959,9 +957,7 @@ Ext.extend(MODx.window.CreateElementPropertyOption,MODx.Window,{ return false; } }); -Ext.reg('modx-window-element-property-option-create',MODx.window.CreateElementPropertyOption); - - +Ext.reg('modx-window-element-property-option-create', MODx.window.CreateElementPropertyOption); /** * Displays a xtype combobox @@ -971,84 +967,78 @@ Ext.reg('modx-window-element-property-option-create',MODx.window.CreateElementPr * @param {Object} config An object of configuration properties * @xtype modx-combo-xtype */ -MODx.combo.xType = function(config) { - config = config || {}; - Ext.applyIf(config,{ +MODx.combo.xType = function(config = {}) { + Ext.applyIf(config, { store: new Ext.data.SimpleStore({ - fields: ['d','v'] - ,data: [ - [_('textfield'),'textfield'] - ,[_('textarea'),'textarea'] - ,[_('yesno'),'combo-boolean'] - ,[_('date'),'datefield'] - ,[_('list'),'list'] - ,[_('integer'),'numberfield'] - ,[_('file'),'file'] - ,[_('color'),'color'] + fields: ['d', 'v'], + data: [ + [_('textfield'), 'textfield'], + [_('textarea'), 'textarea'], + [_('yesno'), 'combo-boolean'], + [_('date'), 'datefield'], + [_('list'), 'list'], + [_('integer'), 'numberfield'], + [_('file'), 'file'], + [_('color'), 'color'] ] - }) - ,displayField: 'd' - ,valueField: 'v' - ,mode: 'local' - ,name: 'xtype' - ,hiddenName: 'xtype' - ,triggerAction: 'all' - ,editable: false - ,selectOnFocus: false - ,value: 'textfield' + }), + displayField: 'd', + valueField: 'v', + mode: 'local', + name: 'xtype', + hiddenName: 'xtype', + triggerAction: 'all', + editable: false, + selectOnFocus: false, + value: 'textfield' }); - MODx.combo.xType.superclass.constructor.call(this,config); + MODx.combo.xType.superclass.constructor.call(this, config); }; -Ext.extend(MODx.combo.xType,Ext.form.ComboBox); -Ext.reg('modx-combo-xtype',MODx.combo.xType); - - +Ext.extend(MODx.combo.xType, Ext.form.ComboBox); +Ext.reg('modx-combo-xtype', MODx.combo.xType); - -MODx.form.ElementValueField = function(config) { - config = config || {}; - Ext.applyIf(config,{ - fieldLabel: _('value') - ,name: 'value' - ,xtype: 'textfield' +MODx.form.ElementValueField = function(config = {}) { + Ext.applyIf(config, { + fieldLabel: _('value'), + name: 'value', + xtype: 'textfield' }); - MODx.form.ElementValueField.superclass.constructor.call(this,config); + MODx.form.ElementValueField.superclass.constructor.call(this, config); this.config = config; - this.on('change',this.checkValue,this); + this.on('change', this.checkValue, this); }; -Ext.extend(MODx.form.ElementValueField,Ext.form.TextField,{ - checkValue: function(fld,nv,ov) { - var t = Ext.getCmp(this.config.xtypeField).getValue(); - var v = fld.getValue(); - if (t == 'combo-boolean') { - v = (v == '1' || v == 'true' || v == 1 || v == true || v == _('yes') || v == 'yes') ? 1 : 0; - fld.setValue(v); +Ext.extend(MODx.form.ElementValueField, Ext.form.TextField, { + checkValue: function(field, newValue, oldValue) { + const xtype = Ext.getCmp(this.config.xtypeField).getValue(); + if (xtype === 'combo-boolean') { + let value = field.getValue(); + value = [1, '1', true, 'true', _('yes'), 'yes'].includes(value) ? 1 : 0; + field.setValue(value); } } }); -Ext.reg('modx-element-value-field',MODx.form.ElementValueField); - +Ext.reg('modx-element-value-field', MODx.form.ElementValueField); -MODx.combo.PropertySet = function(config) { - config = config || {}; - Ext.applyIf(config,{ - name: 'propertyset' - ,hiddenName: 'propertyset' - ,url: MODx.config.connector_url - ,baseParams: { - action: 'Element/PropertySet/GetList' - } - ,displayField: 'name' - ,valueField: 'id' - ,fields: ['id','name','description','properties'] - ,editable: false - ,value: 0 - ,pageSize: 10 +MODx.combo.PropertySet = function(config = {}) { + Ext.applyIf(config, { + name: 'propertyset', + hiddenName: 'propertyset', + url: MODx.config.connector_url, + baseParams: { + action: 'Element/PropertySet/GetList', + combo: true + }, + displayField: 'name', + valueField: 'id', + fields: ['id', 'name', 'description', 'properties'], + editable: false, + value: 0, + pageSize: 10 }); - MODx.combo.PropertySet.superclass.constructor.call(this,config); + MODx.combo.PropertySet.superclass.constructor.call(this, config); }; -Ext.extend(MODx.combo.PropertySet,MODx.combo.ComboBox); -Ext.reg('modx-combo-property-set',MODx.combo.PropertySet); +Ext.extend(MODx.combo.PropertySet, MODx.combo.ComboBox); +Ext.reg('modx-combo-property-set', MODx.combo.PropertySet); /** * @class MODx.window.AddPropertySet @@ -1056,115 +1046,116 @@ Ext.reg('modx-combo-property-set',MODx.combo.PropertySet); * @param {Object} config An object of configuration properties * @xtype modx-window-element-property-set-add */ -MODx.window.AddPropertySet = function(config) { - config = config || {}; - Ext.applyIf(config,{ - title: _('propertyset_add') - ,id: 'modx-window-element-property-set-add' - ,url: MODx.config.connector_url - ,action: 'Element/PropertySet/Associate' - ,autoHeight: true // makes window grow when the fieldset is toggled - ,fields: [{ - xtype: 'hidden' - ,name: 'elementId' - ,id: 'modx-aps-elementId' - },{ - xtype: 'hidden' - ,name: 'elementType' - ,id: 'modx-aps-elementType' - },{ - html: _('propertyset_panel_desc') - ,xtype: 'modx-description' +MODx.window.AddPropertySet = function(config = {}) { + Ext.applyIf(config, { + title: _('propertyset_add'), + id: 'modx-window-element-property-set-add', + url: MODx.config.connector_url, + action: 'Element/PropertySet/Associate', + autoHeight: true, // makes window grow when the fieldset is toggled + fields: [{ + xtype: 'hidden', + name: 'elementId' + }, { + xtype: 'hidden', + name: 'elementType' + }, { + html: _('propertyset_panel_desc'), + xtype: 'modx-description' - },MODx.PanelSpacer,{ - xtype: 'modx-combo-property-set' - ,fieldLabel: _('propertyset') - ,name: 'propertyset' - ,id: 'modx-aps-propertyset' - ,anchor: '100%' - ,baseParams: { - action: 'Element/PropertySet/GetList' - ,showNotAssociated: true - ,elementId: config.record.elementId - ,elementType: config.record.elementType - } - },{ - xtype: 'hidden' - ,name: 'propertyset_new' - ,id: 'modx-aps-propertyset-new' - ,value: false - },{ - xtype: 'fieldset' - ,title: _('propertyset_create_new') - ,autoHeight: true - ,checkboxToggle: true - ,collapsed: true - ,forceLayout: true - ,id: 'modx-aps-propertyset-new-fs' - ,listeners: { - 'expand': {fn:function(p) { - Ext.getCmp('modx-aps-propertyset-new').setValue(true); - this.center(); // re-centers window on screen after height changed - },scope:this} - ,'collapse': {fn:function(p) { - Ext.getCmp('modx-aps-propertyset-new').setValue(false); - this.center(); // re-centers window on screen after height changed - },scope:this} + }, MODx.PanelSpacer, { + xtype: 'modx-combo-property-set', + fieldLabel: _('propertyset'), + name: 'propertyset', + anchor: '100%', + baseParams: { + action: 'Element/PropertySet/GetList', + showNotAssociated: true, + elementId: config.record.elementId, + elementType: config.record.elementType, + combo: true } - ,items: [{ - xtype: 'textfield' - ,fieldLabel: _('name') - ,name: 'name' - ,id: 'modx-aps-name' - ,anchor: '100%' - },{ - xtype: 'textarea' - ,fieldLabel: _('description') - ,name: 'description' - ,id: 'modx-aps-description' - ,anchor: '100%' - ,grow: true + }, { + xtype: 'hidden', + name: 'propertyset_new', + id: 'modx-aps-propertyset-new', + value: false + }, { + xtype: 'fieldset', + title: _('propertyset_create_new'), + autoHeight: true, + checkboxToggle: true, + collapsed: true, + forceLayout: true, + listeners: { + expand: { + fn: function(p) { + Ext.getCmp('modx-aps-propertyset-new').setValue(true); + this.center(); + }, + scope: this + }, + collapse: { + fn: function(p) { + Ext.getCmp('modx-aps-propertyset-new').setValue(false); + this.center(); + }, + scope: this + } + }, + items: [{ + xtype: 'textfield', + fieldLabel: _('name'), + name: 'name', + anchor: '100%' + }, { + xtype: 'textarea', + fieldLabel: _('description'), + name: 'description', + anchor: '100%', + grow: true }] }] }); - MODx.window.AddPropertySet.superclass.constructor.call(this,config); + MODx.window.AddPropertySet.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.AddPropertySet,MODx.Window); -Ext.reg('modx-window-element-property-set-add',MODx.window.AddPropertySet); +Ext.extend(MODx.window.AddPropertySet, MODx.Window); +Ext.reg('modx-window-element-property-set-add', MODx.window.AddPropertySet); -MODx.window.ImportProperties = function(config) { - config = config || {}; - Ext.applyIf(config,{ - title: _('import') - ,id: 'modx-window-properties-import' - ,url: MODx.config.connector_url - ,action: 'Element/ImportProperties' - ,fileUpload: true - ,saveBtnText: _('import') - ,fields: [{ - html: _('properties_import_msg') - ,id: 'modx-impp-desc' - ,style: 'margin-bottom: 10px;' - ,xtype: 'modx-description' - },{ - xtype: 'fileuploadfield' - ,fieldLabel: _('file') - ,buttonText: _('upload.buttons.upload') - ,name: 'file' - ,id: 'modx-impp-file' - ,anchor: '100%' +MODx.window.ImportProperties = function(config = {}) { + Ext.applyIf(config, { + title: _('import'), + id: 'modx-window-properties-import', + url: MODx.config.connector_url, + action: 'Element/ImportProperties', + fileUpload: true, + saveBtnText: _('import'), + fields: [{ + html: _('properties_import_msg'), + style: 'margin-bottom: 10px;', + xtype: 'modx-description' + }, { + xtype: 'fileuploadfield', + fieldLabel: _('file'), + buttonText: _('upload.buttons.upload'), + name: 'file', + id: 'modx-impp-file', + anchor: '100%' }] }); - MODx.window.ImportProperties.superclass.constructor.call(this,config); - - // Trigger "fileselected" event - var fp = Ext.getCmp('modx-impp-file'); - var onFileUploadFieldFileSelected = function(fp, fakeFilePath) { - var fileApi = fp.fileInput.dom.files; - fp.el.dom.value = (typeof fileApi != 'undefined') ? fileApi[0].name : fakeFilePath.replace("C:\\fakepath\\", ""); - }; - fp.on('fileselected', onFileUploadFieldFileSelected); + MODx.window.ImportProperties.superclass.constructor.call(this, config); + const + fileCmp = Ext.getCmp('modx-impp-file'), + onFileUploadFieldFileSelected = function(fileCmp, fakeFilePath) { + const fileApi = fileCmp.fileInput.dom.files; + fileCmp.el.dom.value = (typeof fileApi != 'undefined') + ? fileApi[0].name + : fakeFilePath.replace('C:\\fakepath\\', '') + ; + } + ; + fileCmp.on('fileselected', onFileUploadFieldFileSelected); }; -Ext.extend(MODx.window.ImportProperties,MODx.Window); -Ext.reg('modx-window-properties-import',MODx.window.ImportProperties); +Ext.extend(MODx.window.ImportProperties, MODx.Window); +Ext.reg('modx-window-properties-import', MODx.window.ImportProperties); diff --git a/manager/assets/modext/widgets/element/modx.grid.template.tv.js b/manager/assets/modext/widgets/element/modx.grid.template.tv.js index d4e968a03c2..bb5ac83ccc4 100644 --- a/manager/assets/modext/widgets/element/modx.grid.template.tv.js +++ b/manager/assets/modext/widgets/element/modx.grid.template.tv.js @@ -24,7 +24,6 @@ MODx.grid.TemplateTV = function(config = {}) { 'caption', 'tv_rank', 'access', - 'perm', 'category_name', 'category' ], @@ -64,10 +63,13 @@ MODx.grid.TemplateTV = function(config = {}) { sortable: true, renderer: { fn: function(value, metadata, record) { - return this.renderLink(value, { - href: `?a=element/tv/update&id=${record.data.id}`, - target: '_blank' - }); + return this.userCanEditTv && this.userCanEditRecord(record, 'updateTv') + ? this.renderLink(value, { + href: `?a=element/tv/update&id=${record.data.id}`, + target: '_blank' + }) + : value + ; }, scope: this } @@ -112,16 +114,22 @@ MODx.grid.TemplateTV = function(config = {}) { ] }); MODx.grid.TemplateTV.superclass.constructor.call(this, config); + + // In this case, edit grid action indicates ability to edit the TV, not the Template + this.gridMenuActions = ['editTv']; + this.setUserCanEdit(['edit_template', 'save_template']); + this.setUserHasPermissions('editTv', ['edit_tv', 'save_tv']); + this.setShowActionsMenu(); + this.on('render', this.prepareDDSort, this); }; Ext.extend(MODx.grid.TemplateTV, MODx.grid.Grid, { getMenu: function() { const record = this.getSelectionModel().getSelected(), - permissions = record.data.perm, menu = [] ; - if (permissions.indexOf('pedit') !== -1) { + if (this.userCanEditTv && this.userCanEditRecord(record, 'updateTv')) { menu.push({ text: _('edit'), handler: this.updateTV diff --git a/manager/assets/modext/widgets/element/modx.grid.tv.security.js b/manager/assets/modext/widgets/element/modx.grid.tv.security.js index 297e1247b0d..ffdefc19cb0 100644 --- a/manager/assets/modext/widgets/element/modx.grid.tv.security.js +++ b/manager/assets/modext/widgets/element/modx.grid.tv.security.js @@ -6,44 +6,60 @@ * @param {Object} config An object of options. * @xtype modx-grid-tv-security */ -MODx.grid.TVSecurity = function(config) { - config = config || {}; - var tt = new Ext.ux.grid.CheckColumn({ - header: _('access') - ,dataIndex: 'access' - ,width: 40 - ,sortable: false +MODx.grid.TVSecurity = function(config = {}) { + const accessCheckboxCol = new Ext.ux.grid.CheckColumn({ + header: _('access'), + dataIndex: 'access', + width: 40, + sortable: false }); - Ext.applyIf(config,{ - id: 'modx-grid-tv-security' - ,url: MODx.config.connector_url - ,showActionsColumn: false - ,fields: ['id','name','access','menu'] - ,baseParams: { - action: 'Element/TemplateVar/ResourceGroup/GetList' - ,tv: config.tv - } - ,saveParams: { + Ext.applyIf(config, { + id: 'modx-grid-tv-security', + url: MODx.config.connector_url, + showActionsColumn: false, + fields: [ + 'id', + 'name', + 'access', + 'menu' + ], + baseParams: { + action: 'Element/TemplateVar/ResourceGroup/GetList', tv: config.tv - } - ,width: 800 - ,paging: true - ,remoteSort: true - ,plugins: tt - ,columns: [{ - header: _('name') - ,dataIndex: 'name' - ,width: 200 - ,sortable: true - ,renderer: { fn: function(v,md,record) { - return this.renderLink(v, { - href: '?a=security/resourcegroup' - ,target: '_blank' - }); - }, scope: this } - },tt] + }, + saveParams: { + tv: config.tv + }, + width: 800, + paging: true, + remoteSort: true, + plugins: accessCheckboxCol, + columns: [ + { + header: _('name'), + dataIndex: 'name', + width: 200, + sortable: true, + renderer: { + fn: function(value, metaData, record) { + return this.userCanEditResourceGroups + ? this.renderLink(value, { + href: '?a=security/resourcegroup', + target: '_blank' + }) + : value + ; + }, + scope: this + } + }, + accessCheckboxCol + ] }); - MODx.grid.TVSecurity.superclass.constructor.call(this,config); + MODx.grid.TVSecurity.superclass.constructor.call(this, config); + + this.setUserCanEdit(['edit_tv', 'save_tv']); + this.setUserHasPermissions('editResourceGroups', ['resourcegroup_view', 'resourcegroup_resource_list']); }; -Ext.extend(MODx.grid.TVSecurity,MODx.grid.Grid); -Ext.reg('modx-grid-tv-security',MODx.grid.TVSecurity); +Ext.extend(MODx.grid.TVSecurity, MODx.grid.Grid); +Ext.reg('modx-grid-tv-security', MODx.grid.TVSecurity); diff --git a/manager/assets/modext/widgets/element/modx.grid.tv.template.js b/manager/assets/modext/widgets/element/modx.grid.tv.template.js index ce61407d7d2..72a25fe2915 100644 --- a/manager/assets/modext/widgets/element/modx.grid.tv.template.js +++ b/manager/assets/modext/widgets/element/modx.grid.tv.template.js @@ -46,10 +46,13 @@ MODx.grid.TemplateVarTemplate = function(config = {}) { sortable: true, renderer: { fn: function(value, metadata, record) { - return this.renderLink(value, { - href: `?a=element/template/update&id=${record.data.id}`, - target: '_blank' - }); + return this.userCanEditTemplate && this.userCanEditRecord(record, 'updateTemplate') + ? this.renderLink(value, { + href: `?a=element/template/update&id=${record.data.id}`, + target: '_blank' + }) + : value + ; }, scope: this } @@ -86,6 +89,9 @@ MODx.grid.TemplateVarTemplate = function(config = {}) { ] }); MODx.grid.TemplateVarTemplate.superclass.constructor.call(this, config); + + this.setUserCanEdit(['edit_tv', 'save_tv']); + this.setUserHasPermissions('editTemplate', ['edit_template', 'save_template']); }; Ext.extend(MODx.grid.TemplateVarTemplate, MODx.grid.Grid); Ext.reg('modx-grid-tv-template', MODx.grid.TemplateVarTemplate); diff --git a/manager/assets/modext/widgets/element/modx.panel.property.set.js b/manager/assets/modext/widgets/element/modx.panel.property.set.js index f51af014cf9..0002703bcce 100644 --- a/manager/assets/modext/widgets/element/modx.panel.property.set.js +++ b/manager/assets/modext/widgets/element/modx.panel.property.set.js @@ -4,60 +4,59 @@ * @param {Object} config An object of config properties * @xtype modx-panel-property-sets */ -MODx.panel.PropertySet = function(config) { - config = config || {}; - Ext.applyIf(config,{ - id: 'modx-panel-property-sets' - ,cls: 'container' - ,items: [{ - html: _('propertysets') - ,xtype: 'modx-header' - },MODx.getPageStructure([{ - title: _('propertysets') - ,layout: 'form' - ,id: 'modx-property-set-form' - ,border: true - ,items: [{ - html: '

    '+_('propertysets_desc')+'

    ' - ,id: 'modx-property-set-msg' - ,xtype: 'modx-description' - },{ - layout: 'column' - ,border: false - ,cls: 'main-wrapper' - ,items: [{ - columnWidth: .3 - ,cls: 'left-col' - ,border: false - ,layout: 'anchor' - ,items: [{ - xtype: 'modx-tree-property-sets' - ,preventRender: true - ,anchor: '100%' +MODx.panel.PropertySet = function(config = {}) { + Ext.applyIf(config, { + id: 'modx-panel-property-sets', + cls: 'container', + items: [{ + html: _('propertysets'), + xtype: 'modx-header' + }, MODx.getPageStructure([{ + title: _('propertysets'), + layout: 'form', + id: 'modx-property-set-form', + border: true, + items: [{ + html: `

    ${_('propertysets_desc')}

    `, + id: 'modx-property-set-msg', + xtype: 'modx-description' + }, { + layout: 'column', + border: false, + cls: 'main-wrapper', + items: [{ + columnWidth: 0.3, + cls: 'left-col', + border: false, + layout: 'anchor', + items: [{ + xtype: 'modx-tree-property-sets', + preventRender: true, + anchor: '100%' }] - },{ - columnWidth: .7 - ,layout: 'form' - ,border: false - ,autoHeight: true - ,id: 'right-column' - ,items: [] + }, { + columnWidth: 0.7, + layout: 'form', + border: false, + autoHeight: true, + id: 'right-column', + items: [] }] }] }])] }); - MODx.panel.PropertySet.superclass.constructor.call(this,config); + MODx.panel.PropertySet.superclass.constructor.call(this, config); /* load after b/c of safari/ie focus bug */ (function() { Ext.getCmp('right-column').add({ - xtype: 'modx-grid-property-set-properties' - ,id: 'modx-grid-element-properties' + xtype: 'modx-grid-property-set-properties', + id: 'modx-grid-element-properties' }); }).defer(50, this); }; -Ext.extend(MODx.panel.PropertySet,MODx.FormPanel); -Ext.reg('modx-panel-property-sets',MODx.panel.PropertySet); +Ext.extend(MODx.panel.PropertySet, MODx.FormPanel); +Ext.reg('modx-panel-property-sets', MODx.panel.PropertySet); /** * @class MODx.grid.PropertySetProperties @@ -65,43 +64,50 @@ Ext.reg('modx-panel-property-sets',MODx.panel.PropertySet); * @param {Object} config An object of config properties * @xtype modx-grid-property-set-properties */ -MODx.grid.PropertySetProperties = function(config) { - config = config || {}; - Ext.applyIf(config,{ - autoHeight: true - ,lockProperties: false - ,tbar: [{ - xtype: 'modx-combo-property-set' - ,id: 'modx-combo-property-set' - ,baseParams: { - action: 'Element/PropertySet/GetList' - } - ,listeners: { - 'select': {fn:function(cb) { Ext.getCmp('modx-grid-element-properties').changePropertySet(cb); },scope:this} - } - ,value: '' - },{ - text: _('property_create') - ,handler: function(btn,e) { - if (Ext.getCmp('modx-combo-property-set').value != '') { - Ext.getCmp('modx-grid-element-properties').create(btn,e); +MODx.grid.PropertySetProperties = function(config = {}) { + Ext.applyIf(config, { + autoHeight: true, + lockProperties: false, + tbar: [{ + xtype: 'modx-combo-property-set', + id: 'modx-combo-property-set', + baseParams: { + action: 'Element/PropertySet/GetList', + combo: true + }, + listeners: { + select: { + fn: function(cb) { + Ext.getCmp('modx-grid-element-properties').changePropertySet(cb); + }, + scope: this + } + }, + value: '' + }, { + text: _('property_create'), + id: 'modx-btn-property-create', + handler: function(btn, e) { + if (Ext.getCmp('modx-combo-property-set').value !== '') { + Ext.getCmp('modx-grid-element-properties').create(btn, e); } else { MODx.msg.alert('', _('propertyset_err_ns')); } - } - ,scope: this - },'->',{ - text: _('propertyset_save') - ,cls: 'primary-button' - ,handler: function() { Ext.getCmp('modx-grid-element-properties').save(); } - ,scope: this + }, + scope: this + }, '->', { + text: _('propertyset_save'), + id: 'modx-btn-property-set-save', + cls: 'primary-button', + handler: function() { Ext.getCmp('modx-grid-element-properties').save(); }, + scope: this }] }); Ext.getCmp('right-column').disable(); - MODx.grid.PropertySetProperties.superclass.constructor.call(this,config); + MODx.grid.PropertySetProperties.superclass.constructor.call(this, config); }; -Ext.extend(MODx.grid.PropertySetProperties,MODx.grid.ElementProperties); -Ext.reg('modx-grid-property-set-properties',MODx.grid.PropertySetProperties); +Ext.extend(MODx.grid.PropertySetProperties, MODx.grid.ElementProperties); +Ext.reg('modx-grid-property-set-properties', MODx.grid.PropertySetProperties); /** * @class MODx.tree.PropertySets @@ -109,199 +115,232 @@ Ext.reg('modx-grid-property-set-properties',MODx.grid.PropertySetProperties); * @param {Object} config An object of config properties * @xtype modx-tree-property-sets */ -MODx.tree.PropertySets = function(config) { - config = config || {}; - Ext.applyIf(config,{ - title: _('propertysets') - ,url: MODx.config.connector_url - ,action: 'Element/PropertySet/GetNodes' - ,rootIconCls: 'icon-sitemap' - ,root_name: _('propertysets') - ,rootVisible: false - ,enableDD: false - ,tbar: ['->', { - text: _('propertyset_new') - ,cls: 'primary-button' - ,handler: this.createSet - ,scope: this - }] - ,useDefaultToolbar: true +MODx.tree.PropertySets = function(config = {}) { + Ext.applyIf(config, { + title: _('propertysets'), + url: MODx.config.connector_url, + action: 'Element/PropertySet/GetNodes', + rootIconCls: 'icon-sitemap', + root_name: _('propertysets'), + rootVisible: false, + enableDD: false, + tbar: ['->', { + text: _('propertyset_new'), + cls: 'primary-button', + handler: this.createSet, + hidden: !MODx.perm.new_propertyset || !MODx.perm.save_propertyset, + scope: this + }], + useDefaultToolbar: true }); - MODx.tree.PropertySets.superclass.constructor.call(this,config); - this.on('click',this.loadGrid,this); + MODx.tree.PropertySets.superclass.constructor.call(this, config); + this.on('click', this.loadGrid, this); }; -Ext.extend(MODx.tree.PropertySets,MODx.tree.Tree,{ - loadGrid: function(n,e) { - Ext.getCmp('right-column').enable(); - var ar = n.id.split('_'); - if (ar[0] == 'ps') { - MODx.Ajax.request({ - url: MODx.config.connector_url - ,params: { - action: 'Element/PropertySet/GetProperties' - ,id: ar[1] +Ext.extend(MODx.tree.PropertySets, MODx.tree.Tree, { + loadGrid: function(node, e) { + const + [recordType, setId, elId, elType] = node.id.split('_'), + propsGrid = Ext.getCmp('modx-grid-element-properties'), + propSetCombo = Ext.getCmp('modx-combo-property-set'), + setGridData = (response, setId, elId = null, elType = null) => { + const + data = response.object, + store = propsGrid.getStore() + ; + propsGrid.defaultProperties = data; + if (elId && elType) { + propsGrid.config.elementId = elId; + propsGrid.config.elementType = elType; + } else { + delete propsGrid.config.elementId; + delete propsGrid.config.elementType; } - ,listeners: { - 'success': {fn:function(r) { - var d = r.object; - var g = Ext.getCmp('modx-grid-element-properties'); - var s = g.getStore(); - g.defaultProperties = d; - delete g.config.elementId; - delete g.config.elementType; - s.removeAll(); - s.loadData(d); + store.removeAll(); + store.loadData(data); + propSetCombo.setValue(setId); + } + ; + Ext.getCmp('right-column').enable(); - Ext.getCmp('modx-combo-property-set').setValue(ar[1]); - },scope:this} + if (recordType === 'ps') { + MODx.Ajax.request({ + url: MODx.config.connector_url, + params: { + action: 'Element/PropertySet/GetProperties', + id: setId + }, + listeners: { + success: { + fn: response => { + setGridData(response, setId); + } + } } }); - } else if (ar[0] == 'el' && ar[2] && ar[3]) { + } else if (recordType === 'el' && elId && elType) { MODx.Ajax.request({ - url: MODx.config.connector_url - ,params: { - action: 'Element/PropertySet/GetProperties' - ,id: ar[1] - ,element: ar[2] - ,element_class: ar[3] - } - ,listeners: { - 'success': {fn:function(r) { - var d = r.object; - var g = Ext.getCmp('modx-grid-element-properties'); - var s = g.getStore(); - g.defaultProperties = d; - g.config.elementId = ar[2]; - g.config.elementType = ar[3]; - s.removeAll(); - s.loadData(d); - - Ext.getCmp('modx-combo-property-set').setValue(ar[1]); - },scope:this} + url: MODx.config.connector_url, + params: { + action: 'Element/PropertySet/GetProperties', + id: setId, + element: elId, + element_class: elType + }, + listeners: { + success: { + fn: response => { + setGridData(response, setId, elId, elType); + } + } } }); } - } + }, - ,createSet: function(btn,e) { + createSet: function(btn, e) { if (!this.winCreateSet) { this.winCreateSet = MODx.load({ - xtype: 'modx-window-property-set-create' - ,listeners: { - 'success':{fn:function() { - this.refresh(); - Ext.getCmp('modx-combo-property-set').store.reload(); - },scope:this} + xtype: 'modx-window-property-set-create', + listeners: { + success: { + fn: function() { + this.refresh(); + Ext.getCmp('modx-combo-property-set').store.reload(); + }, + scope: this + } } }); } this.winCreateSet.reset(); this.winCreateSet.show(e.target); - } + }, - ,duplicateSet: function(btn,e) { - var id = this.cm.activeNode.id.split('_'); - var r = this.cm.activeNode.attributes.data; - r.id = id[1]; - r.new_name = _('duplicate_of',{name:r.name}); + duplicateSet: function(btn, e) { + const + [, setId] = this.cm.activeNode.id.split('_'), + record = this.cm.activeNode.attributes.data + ; + record.id = setId; + record.new_name = _('duplicate_of', { name: record.name }); if (!this.winDupeSet) { this.winDupeSet = MODx.load({ - xtype: 'modx-window-property-set-duplicate' - ,record: r - ,listeners: { - 'success':{fn:function() { - this.refresh(); - Ext.getCmp('modx-combo-property-set').store.reload(); - },scope:this} + xtype: 'modx-window-property-set-duplicate', + record: record, + listeners: { + success: { + fn: function() { + this.refresh(); + Ext.getCmp('modx-combo-property-set').store.reload(); + }, + scope: this + } } }); } - this.winDupeSet.setValues(r); + this.winDupeSet.setValues(record); this.winDupeSet.show(e.target); - } + }, - ,updateSet: function(btn,e) { - var id = this.cm.activeNode.id.split('_'); - var r = this.cm.activeNode.attributes.data; - r.id = id[1]; + updateSet: function(btn, e) { + const + [, setId] = this.cm.activeNode.id.split('_'), + record = this.cm.activeNode.attributes.data + ; + record.id = setId; if (!this.winUpdateSet) { this.winUpdateSet = MODx.load({ - xtype: 'modx-window-property-set-update' - ,record: r - ,listeners: { - 'success':{fn:function() { - this.refresh(); - Ext.getCmp('modx-combo-property-set').store.reload(); - },scope:this} + xtype: 'modx-window-property-set-update', + record: record, + listeners: { + success: { + fn: function() { + this.refresh(); + Ext.getCmp('modx-combo-property-set').store.reload(); + }, + scope: this + } } }); } - this.winUpdateSet.setValues(r); + this.winUpdateSet.setValues(record); this.winUpdateSet.show(e.target); - } + }, - ,removeSet: function(btn,e) { - var id = this.cm.activeNode.id.split('_'); - id = id[1]; + removeSet: function(btn, e) { + const [, setId] = this.cm.activeNode.id.split('_'); MODx.msg.confirm({ - text: _('propertyset_remove_confirm') - ,url: MODx.config.connector_url - ,params: { - action: 'Element/PropertySet/Remove' - ,id: id - } - ,listeners: { - 'success': {fn:function() { - this.refreshNode(this.cm.activeNode.id); - var g = Ext.getCmp('modx-grid-element-properties'); - g.getStore().removeAll(); - g.defaultProperties = []; - Ext.getCmp('modx-combo-property-set').setValue(''); - },scope:this} + text: _('propertyset_remove_confirm'), + url: MODx.config.connector_url, + params: { + action: 'Element/PropertySet/Remove', + id: setId + }, + listeners: { + success: { + fn: function() { + this.refreshNode(this.cm.activeNode.id); + const propsGrid = Ext.getCmp('modx-grid-element-properties'); + propsGrid.getStore().removeAll(); + propsGrid.defaultProperties = []; + Ext.getCmp('modx-combo-property-set').setValue(''); + }, + scope: this + } } }); - } - - ,addElement: function(btn,e) { - var id = this.cm.activeNode.id.split('_'); id = id[1]; - var t = this.cm.activeNode.text; - var r = { - propertysetName: this.cm.activeNode.text - ,propertyset: id - }; + }, + addElement: function(btn, e) { + const + [, setId] = this.cm.activeNode.id.split('_'), + record = { + propertysetName: this.cm.activeNode.text, + propertyset: setId + } + ; if (!this.winPSEA) { this.winPSEA = MODx.load({ - xtype: 'modx-window-propertyset-element-add' - ,record: r - ,listeners: { - 'success':{fn:function() { this.refreshNode(this.cm.activeNode.id,true); },scope:this} + xtype: 'modx-window-propertyset-element-add', + record: record, + listeners: { + success: { + fn: function() { + this.refreshNode(this.cm.activeNode.id, true); + }, + scope: this + } } }); } this.winPSEA.fp.getForm().reset(); - this.winPSEA.fp.getForm().setValues(r); + this.winPSEA.fp.getForm().setValues(record); this.winPSEA.show(e.target); - } + }, - ,removeElement: function(btn,e) { - var d = this.cm.activeNode.attributes; + removeElement: function(btn, e) { + const { attributes } = this.cm.activeNode; MODx.msg.confirm({ - text: _('propertyset_element_remove_confirm') - ,url: MODx.config.connector_url - ,params: { - action: 'Element/PropertySet/RemoveElement' - ,element: d.pk - ,element_class: d.element_class - ,propertyset: d.propertyset - } - ,listeners: { - 'success': {fn:function() { this.refreshNode(this.cm.activeNode.id); },scope:this} + text: _('propertyset_element_remove_confirm'), + url: MODx.config.connector_url, + params: { + action: 'Element/PropertySet/RemoveElement', + element: attributes.pk, + element_class: attributes.element_class, + propertyset: attributes.propertyset + }, + listeners: { + success: { + fn: function() { + this.refreshNode(this.cm.activeNode.id); + }, + scope: this + } } }); } }); -Ext.reg('modx-tree-property-sets',MODx.tree.PropertySets); +Ext.reg('modx-tree-property-sets', MODx.tree.PropertySets); /** * @class MODx.window.AddElementToPropertySet @@ -309,60 +348,61 @@ Ext.reg('modx-tree-property-sets',MODx.tree.PropertySets); * @param {Object} config An object of configuration properties * @xtype modx-window-propertyset-element-add */ -MODx.window.AddElementToPropertySet = function(config) { - config = config || {}; - Ext.applyIf(config,{ - title: _('propertyset_element_add') - ,url: MODx.config.connector_url - ,baseParams: { +MODx.window.AddElementToPropertySet = function(config = {}) { + Ext.applyIf(config, { + title: _('propertyset_element_add'), + url: MODx.config.connector_url, + baseParams: { action: 'Element/PropertySet/AddElement' - } - ,fields: [{ - xtype: 'hidden' - ,name: 'propertyset' - },{ - xtype: 'statictextfield' - ,fieldLabel: _('propertyset') - ,name: 'propertysetName' - ,anchor: '100%' - },{ - xtype: 'modx-combo-element-class' - ,fieldLabel: _('class_name') - ,name: 'element_class' - ,id: 'modx-combo-element-class' - ,anchor: '100%' - ,listeners: { - 'select': {fn:this.onClassSelect,scope:this} + }, + fields: [{ + xtype: 'hidden', + name: 'propertyset' + }, { + xtype: 'statictextfield', + fieldLabel: _('propertyset'), + name: 'propertysetName', + anchor: '100%' + }, { + xtype: 'modx-combo-element-class', + fieldLabel: _('class_name'), + name: 'element_class', + id: 'modx-combo-element-class', + anchor: '100%', + listeners: { + select: { fn: this.onClassSelect, scope: this } } - },{ - xtype: 'modx-combo-elements' - ,fieldLabel: _('element') - ,name: 'element' - ,id: 'modx-combo-elements' - ,anchor: '100%' - ,listeners: { - 'select': {fn:this.onElementSelect,scope:this} + }, { + xtype: 'modx-combo-elements', + fieldLabel: _('element'), + name: 'element', + id: 'modx-combo-elements', + anchor: '100%', + listeners: { + select: { fn: this.onElementSelect, scope: this } } }] }); - MODx.window.AddElementToPropertySet.superclass.constructor.call(this,config); + MODx.window.AddElementToPropertySet.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.AddElementToPropertySet,MODx.Window,{ - onClassSelect: function(cb) { - var e = Ext.getCmp('modx-combo-elements'); - var s = e.store; - s.baseParams.element_class = cb.getValue(); - s.load(); - e.setValue(''); - } - ,onElementSelect: function(cb) { - var ec = Ext.getCmp('modx-combo-element-class'); - if (ec.getValue() === '') { - ec.setValue('MODX\\Revolution\\modSnippet'); +Ext.extend(MODx.window.AddElementToPropertySet, MODx.Window, { + onClassSelect: function(classCombo) { + const + elCombo = Ext.getCmp('modx-combo-elements'), + { store } = elCombo + ; + store.baseParams.element_class = classCombo.getValue(); + store.load(); + elCombo.setValue(''); + }, + onElementSelect: function(elCombo) { + const elType = Ext.getCmp('modx-combo-element-class'); + if (elType.getValue() === '') { + elType.setValue('MODX\\Revolution\\modSnippet'); } } }); -Ext.reg('modx-window-propertyset-element-add',MODx.window.AddElementToPropertySet); +Ext.reg('modx-window-propertyset-element-add', MODx.window.AddElementToPropertySet); /** * @class MODx.combo.ElementClass @@ -370,25 +410,24 @@ Ext.reg('modx-window-propertyset-element-add',MODx.window.AddElementToPropertySe * @param {Object} config An object of configuration properties * @xtype modx-combo-element-class */ -MODx.combo.ElementClass = function(config) { - config = config || {}; - Ext.applyIf(config,{ - name: 'element_class' - ,hiddenName: 'element_class' - ,displayField: 'name' - ,valueField: 'name' - ,fields: ['name'] - ,pageSize: 20 - ,editable: false - ,url: MODx.config.connector_url - ,baseParams: { +MODx.combo.ElementClass = function(config = {}) { + Ext.applyIf(config, { + name: 'element_class', + hiddenName: 'element_class', + displayField: 'name', + valueField: 'name', + fields: ['name'], + pageSize: 20, + editable: false, + url: MODx.config.connector_url, + baseParams: { action: 'Element/GetClasses' } }); - MODx.combo.ElementClass.superclass.constructor.call(this,config); + MODx.combo.ElementClass.superclass.constructor.call(this, config); }; -Ext.extend(MODx.combo.ElementClass,MODx.combo.ComboBox); -Ext.reg('modx-combo-element-class',MODx.combo.ElementClass); +Ext.extend(MODx.combo.ElementClass, MODx.combo.ComboBox); +Ext.reg('modx-combo-element-class', MODx.combo.ElementClass); /** * @class MODx.combo.Elements @@ -396,26 +435,25 @@ Ext.reg('modx-combo-element-class',MODx.combo.ElementClass); * @param {Object} config An object of configuration properties * @xtype modx-combo-elements */ -MODx.combo.Elements = function(config) { - config = config || {}; - Ext.applyIf(config,{ - name: 'element' - ,hiddenName: 'element' - ,displayField: 'name' - ,valueField: 'id' - ,fields: ['id','name'] - ,pageSize: 20 - ,editable: false - ,url: MODx.config.connector_url - ,baseParams: { - action: 'Element/GetListByClass' - ,element_class: 'MODX\\Revolution\\modSnippet' +MODx.combo.Elements = function(config = {}) { + Ext.applyIf(config, { + name: 'element', + hiddenName: 'element', + displayField: 'name', + valueField: 'id', + fields: ['id', 'name'], + pageSize: 20, + editable: false, + url: MODx.config.connector_url, + baseParams: { + action: 'Element/GetListByClass', + element_class: 'MODX\\Revolution\\modSnippet' } }); - MODx.combo.Elements.superclass.constructor.call(this,config); + MODx.combo.Elements.superclass.constructor.call(this, config); }; -Ext.extend(MODx.combo.Elements,MODx.combo.ComboBox); -Ext.reg('modx-combo-elements',MODx.combo.Elements); +Ext.extend(MODx.combo.Elements, MODx.combo.ComboBox); +Ext.reg('modx-combo-elements', MODx.combo.Elements); /** * @class MODx.window.CreatePropertySet @@ -423,45 +461,43 @@ Ext.reg('modx-combo-elements',MODx.combo.Elements); * @param {Object} config An object of configuration properties * @xtype modx-window-property-set-create */ -MODx.window.CreatePropertySet = function(config) { - config = config || {}; - Ext.applyIf(config,{ - title: _('propertyset_create') - ,url: MODx.config.connector_url - ,baseParams: { +MODx.window.CreatePropertySet = function(config = {}) { + Ext.applyIf(config, { + title: _('propertyset_create'), + url: MODx.config.connector_url, + baseParams: { action: 'Element/PropertySet/Create' - } - ,autoHeight: true - ,fields: [{ - xtype: 'hidden' - ,name: 'id' - },{ - xtype: 'textfield' - ,fieldLabel: _('name') - ,name: 'name' - ,anchor: '100%' - ,allowBlank: false - ,maxLength: 50 - },{ - xtype: 'modx-combo-category' - ,fieldLabel: _('category') - ,name: 'category' - ,anchor: '100%' - ,allowBlank: true - },{ - xtype: 'textarea' - ,fieldLabel: _('description') - ,name: 'description' - ,anchor: '100%' - ,grow: true - ,maxLength: 255 - }] - ,keys: [] + }, + autoHeight: true, + fields: [{ + xtype: 'hidden', + name: 'id' + }, { + xtype: 'textfield', + fieldLabel: _('name'), + name: 'name', + anchor: '100%', + allowBlank: false, + maxLength: 50 + }, { + xtype: 'modx-combo-category', + fieldLabel: _('category'), + name: 'category', + anchor: '100%' + }, { + xtype: 'textarea', + fieldLabel: _('description'), + name: 'description', + anchor: '100%', + grow: true, + maxLength: 255 + }], + keys: [] }); - MODx.window.CreatePropertySet.superclass.constructor.call(this,config); + MODx.window.CreatePropertySet.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.CreatePropertySet,MODx.Window); -Ext.reg('modx-window-property-set-create',MODx.window.CreatePropertySet); +Ext.extend(MODx.window.CreatePropertySet, MODx.Window); +Ext.reg('modx-window-property-set-create', MODx.window.CreatePropertySet); /** * @class MODx.window.UpdatePropertySet @@ -469,19 +505,18 @@ Ext.reg('modx-window-property-set-create',MODx.window.CreatePropertySet); * @param {Object} config An object of configuration properties * @xtype modx-window-property-set-update */ -MODx.window.UpdatePropertySet = function(config) { - config = config || {}; - Ext.applyIf(config,{ - title: _('propertyset_update') - ,baseParams: { +MODx.window.UpdatePropertySet = function(config = {}) { + Ext.applyIf(config, { + title: _('propertyset_update'), + baseParams: { action: 'Element/PropertySet/Update' - } - ,autoHeight: true + }, + autoHeight: true }); - MODx.window.UpdatePropertySet.superclass.constructor.call(this,config); + MODx.window.UpdatePropertySet.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.UpdatePropertySet,MODx.window.CreatePropertySet); -Ext.reg('modx-window-property-set-update',MODx.window.UpdatePropertySet); +Ext.extend(MODx.window.UpdatePropertySet, MODx.window.CreatePropertySet); +Ext.reg('modx-window-property-set-update', MODx.window.UpdatePropertySet); /** * @class MODx.window.DuplicatePropertySet @@ -489,36 +524,35 @@ Ext.reg('modx-window-property-set-update',MODx.window.UpdatePropertySet); * @param {Object} config An object of configuration properties * @xtype modx-window-property-set-duplicate */ -MODx.window.DuplicatePropertySet = function(config) { - config = config || {}; - Ext.applyIf(config,{ - title: _('propertyset_duplicate') - ,url: MODx.config.connector_url - ,baseParams: { +MODx.window.DuplicatePropertySet = function(config = {}) { + Ext.applyIf(config, { + title: _('propertyset_duplicate'), + url: MODx.config.connector_url, + baseParams: { action: 'Element/PropertySet/Duplicate' - } - ,autoHeight: true - ,fields: [{ - xtype: 'hidden' - ,name: 'id' - ,id: 'modx-dpropset-id' - },{ - xtype: 'textfield' - ,fieldLabel: _('new_name') - ,name: 'name' - ,anchor: '100%' - ,value: _('duplicate_of',{name:config.record.name}) - ,maxLength: 50 - },{ - xtype: 'xcheckbox' - ,boxLabel: _('propertyset_duplicate_copyels') - ,hideLabel: true - ,name: 'copyels' - ,id: 'modx-dpropset-copyels' - ,checked: true + }, + autoHeight: true, + fields: [{ + xtype: 'hidden', + name: 'id', + id: 'modx-dpropset-id' + }, { + xtype: 'textfield', + fieldLabel: _('new_name'), + name: 'name', + anchor: '100%', + value: _('duplicate_of', { name: config.record.name }), + maxLength: 50 + }, { + xtype: 'xcheckbox', + boxLabel: _('propertyset_duplicate_copyels'), + hideLabel: true, + name: 'copyels', + id: 'modx-dpropset-copyels', + checked: true }] }); - MODx.window.DuplicatePropertySet.superclass.constructor.call(this,config); + MODx.window.DuplicatePropertySet.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.DuplicatePropertySet,MODx.Window); -Ext.reg('modx-window-property-set-duplicate',MODx.window.DuplicatePropertySet); +Ext.extend(MODx.window.DuplicatePropertySet, MODx.Window); +Ext.reg('modx-window-property-set-duplicate', MODx.window.DuplicatePropertySet); diff --git a/manager/assets/modext/widgets/element/modx.panel.tv.js b/manager/assets/modext/widgets/element/modx.panel.tv.js index 68480d95677..b02049f199d 100644 --- a/manager/assets/modext/widgets/element/modx.panel.tv.js +++ b/manager/assets/modext/widgets/element/modx.panel.tv.js @@ -1651,7 +1651,11 @@ MODx.grid.ElementSources = function(config = {}) { src.getStore().load(); Ext.applyIf(config, { id: 'modx-grid-element-sources', - fields: ['context_key', 'source', 'name'], + fields: [ + 'context_key', + 'source', + 'name' + ], showActionsColumn: false, autoHeight: true, primaryKey: 'id', @@ -1659,11 +1663,14 @@ MODx.grid.ElementSources = function(config = {}) { header: _('context'), dataIndex: 'context_key', renderer: { - fn: function(v, md, record) { - return this.renderLink(v, { - href: `?a=context/update&key=${v}`, - target: '_blank' - }); + fn: function(value, metaData, record) { + return this.userCanEditContexts + ? this.renderLink(value, { + href: `?a=context/update&key=${value}`, + target: '_blank' + }) + : value + ; }, scope: this } @@ -1676,11 +1683,14 @@ MODx.grid.ElementSources = function(config = {}) { }] }); MODx.grid.ElementSources.superclass.constructor.call(this, config); - this.propRecord = Ext.data.Record.create(['context_key', 'source']); + + this.propRecord = Ext.data.Record.create([ + 'context_key', + 'source' + ]); + + this.setUserCanEdit(['edit_tv', 'save_tv']); + this.setUserHasPermissions('editContexts', ['edit_context', 'save_context']); }; -Ext.extend(MODx.grid.ElementSources, MODx.grid.LocalGrid, { - getMenu: function() { - return []; - } -}); +Ext.extend(MODx.grid.ElementSources, MODx.grid.LocalGrid); Ext.reg('modx-grid-element-sources', MODx.grid.ElementSources); diff --git a/manager/assets/modext/widgets/fc/modx.grid.fcprofile.js b/manager/assets/modext/widgets/fc/modx.grid.fcprofile.js index d397e471b2d..6ceab8488ba 100644 --- a/manager/assets/modext/widgets/fc/modx.grid.fcprofile.js +++ b/manager/assets/modext/widgets/fc/modx.grid.fcprofile.js @@ -4,37 +4,39 @@ * @param {Object} config An object of configuration options * @xtype modx-panel-fc-profiles */ -MODx.panel.FCProfiles = function(config) { - config = config || {}; - Ext.applyIf(config,{ - id: 'modx-panel-fc-profiles' - ,cls: 'container' - ,defaults: { collapsible: false ,autoHeight: true } - ,items: [{ - html: _('form_customization') - ,id: 'modx-fcp-header' - ,xtype: 'modx-header' - },MODx.getPageStructure([{ - title: _('profiles') - ,autoHeight: true - ,layout: "form" - ,items: [{ - html: '

    '+_('form_customization_msg')+'

    ' - ,xtype: 'modx-description' - },{ - title: '' - ,preventRender: true - ,xtype: 'modx-grid-fc-profile' - ,cls:'main-wrapper' +MODx.panel.FCProfiles = function(config = {}) { + Ext.applyIf(config, { + id: 'modx-panel-fc-profiles', + cls: 'container', + defaults: { + collapsible: false, + autoHeight: true + }, + items: [{ + html: _('form_customization'), + id: 'modx-fcp-header', + xtype: 'modx-header' + }, MODx.getPageStructure([{ + title: _('profiles'), + autoHeight: true, + layout: 'form', + items: [{ + html: `

    ${_('form_customization_msg')}

    `, + xtype: 'modx-description' + }, { + title: '', + preventRender: true, + xtype: 'modx-grid-fc-profile', + cls: 'main-wrapper' }] - }],{ + }], { id: 'modx-form-customization-tabs' })] }); - MODx.panel.FCProfiles.superclass.constructor.call(this,config); + MODx.panel.FCProfiles.superclass.constructor.call(this, config); }; -Ext.extend(MODx.panel.FCProfiles,MODx.FormPanel); -Ext.reg('modx-panel-fc-profiles',MODx.panel.FCProfiles); +Ext.extend(MODx.panel.FCProfiles, MODx.FormPanel); +Ext.reg('modx-panel-fc-profiles', MODx.panel.FCProfiles); /** * @class MODx.grid.FCProfile @@ -42,273 +44,276 @@ Ext.reg('modx-panel-fc-profiles',MODx.panel.FCProfiles); * @param {Object} config An object of configuration properties * @xtype modx-grid-fc-profile */ -MODx.grid.FCProfile = function(config) { - config = config || {}; +MODx.grid.FCProfile = function(config = {}) { this.sm = new Ext.grid.CheckboxSelectionModel(); - Ext.applyIf(config,{ - id: 'modx-grid-fc-profile' - ,url: MODx.config.connector_url - ,baseParams: { + Ext.applyIf(config, { + id: 'modx-grid-fc-profile', + url: MODx.config.connector_url, + baseParams: { action: 'Security/Forms/Profile/GetList' - } - ,fields: [ + }, + fields: [ 'id', 'name', 'description', 'usergroups', 'active', 'rank', - 'sets', - 'perm' - ] - ,paging: true - ,autosave: true - ,save_action: 'Security/Forms/Profile/UpdateFromGrid' - ,sm: this.sm - ,remoteSort: true - ,columns: [this.sm,{ - header: _('id') - ,dataIndex: 'id' - ,width: 40 - ,sortable: true - },{ - header: _('name') - ,dataIndex: 'name' - ,width: 200 - ,sortable: true - ,editor: { xtype: 'textfield' } - ,renderer: { fn: function(v,md,record) { - return this.renderLink(v, { - href: '?a=security/forms/profile/update&id=' + record.data.id - }); - }, scope: this } - },{ - header: _('description') - ,dataIndex: 'description' - ,width: 250 - ,sortable: true - ,editor: { xtype: 'textarea' } - },{ - header: _('usergroups') - ,dataIndex: 'usergroups' - ,width: 150 - }] - ,viewConfig: { - forceFit:true - ,enableRowBody:true - ,scrollOffset: 0 - ,autoFill: true - ,showPreview: true - ,getRowClass : function(rec, ri, p){ - return rec.data.active ? 'grid-row-active' : 'grid-row-inactive'; + 'sets' + ], + paging: true, + autosave: true, + save_action: 'Security/Forms/Profile/UpdateFromGrid', + sm: this.sm, + remoteSort: true, + columns: [this.sm, { + header: _('id'), + dataIndex: 'id', + width: 40, + sortable: true + }, { + header: _('name'), + dataIndex: 'name', + width: 200, + sortable: true, + editor: { + xtype: 'textfield' + }, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record); + return this.renderLink(value, { + href: `?a=security/forms/profile/update&id=${record.data.id}` + }); + }, + scope: this } - } - ,tbar: [ - { - text: _('create') - ,scope: this - ,handler: this.createProfile - ,cls:'primary-button' - },{ - text: _('bulk_actions') - ,menu: [{ - text: _('selected_activate') - ,handler: this.activateSelected - ,scope: this - },{ - text: _('selected_deactivate') - ,handler: this.deactivateSelected - ,scope: this - },{ - text: _('selected_remove') - ,handler: this.removeSelected - ,scope: this - }] + }, { + header: _('description'), + dataIndex: 'description', + width: 250, + sortable: true, + editor: { + xtype: 'textarea' }, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record); + return value; + }, + scope: this + } + }, { + header: _('usergroups'), + dataIndex: 'usergroups', + width: 150 + }], + tbar: [ + this.getCreateButton('profile', 'createProfile'), + this.getBulkActionsButton('profile', 'Security/Forms/Profile/RemoveMultiple', 'int', 'activate', 'deactivate'), '->', this.getQueryFilterField(), this.getClearFiltersButton() - ] + ], + viewConfig: this.getViewConfig(true, false, true) + }); + MODx.grid.FCProfile.superclass.constructor.call(this, config); + + this.gridMenuActions = ['edit', 'delete', 'duplicate']; + + // Note there are currently no action-specific, object-specific permissions for FC Profiles + this.setUserCanEdit(['customize_forms', 'save']); + this.setUserCanCreate(['customize_forms', 'save']); + this.setUserCanDelete(['customize_forms', 'remove']); + this.setShowActionsMenu(); + + this.on({ + render: function() { + this.getStore().reload(); + }, + beforeedit: function(e) { + if (!this.userCanEdit) { + return false; + } + } }); - MODx.grid.FCProfile.superclass.constructor.call(this,config); - this.on('render',function() { this.getStore().reload(); },this); }; -Ext.extend(MODx.grid.FCProfile,MODx.grid.Grid,{ +Ext.extend(MODx.grid.FCProfile, MODx.grid.Grid, { getMenu: function() { - var r = this.getSelectionModel().getSelected(); - var p = r.data.perm; - - var m = []; - if (this.getSelectionModel().getCount() > 1) { - m.push({ - text: _('selected_activate') - ,handler: this.activateSelected - }); - m.push({ - text: _('selected_deactivate') - ,handler: this.deactivateSelected - }); - m.push('-'); - m.push({ - text: _('selected_remove') - ,handler: this.removeSelected - }); + const + model = this.getSelectionModel(), + record = model.getSelected(), + menu = [] + ; + if (model.getCount() > 1) { + if (this.userCanEdit) { + menu.push({ + text: _('selected_activate'), + handler: this.activateSelected + }); + menu.push({ + text: _('selected_deactivate'), + handler: this.deactivateSelected + }); + } + if (this.userCanDelete) { + menu.push('-'); + menu.push({ + text: _('selected_remove'), + handler: this.removeSelected.bind(this, 'profile', 'Security/Forms/Profile/RemoveMultiple') + }); + } } else { - if (p.indexOf('pedit') != -1) { - m.push({ - text: _('edit') - ,handler: this.updateProfile - },{ - text: _('duplicate') - ,handler: this.duplicateProfile - },'-'); - if (r.data.active) { - m.push({ - text: _('deactivate') - ,handler: this.deactivateProfile + if (this.userCanEdit) { + menu.push({ + text: _('edit'), + handler: this.updateProfile + }, { + text: _('duplicate'), + handler: this.duplicateProfile + }, '-'); + if (record.data.active) { + menu.push({ + text: _('deactivate'), + handler: this.deactivateProfile }); } else { - m.push({ - text: _('activate') - ,handler: this.activateProfile + menu.push({ + text: _('activate'), + handler: this.activateProfile }); } } - if (p.indexOf('premove') != -1) { - m.push('-',{ - text: _('delete') - ,handler: this.confirm.createDelegate(this,['Security/Forms/Profile/Remove','profile_remove_confirm']) + if (this.userCanDelete) { + menu.push('-', { + text: _('delete'), + handler: this.confirm.createDelegate(this, ['Security/Forms/Profile/Remove', 'profile_remove_confirm']) }); } } + return menu; + }, - if (m.length > 0) { - this.addContextMenuItem(m); - } - } - - ,createProfile: function(btn,e) { + createProfile: function(btn, e) { if (!this.windows.cpro) { this.windows.cpro = MODx.load({ - xtype: 'modx-window-fc-profile-create' - ,listeners: { - 'success': {fn:function(r) { - this.refresh(); - },scope:this} + xtype: 'modx-window-fc-profile-create', + listeners: { + success: { + fn: this.refresh, + scope: this + } } }); } this.windows.cpro.reset(); this.windows.cpro.show(e.target); - } + }, - ,updateProfile: function(btn,e) { - var r = this.menu.record; - location.href = '?a=security/forms/profile/update&id='+r.id; - } + updateProfile: function(btn, e) { + const { record } = this.menu; + window.location.href = `?a=security/forms/profile/update&id=${record.id}`; + }, - ,duplicateProfile: function(btn,e) { + duplicateProfile: function(btn, e) { MODx.Ajax.request({ - url: this.config.url - ,params: { - action: 'security/forms/profile/duplicate' - ,id: this.menu.record.id - } - ,listeners: { - 'success': {fn:this.refresh,scope:this} + url: this.config.url, + params: { + action: 'security/forms/profile/duplicate', + id: this.menu.record.id + }, + listeners: { + success: { + fn: this.refresh, + scope: this + } } }); - } + }, - ,activateProfile: function(btn,e) { + activateProfile: function(btn, e) { MODx.Ajax.request({ - url: this.config.url - ,params: { - action: 'Security/Forms/Profile/Activate' - ,id: this.menu.record.id - } - ,listeners: { - 'success': {fn:this.refresh,scope:this} + url: this.config.url, + params: { + action: 'Security/Forms/Profile/Activate', + id: this.menu.record.id + }, + listeners: { + success: { + fn: this.refresh, + scope: this + } } }); - } + }, - ,deactivateProfile: function(btn,e) { + deactivateProfile: function(btn, e) { MODx.Ajax.request({ - url: this.config.url - ,params: { - action: 'Security/Forms/Profile/Deactivate' - ,id: this.menu.record.id - } - ,listeners: { - 'success': {fn:this.refresh,scope:this} + url: this.config.url, + params: { + action: 'Security/Forms/Profile/Deactivate', + id: this.menu.record.id + }, + listeners: { + success: { + fn: this.refresh, + scope: this + } } }); - } - - ,activateSelected: function() { - var cs = this.getSelectedAsList(); - if (cs === false) return false; + }, + activateSelected: function() { + const selections = this.getSelectedAsList(); + if (selections === false) { + return false; + } MODx.Ajax.request({ - url: this.config.url - ,params: { - action: 'Security/Forms/Profile/ActivateMultiple' - ,profiles: cs - } - ,listeners: { - 'success': {fn:function(r) { - this.getSelectionModel().clearSelections(true); - this.refresh(); - },scope:this} + url: this.config.url, + params: { + action: 'Security/Forms/Profile/ActivateMultiple', + profiles: selections + }, + listeners: { + success: { + fn: function() { + this.getSelectionModel().clearSelections(true); + this.refresh(); + }, + scope: this + } } }); return true; - } - - ,deactivateSelected: function() { - var cs = this.getSelectedAsList(); - if (cs === false) return false; + }, + deactivateSelected: function() { + const selections = this.getSelectedAsList(); + if (selections === false) { + return false; + } MODx.Ajax.request({ - url: this.config.url - ,params: { - action: 'Security/Forms/Profile/DeactivateMultiple' - ,profiles: cs - } - ,listeners: { - 'success': {fn:function(r) { - this.getSelectionModel().clearSelections(true); - this.refresh(); - },scope:this} - } - }); - return true; - } - - ,removeSelected: function() { - var cs = this.getSelectedAsList(); - if (cs === false) return false; - - MODx.msg.confirm({ - title: _('selected_remove') - ,text: _('profile_remove_multiple_confirm') - ,url: this.config.url - ,params: { - action: 'Security/Forms/Profile/RemoveMultiple' - ,profiles: cs - } - ,listeners: { - 'success': {fn:function(r) { - this.getSelectionModel().clearSelections(true); - this.refresh(); - },scope:this} + url: this.config.url, + params: { + action: 'Security/Forms/Profile/DeactivateMultiple', + profiles: selections + }, + listeners: { + success: { + fn: function() { + this.getSelectionModel().clearSelections(true); + this.refresh(); + }, + scope: this + } } }); return true; } }); -Ext.reg('modx-grid-fc-profile',MODx.grid.FCProfile); +Ext.reg('modx-grid-fc-profile', MODx.grid.FCProfile); /** * @class MODx.window.CreateFCProfile @@ -316,39 +321,38 @@ Ext.reg('modx-grid-fc-profile',MODx.grid.FCProfile); * @param {Object} config An object of options. * @xtype modx-window-fc-profile-create */ -MODx.window.CreateFCProfile = function(config) { - config = config || {}; - Ext.applyIf(config,{ - title: _('create') - ,url: MODx.config.connector_url - ,action: 'Security/Forms/Profile/Create' - ,fields: [{ - xtype: 'textfield' - ,name: 'name' - ,fieldLabel: _('name') - ,id: 'modx-fccp-name' - ,allowBlank: false - ,anchor: '100%' - },{ - xtype: 'textarea' - ,name: 'description' - ,fieldLabel: _('description') - ,id: 'modx-fccp-description' - ,anchor: '100%' - },{ - xtype: 'xcheckbox' - ,boxLabel: _('active') - ,hideLabel: true - ,name: 'active' - ,id: 'modx-fccp-active' - ,inputValue: 1 - ,value: 1 - ,checked: true - ,anchor: '100%' - }] - ,keys: [] +MODx.window.CreateFCProfile = function(config = {}) { + Ext.applyIf(config, { + title: _('create'), + url: MODx.config.connector_url, + action: 'Security/Forms/Profile/Create', + formDefaults: { + anchor: '100%', + msgTarget: 'under', + validationEvent: 'change', + validateOnBlur: false + }, + fields: [{ + xtype: 'textfield', + name: 'name', + fieldLabel: _('name'), + allowBlank: false + }, { + xtype: 'textarea', + name: 'description', + fieldLabel: _('description') + }, { + xtype: 'xcheckbox', + boxLabel: _('active'), + hideLabel: true, + name: 'active', + inputValue: 1, + value: 1, + checked: true + }], + keys: [] }); - MODx.window.CreateFCProfile.superclass.constructor.call(this,config); + MODx.window.CreateFCProfile.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.CreateFCProfile,MODx.Window); -Ext.reg('modx-window-fc-profile-create',MODx.window.CreateFCProfile); +Ext.extend(MODx.window.CreateFCProfile, MODx.Window); +Ext.reg('modx-window-fc-profile-create', MODx.window.CreateFCProfile); diff --git a/manager/assets/modext/widgets/fc/modx.grid.fcset.js b/manager/assets/modext/widgets/fc/modx.grid.fcset.js index c4f95b1c740..68c036c82ee 100644 --- a/manager/assets/modext/widgets/fc/modx.grid.fcset.js +++ b/manager/assets/modext/widgets/fc/modx.grid.fcset.js @@ -1,12 +1,13 @@ MODx.grid.FCSet = function(config = {}) { this.sm = new Ext.grid.CheckboxSelectionModel(); - Ext.applyIf(config,{ - id: 'modx-grid-fc-set' - ,url: MODx.config.connector_url - ,baseParams: { + const actionCombo = new MODx.combo.FCAction(); + Ext.applyIf(config, { + id: 'modx-grid-fc-set', + url: MODx.config.connector_url, + baseParams: { action: 'Security/Forms/Set/GetList' - } - ,fields: [ + }, + fields: [ 'id', 'profile', 'action', @@ -18,339 +19,381 @@ MODx.grid.FCSet = function(config = {}) { 'constraint', 'constraint_field', 'constraint_class', - 'rules', - 'perm' - ] - ,paging: true - ,autosave: true - ,preventSaveRefresh: false - ,save_action: 'Security/Forms/Set/UpdateFromGrid' - ,sm: this.sm - ,remoteSort: true - ,autoExpandColumn: 'controller' - ,columns: [this.sm,{ - header: _('id') - ,dataIndex: 'id' - ,width: 40 - ,sortable: true - },{ - header: _('action') - ,dataIndex: 'action' - ,width: 200 - ,editable: true - ,sortable: true - ,editor: { - xtype: 'modx-combo-fc-action', - renderer: true - } - },{ - header: _('description') - ,dataIndex: 'description' - ,width: 200 - ,editable: true - ,sortable: true - ,editor: { - xtype: 'textarea', - renderer: true + 'rules' + ], + paging: true, + autosave: true, + preventSaveRefresh: false, + save_action: 'Security/Forms/Set/UpdateFromGrid', + sm: this.sm, + remoteSort: true, + autoExpandColumn: 'controller', + columns: [this.sm, { + header: _('id'), + dataIndex: 'id', + width: 40, + sortable: true + }, { + header: _('template'), + dataIndex: 'template', + width: 150, + sortable: true, + renderer: { + fn: function(value, metaData, record) { + let + displayValue = record.json.templatename, + linkDescripton = _('set_edit') + ; + if (Ext.isEmpty(record.json.templatename)) { + if (record.json.template > 0) { + displayValue = _('template_missing'); + linkDescripton += `\n${_('template_missing_desc')}`; + } else { + displayValue = _('template_empty'); + linkDescripton += `\n${_('template_empty_desc')}`; + } + } + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record); + return this.renderLink(displayValue, { + href: `?a=security/forms/set/update&id=${record.id}`, + title: linkDescripton + }); + }, + scope: this } - },{ - header: _('template') - ,dataIndex: 'template' - ,width: 150 - ,sortable: true - ,editable: true - ,editor: { - xtype: 'modx-combo-template', - renderer: true + }, { + header: _('action'), + dataIndex: 'action', + width: 200, + sortable: true, + editor: actionCombo, + renderer: { + fn: function(value, metaData, record, rowIndex, colIndex) { + const actionRecord = actionCombo.findRecord(actionCombo.valueField, value); + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record); + return actionRecord ? actionRecord.get(actionCombo.displayField) : value; + }, + scope: this } - },{ - header: _('constraint_field') - ,dataIndex: 'constraint_field' - ,width: 200 - ,editable: true - ,sortable: false - ,editor: { - xtype: 'textfield', - renderer: true + }, { + header: _('description'), + dataIndex: 'description', + width: 200, + sortable: true, + editor: { + xtype: 'textarea' + }, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record); + return value; + }, + scope: this } - },{ - header: _('constraint') - ,dataIndex: 'constraint' - ,width: 200 - ,editable: true - ,sortable: false - ,editor: { - xtype: 'textfield', - renderer: true + }, { + header: _('constraint_field'), + dataIndex: 'constraint_field', + width: 200, + sortable: false, + editor: { + xtype: 'textfield' + }, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record); + return value; + }, + scope: this } - }] - ,viewConfig: { - forceFit:true - ,enableRowBody:true - ,scrollOffset: 0 - ,autoFill: true - ,showPreview: true - ,getRowClass : function(rec, ri, p){ - return rec.data.active ? 'grid-row-active' : 'grid-row-inactive'; + }, { + header: _('constraint'), + dataIndex: 'constraint', + width: 200, + sortable: false, + editor: { + xtype: 'textfield' + }, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record); + return value; + }, + scope: this } - } - ,tbar: [ + }], + tbar: [ + this.getCreateButton('set', 'createSet'), + this.getBulkActionsButton('set', 'Security/Forms/Set/RemoveMultiple', 'int', 'activate', 'deactivate'), { - text: _('create') - ,cls: 'primary-button' - ,scope: this - ,handler: this.createSet - },{ - text: _('bulk_actions') - ,menu: [{ - text: _('selected_activate') - ,handler: this.activateSelected - ,scope: this - },{ - text: _('selected_deactivate') - ,handler: this.deactivateSelected - ,scope: this - },{ - text: _('selected_remove') - ,handler: this.removeSelected - ,scope: this - }] - },{ - text: _('import') - ,handler: this.importSet - ,scope: this + text: _('import'), + handler: this.importSet, + scope: this, + listeners: { + render: { + fn: function(btn) { + if (!this.userCanEdit) { + btn.hide(); + } + }, + scope: this + } + } }, '->', this.getQueryFilterField(), this.getClearFiltersButton() - ] + ], + viewConfig: this.getViewConfig(true, false, true) + }); + MODx.grid.FCSet.superclass.constructor.call(this, config); + + this.gridMenuActions = ['edit', 'delete', 'duplicate']; + + // Note there are currently no action-specific, object-specific permissions for FC Sets + this.setUserCanEdit(['customize_forms', 'save']); + this.setUserCanCreate(['customize_forms', 'save']); + this.setUserCanDelete(['customize_forms', 'remove']); + this.setShowActionsMenu(); + + this.on({ + beforeedit: function(e) { + if (!this.userCanEdit) { + return false; + } + } }); - MODx.grid.FCSet.superclass.constructor.call(this,config); }; -Ext.extend(MODx.grid.FCSet,MODx.grid.Grid,{ +Ext.extend(MODx.grid.FCSet, MODx.grid.Grid, { getMenu: function() { - var r = this.getSelectionModel().getSelected(); - var p = r.data.perm; - - var m = []; - if (this.getSelectionModel().getCount() > 1) { - m.push({ - text: _('selected_activate') - ,handler: this.activateSelected - }); - m.push({ - text: _('selected_deactivate') - ,handler: this.deactivateSelected - }); - m.push('-'); - m.push({ - text: _('selected_remove') - ,handler: this.removeSelected - }); + const + model = this.getSelectionModel(), + record = model.getSelected(), + menu = [] + ; + if (model.getCount() > 1) { + if (this.userCanEdit) { + menu.push({ + text: _('selected_activate'), + handler: this.activateSelected + }); + menu.push({ + text: _('selected_deactivate'), + handler: this.deactivateSelected + }); + } + if (this.userCanDelete) { + menu.push('-'); + menu.push({ + text: _('selected_remove'), + handler: this.removeSelected.bind(this, 'set', 'Security/Forms/Set/RemoveMultiple') + }); + } } else { - if (p.indexOf('pedit') != -1) { - m.push({ - text: _('edit') - ,handler: this.updateSet + if (this.userCanEdit) { + menu.push({ + text: _('edit'), + handler: this.updateSet }); - m.push({ - text: _('duplicate') - ,handler: this.duplicateSet + menu.push({ + text: _('duplicate'), + handler: this.duplicateSet }); - m.push({ - text: _('export') - ,handler: this.exportSet + menu.push({ + text: _('export'), + handler: this.exportSet }); - m.push('-'); - if (r.data.active) { - m.push({ - text: _('deactivate') - ,handler: this.deactivateSet + menu.push('-'); + if (record.data.active) { + menu.push({ + text: _('deactivate'), + handler: this.deactivateSet }); } else { - m.push({ - text: _('activate') - ,handler: this.activateSet + menu.push({ + text: _('activate'), + handler: this.activateSet }); } } - if (p.indexOf('premove') != -1) { - m.push('-',{ - text: _('delete') - ,handler: this.confirm.createDelegate(this,['Security/Forms/Set/Remove','set_remove_confirm']) + if (this.userCanDelete) { + menu.push('-', { + text: _('delete'), + handler: this.confirm.createDelegate(this, ['Security/Forms/Set/Remove', 'set_remove_confirm']) }); } } + return menu; + }, - if (m.length > 0) { - this.addContextMenuItem(m); - } - } - - ,exportSet: function(btn,e) { - var id = this.menu.record.id; + exportSet: function(btn, e) { + const { id } = this.menu.record; MODx.Ajax.request({ - url: this.config.url - ,params: { - action: 'Security/Forms/Set/Export' - ,id: id - } - ,listeners: { - 'success': {fn:function(r) { - location.href = this.config.url+'?action=Security/Forms/Set/Export&download='+r.message+'&id='+id+'&HTTP_MODAUTH='+MODx.siteId; - },scope:this} + url: this.config.url, + params: { + action: 'Security/Forms/Set/Export', + id: id + }, + listeners: { + success: { + fn: function(response) { + window.location.href = `${this.config.url}?action=Security/Forms/Set/Export&download=${response.message}&id=${id}&HTTP_MODAUTH=${MODx.siteId}`; + }, + scope: this + } } }); - } + }, - ,importSet: function(btn,e) { - var r = { + importSet: function(btn, e) { + const record = { profile: MODx.request.id }; if (!this.windows.impset) { this.windows.impset = MODx.load({ - xtype: 'modx-window-fc-set-import' - ,record: r - ,listeners: { - 'success': {fn:function(o) { - this.refresh(); - },scope:this} + xtype: 'modx-window-fc-set-import', + record: record, + listeners: { + success: { + fn: this.refresh, + scope: this + } } }); } this.windows.impset.reset(); - this.windows.impset.setValues(r); + this.windows.impset.setValues(record); this.windows.impset.show(e.target); - } + }, - ,createSet: function(btn,e) { - var r = { - profile: MODx.request.id - ,active: true + createSet: function(btn, e) { + const record = { + profile: MODx.request.id, + active: true }; if (!this.windows.cset) { this.windows.cset = MODx.load({ - xtype: 'modx-window-fc-set-create' - ,record: r - ,listeners: { - 'success': {fn:function(r) { - this.refresh(); - },scope:this} + xtype: 'modx-window-fc-set-create', + record: record, + listeners: { + success: { + fn: this.refresh, + scope: this + } } }); } this.windows.cset.reset(); - this.windows.cset.setValues(r); + this.windows.cset.setValues(record); this.windows.cset.show(e.target); - } + }, - ,updateSet: function(btn,e) { - var r = this.menu.record; - location.href = '?a=security/forms/set/update&id='+r.id; - } + updateSet: function(btn, e) { + const { record } = this.menu; + window.location.href = `?a=security/forms/set/update&id=${record.id}`; + }, - ,duplicateSet: function(btn,e) { + duplicateSet: function(btn, e) { MODx.Ajax.request({ - url: this.config.url - ,params: { - action: 'security/forms/set/duplicate' - ,id: this.menu.record.id - } - ,listeners: { - 'success': {fn:this.refresh,scope:this} + url: this.config.url, + params: { + action: 'security/forms/set/duplicate', + id: this.menu.record.id + }, + listeners: { + success: { + fn: this.refresh, + scope: this + } } }); - } + }, - ,activateSet: function(btn,e) { + activateSet: function(btn, e) { MODx.Ajax.request({ - url: this.config.url - ,params: { - action: 'Security/Forms/Set/Activate' - ,id: this.menu.record.id - } - ,listeners: { - 'success': {fn:this.refresh,scope:this} + url: this.config.url, + params: { + action: 'Security/Forms/Set/Activate', + id: this.menu.record.id + }, + listeners: { + success: { + fn: this.refresh, + scope: this + } } }); - } + }, - ,deactivateSet: function(btn,e) { + deactivateSet: function(btn, e) { MODx.Ajax.request({ - url: this.config.url - ,params: { - action: 'Security/Forms/Set/Deactivate' - ,id: this.menu.record.id - } - ,listeners: { - 'success': {fn:this.refresh,scope:this} + url: this.config.url, + params: { + action: 'Security/Forms/Set/Deactivate', + id: this.menu.record.id + }, + listeners: { + success: { + fn: this.refresh, + scope: this + } } }); - } - - ,activateSelected: function() { - var cs = this.getSelectedAsList(); - if (cs === false) return false; + }, + activateSelected: function() { + const selections = this.getSelectedAsList(); + if (selections === false) { + return false; + } MODx.Ajax.request({ - url: this.config.url - ,params: { - action: 'Security/Forms/Set/ActivateMultiple' - ,sets: cs - } - ,listeners: { - 'success': {fn:function(r) { - this.getSelectionModel().clearSelections(true); - this.refresh(); - },scope:this} + url: this.config.url, + params: { + action: 'Security/Forms/Set/ActivateMultiple', + sets: selections + }, + listeners: { + success: { + fn: function() { + this.getSelectionModel().clearSelections(true); + this.refresh(); + }, + scope: this + } } }); return true; - } - - ,deactivateSelected: function() { - var cs = this.getSelectedAsList(); - if (cs === false) return false; + }, + deactivateSelected: function() { + const selections = this.getSelectedAsList(); + if (selections === false) { + return false; + } MODx.Ajax.request({ - url: this.config.url - ,params: { - action: 'Security/Forms/Set/DeactivateMultiple' - ,sets: cs - } - ,listeners: { - 'success': {fn:function(r) { - this.getSelectionModel().clearSelections(true); - this.refresh(); - },scope:this} - } - }); - return true; - } - - ,removeSelected: function() { - var cs = this.getSelectedAsList(); - if (cs === false) return false; - - MODx.msg.confirm({ - title: _('selected_remove') - ,text: _('set_remove_multiple_confirm') - ,url: this.config.url - ,params: { - action: 'Security/Forms/Set/RemoveMultiple' - ,sets: cs - } - ,listeners: { - 'success': {fn:function(r) { - this.getSelectionModel().clearSelections(true); - this.refresh(); - },scope:this} + url: this.config.url, + params: { + action: 'Security/Forms/Set/DeactivateMultiple', + sets: selections + }, + listeners: { + success: { + fn: function() { + this.getSelectionModel().clearSelections(true); + this.refresh(); + }, + scope: this + } } }); return true; } }); -Ext.reg('modx-grid-fc-set',MODx.grid.FCSet); +Ext.reg('modx-grid-fc-set', MODx.grid.FCSet); /** * @class MODx.window.CreateFCSet @@ -360,85 +403,85 @@ Ext.reg('modx-grid-fc-set',MODx.grid.FCSet); */ MODx.window.CreateFCSet = function(config = {}) { Ext.applyIf(config, { - title: _('create') - ,url: MODx.config.connector_url - ,action: 'Security/Forms/Set/Create' - ,width: 600 - ,fields: [{ - xtype: 'hidden' - ,name: 'profile' - ,value: MODx.request.id - },{ - xtype: 'hidden' - ,fieldLabel: _('constraint_class') - ,name: 'constraint_class' - ,allowBlank: true - ,value: 'MODX\\Revolution\\modResource' - },{ - layout: 'column' - ,border: false - ,defaults: { - layout: 'form' - ,labelAlign: 'top' - ,border: false - } - ,items: [{ - columnWidth: .5 - ,defaults: { + title: _('create'), + url: MODx.config.connector_url, + action: 'Security/Forms/Set/Create', + width: 600, + fields: [{ + xtype: 'hidden', + name: 'profile', + value: MODx.request.id + }, { + xtype: 'hidden', + fieldLabel: _('constraint_class'), + name: 'constraint_class', + allowBlank: true, + value: 'MODX\\Revolution\\modResource' + }, { + layout: 'column', + border: false, + defaults: { + layout: 'form', + labelAlign: 'top', + border: false + }, + items: [{ + columnWidth: 0.5, + defaults: { anchor: '100%', msgTarget: 'under', validationEvent: 'change', validateOnBlur: false - } - ,items: [{ - fieldLabel: _('action') - ,name: 'action_id' - ,hiddenName: 'action_id' - ,id: 'modx-fcsc-action' - ,xtype: 'modx-combo-fc-action' - ,editable: false - ,allowBlank: false - },{ - xtype: 'textarea' - ,name: 'description' - ,fieldLabel: _('description') - ,id: 'modx-fcsc-description' - },{ - xtype: 'xcheckbox' - ,boxLabel: _('active') - ,hideLabel: true - ,name: 'active' - ,inputValue: 1 - ,value: 1 - ,checked: true + }, + items: [{ + fieldLabel: _('action'), + name: 'action_id', + hiddenName: 'action_id', + id: 'modx-fcsc-action', + xtype: 'modx-combo-fc-action', + editable: false, + allowBlank: false + }, { + xtype: 'textarea', + name: 'description', + fieldLabel: _('description'), + id: 'modx-fcsc-description' + }, { + xtype: 'xcheckbox', + boxLabel: _('active'), + hideLabel: true, + name: 'active', + inputValue: 1, + value: 1, + checked: true }] - },{ - columnWidth: .5 - ,defaults: { + }, { + columnWidth: 0.5, + defaults: { anchor: '100%', msgTarget: 'under', validationEvent: 'change', validateOnBlur: false - } - ,items: [{ - xtype: 'modx-combo-template' - ,name: 'template' - ,hiddenName: 'template' - ,fieldLabel: _('template') - ,description: MODx.expandHelp ? '' : _('set_template_desc') - ,id: 'modx-fcsc-template' - ,baseParams: { action: 'Element/Template/GetList', combo: true } - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-fcsc-template' - ,html: _('set_template_desc') - ,cls: 'desc-under' - },{ - xtype: 'textfield' - ,fieldLabel: _('constraint_field') - ,description: MODx.expandHelp ? '' : _('set_constraint_field_desc') - ,name: 'constraint_field' - ,listeners: { + }, + items: [{ + xtype: 'modx-combo-template', + name: 'template', + hiddenName: 'template', + fieldLabel: _('template'), + description: MODx.expandHelp ? '' : _('set_template_desc'), + id: 'modx-fcsc-template', + baseParams: { action: 'Element/Template/GetList', combo: true } + }, { + xtype: MODx.expandHelp ? 'label' : 'hidden', + forId: 'modx-fcsc-template', + html: _('set_template_desc'), + cls: 'desc-under' + }, { + xtype: 'textfield', + fieldLabel: _('constraint_field'), + description: MODx.expandHelp ? '' : _('set_constraint_field_desc'), + name: 'constraint_field', + listeners: { change: { fn: function(cmp, newValue, oldValue) { if (!Ext.isEmpty(newValue)) { @@ -451,16 +494,16 @@ MODx.window.CreateFCSet = function(config = {}) { scope: this } } - },{ - xtype: MODx.expandHelp ? 'box' : 'hidden' - ,html: _('set_constraint_field_desc') - ,cls: 'desc-under' - },{ - xtype: 'textfield' - ,fieldLabel: _('constraint') - ,description: MODx.expandHelp ? '' : _('set_constraint_desc') - ,name: 'constraint' - ,listeners: { + }, { + xtype: MODx.expandHelp ? 'box' : 'hidden', + html: _('set_constraint_field_desc'), + cls: 'desc-under' + }, { + xtype: 'textfield', + fieldLabel: _('constraint'), + description: MODx.expandHelp ? '' : _('set_constraint_desc'), + name: 'constraint', + listeners: { change: { fn: function(cmp, newValue, oldValue) { if (!Ext.isEmpty(newValue)) { @@ -473,19 +516,19 @@ MODx.window.CreateFCSet = function(config = {}) { scope: this } } - },{ - xtype: MODx.expandHelp ? 'box' : 'hidden' - ,html: _('set_constraint_desc') - ,cls: 'desc-under' + }, { + xtype: MODx.expandHelp ? 'box' : 'hidden', + html: _('set_constraint_desc'), + cls: 'desc-under' }] }] - }] - ,keys: [] + }], + keys: [] }); - MODx.window.CreateFCSet.superclass.constructor.call(this,config); + MODx.window.CreateFCSet.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.CreateFCSet,MODx.Window); -Ext.reg('modx-window-fc-set-create',MODx.window.CreateFCSet); +Ext.extend(MODx.window.CreateFCSet, MODx.Window); +Ext.reg('modx-window-fc-set-create', MODx.window.CreateFCSet); /** * @class MODx.window.ImportFCSet @@ -493,34 +536,33 @@ Ext.reg('modx-window-fc-set-create',MODx.window.CreateFCSet); * @param {Object} config An object of options. * @xtype modx-window-fc-set-import */ -MODx.window.ImportFCSet = function(config) { - config = config || {}; - Ext.applyIf(config,{ - title: _('import') - ,id: 'modx-window-fc-set-import' - ,url: MODx.config.connector_url - ,action: 'Security/Forms/Set/Import' - ,fileUpload: true - ,saveBtnText: _('import') - ,fields: [{ - xtype: 'hidden' - ,name: 'profile' - ,value: MODx.request.id - },{ - html: _('set_import_msg') - ,id: 'modx-impset-desc' - ,xtype: 'modx-description' - ,style: 'margin-bottom: 10px;' - },{ - xtype: 'fileuploadfield' - ,fieldLabel: _('file') - ,buttonText: _('upload.buttons.upload') - ,name: 'file' - ,id: 'modx-impset-file' - ,anchor: '100%' +MODx.window.ImportFCSet = function(config = {}) { + Ext.applyIf(config, { + title: _('import'), + id: 'modx-window-fc-set-import', + url: MODx.config.connector_url, + action: 'Security/Forms/Set/Import', + fileUpload: true, + saveBtnText: _('import'), + fields: [{ + xtype: 'hidden', + name: 'profile', + value: MODx.request.id + }, { + html: _('set_import_msg'), + id: 'modx-impset-desc', + xtype: 'modx-description', + style: 'margin-bottom: 10px;' + }, { + xtype: 'fileuploadfield', + fieldLabel: _('file'), + buttonText: _('upload.buttons.upload'), + name: 'file', + id: 'modx-impset-file', + anchor: '100%' }] }); - MODx.window.ImportFCSet.superclass.constructor.call(this,config); + MODx.window.ImportFCSet.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.ImportFCSet,MODx.Window); -Ext.reg('modx-window-fc-set-import',MODx.window.ImportFCSet); +Ext.extend(MODx.window.ImportFCSet, MODx.Window); +Ext.reg('modx-window-fc-set-import', MODx.window.ImportFCSet); diff --git a/manager/assets/modext/widgets/fc/modx.panel.fcprofile.js b/manager/assets/modext/widgets/fc/modx.panel.fcprofile.js index 002b5e6ed8d..5b288d76b24 100644 --- a/manager/assets/modext/widgets/fc/modx.panel.fcprofile.js +++ b/manager/assets/modext/widgets/fc/modx.panel.fcprofile.js @@ -4,140 +4,142 @@ * @param {Object} config An object of configuration properties * @xtype modx-panel-fc-profile */ -MODx.panel.FCProfile = function(config) { - config = config || {}; - Ext.applyIf(config,{ - url: MODx.config.connector_url - ,baseParams: { +MODx.panel.FCProfile = function(config = {}) { + Ext.applyIf(config, { + url: MODx.config.connector_url, + baseParams: { action: 'Security/Forms/Profile/Update' - } - ,id: 'modx-panel-fc-profile' - ,cls: 'container' - ,class_key: 'MODX\\Revolution\\modFormCustomizationProfile' - ,bodyStyle: '' - ,items: [this.getPageHeader(config), MODx.getPageStructure([{ - title: _('profile') - ,defaults: { border: false ,msgTarget: 'side' } - ,layout: 'form' - ,id: 'modx-fcp-form' - ,labelWidth: 150 - ,items: [{ - html: '

    '+_('profile_msg')+'

    ' - ,id: 'modx-fcp-msg' - ,xtype: 'modx-description' - },{ - xtype: 'panel' - ,border: false - ,cls:'main-wrapper' - ,layout: 'form' - ,items: [{ - xtype: 'hidden' - ,name: 'id' - ,id: 'modx-fcp-id' - ,value: config.record.id || MODx.request.id - },{ - xtype: 'textfield' - ,fieldLabel: _('name') - ,name: 'name' - ,id: 'modx-fcp-name' - ,anchor: '100%' - ,maxLength: 191 - ,enableKeyEvents: true - ,allowBlank: false - ,value: config.record.name - ,listeners: { - 'keyup': {scope:this,fn:function(f,e) { - Ext.getCmp('modx-header-breadcrumbs').updateHeader(Ext.util.Format.htmlEncode(f.getValue())); - }} + }, + id: 'modx-panel-fc-profile', + cls: 'container', + class_key: 'MODX\\Revolution\\modFormCustomizationProfile', + bodyStyle: '', + items: [this.getPageHeader(config), MODx.getPageStructure([{ + title: _('profile'), + defaults: { border: false, msgTarget: 'side' }, + layout: 'form', + id: 'modx-fcp-form', + labelWidth: 150, + items: [{ + html: `

    ${_('profile_msg')}

    `, + id: 'modx-fcp-msg', + xtype: 'modx-description' + }, { + xtype: 'panel', + border: false, + cls: 'main-wrapper', + layout: 'form', + items: [{ + xtype: 'hidden', + name: 'id', + id: 'modx-fcp-id', + value: config.record.id || MODx.request.id + }, { + xtype: 'textfield', + fieldLabel: _('name'), + name: 'name', + id: 'modx-fcp-name', + anchor: '100%', + maxLength: 191, + enableKeyEvents: true, + allowBlank: false, + value: config.record.name, + listeners: { + keyup: { + fn: function(f, e) { + Ext.getCmp('modx-header-breadcrumbs').updateHeader(Ext.util.Format.htmlEncode(f.getValue())); + }, + scope: this + } } - },{ - xtype: 'textarea' - ,fieldLabel: _('description') - ,name: 'description' - ,id: 'modx-fcp-description' - ,anchor: '100%' - ,maxLength: 255 - ,grow: false - ,value: config.record.description - },{ - xtype: 'xcheckbox' - ,fieldLabel: _('active') - ,name: 'active' - ,id: 'modx-fcp-active' - ,inputValue: true - ,value: config.record.active ? true : false - ,anchor: '100%' - ,allowBlank: true + }, { + xtype: 'textarea', + fieldLabel: _('description'), + name: 'description', + id: 'modx-fcp-description', + anchor: '100%', + maxLength: 255, + grow: false, + value: config.record.description + }, { + xtype: 'xcheckbox', + fieldLabel: _('active'), + ctCls: 'display-switch', + name: 'active', + id: 'modx-fcp-active', + inputValue: true, + value: Boolean(config.record.active), + anchor: '100%' }] - },{ - xtype: 'modx-grid-fc-set' - ,cls:'main-wrapper' - ,baseParams: { - action: 'Security/Forms/Set/GetList' - ,profile: config.record.id - } - ,preventRender: true + }, { + xtype: 'modx-grid-fc-set', + cls: 'main-wrapper', + baseParams: { + action: 'Security/Forms/Set/GetList', + profile: config.record.id + }, + preventRender: true }] - },{ - title: _('usergroups') - ,layout: 'anchor' - ,items: [{ - html: '

    '+_('profile_usergroups_msg')+'

    ' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-fc-profile-usergroups' - ,cls:'main-wrapper' - ,data: config.record.usergroups || [] - ,preventRender: true + }, { + title: _('usergroups'), + layout: 'anchor', + items: [{ + html: `

    ${_('profile_usergroups_msg')}

    `, + xtype: 'modx-description' + }, { + xtype: 'modx-grid-fc-profile-usergroups', + cls: 'main-wrapper', + data: config.record.usergroups || [], + preventRender: true }] - }],{ + }], { id: 'modx-fc-profile-tabs' - })] - ,listeners: { - 'setup': {fn:this.setup,scope:this} - ,'success': {fn:this.success,scope:this} - ,'beforeSubmit': {fn:this.beforeSubmit,scope:this} + })], + listeners: { + setup: { fn: this.setup, scope: this }, + success: { fn: this.success, scope: this }, + beforeSubmit: { fn: this.beforeSubmit, scope: this } } }); - MODx.panel.FCProfile.superclass.constructor.call(this,config); + MODx.panel.FCProfile.superclass.constructor.call(this, config); }; -Ext.extend(MODx.panel.FCProfile,MODx.FormPanel,{ - initialized: false +Ext.extend(MODx.panel.FCProfile, MODx.FormPanel, { + initialized: false, - ,setup: function() { + setup: function() { if (!this.initialized) { this.getForm().setValues(this.config.record); } if (!Ext.isEmpty(this.config.record.name)) { Ext.getCmp('modx-header-breadcrumbs').updateHeader(Ext.util.Format.htmlEncode(this.config.record.name)); } - this.fireEvent('ready',this.config.record); + this.fireEvent('ready', this.config.record); this.clearDirty(); this.initialized = true; MODx.fireEvent('ready'); return true; - } + }, - ,beforeSubmit: function(o) { - Ext.apply(o.form.baseParams,{ + beforeSubmit: function(o) { + Ext.apply(o.form.baseParams, { usergroups: Ext.getCmp('modx-grid-fc-profile-usergroups').encode() }); - return this.fireEvent('save',{ + return this.fireEvent('save', { values: this.getForm().getValues() }); - } + }, - ,success: function(r) { + success: function(r) { Ext.getCmp('modx-grid-fc-profile-usergroups').getStore().commitChanges(); this.getForm().setValues(r.result.object); - } + }, - ,getPageHeader: function(config) { + getPageHeader: function(config) { return MODx.util.getHeaderBreadCrumbs('modx-fcp-header', [{ text: _('form_customization'), href: MODx.getPage('security/forms') }]); } }); -Ext.reg('modx-panel-fc-profile',MODx.panel.FCProfile); +Ext.reg('modx-panel-fc-profile', MODx.panel.FCProfile); /** * @class MODx.grid.FCProfileUserGroups @@ -145,65 +147,79 @@ Ext.reg('modx-panel-fc-profile',MODx.panel.FCProfile); * @param {Object} config An object of configuration properties * @xtype modx-grid-fc-profile-usergroups */ -MODx.grid.FCProfileUserGroups = function(config) { - config = config || {}; - Ext.applyIf(config,{ - id: 'modx-grid-fc-profile-usergroups' - ,fields: ['id','name'] - ,autoHeight: true - ,stateful: false - ,columns: [{ - header: _('name') - ,dataIndex: 'name' - ,renderer: { fn: function(v,md,record) { - return this.renderLink(v, { - href: '?a=security/usergroup/update&id=' + record.data.id - ,target: '_blank' - }); - }, scope: this } - }] - ,tbar: [{ - text: _('usergroup_create') - ,cls: 'primary-button' - ,handler: this.addUserGroup - ,scope: this +MODx.grid.FCProfileUserGroups = function(config = {}) { + Ext.applyIf(config, { + id: 'modx-grid-fc-profile-usergroups', + fields: [ + 'id', + 'name' + ], + autoHeight: true, + stateful: false, + columns: [{ + header: _('name'), + dataIndex: 'name', + renderer: { + fn: function(value, metaData, record) { + const canEditGroups = MODx.perm.usergroup_edit && MODx.perm.usergroup_save; + return canEditGroups + ? this.renderLink(value, { + href: `?a=security/usergroup/update&id=${record.data.id}`, + target: '_blank' + }) + : value + ; + }, + scope: this + } + }], + tbar: [{ + text: _('usergroup_create'), + cls: 'primary-button', + handler: this.addUserGroup, + scope: this }] }); - MODx.grid.FCProfileUserGroups.superclass.constructor.call(this,config); + MODx.grid.FCProfileUserGroups.superclass.constructor.call(this, config); this.fcugRecord = Ext.data.Record.create(config.fields); }; -Ext.extend(MODx.grid.FCProfileUserGroups,MODx.grid.LocalGrid,{ - getMenu: function(g,ri) { +Ext.extend(MODx.grid.FCProfileUserGroups, MODx.grid.LocalGrid, { + getMenu: function(g, ri) { return [{ - text: _('usergroup_remove') - ,handler: this.removeUserGroup - ,scope: this + text: _('usergroup_remove'), + handler: this.removeUserGroup, + scope: this }]; - } + }, - ,addUserGroup: function(btn,e) { - this.loadWindow(btn,e,{ - xtype: 'modx-window-fc-profile-add-usergroup' - ,listeners: { - 'success': {fn:function(r) { - var s = this.getStore(); - var rec = new this.fcugRecord(r); - s.add(rec); - },scope:this} + addUserGroup: function(btn, e) { + this.loadWindow(btn, e, { + xtype: 'modx-window-fc-profile-add-usergroup', + listeners: { + success: { + fn: function(response) { + const + store = this.getStore(), + record = new this.fcugRecord(response) + ; + store.add(record); + }, + scope: this + } } }); - } + }, - ,removeUserGroup: function(btn,e) { - var rec = this.getSelectionModel().getSelected(); - Ext.Msg.confirm(_('usergroup_remove'),_('usergroup_remove_confirm'),function(e) { - if (e == 'yes') { - this.getStore().remove(rec); + removeUserGroup: function(btn, e) { + const record = this.getSelectionModel().getSelected(); + Ext.Msg.confirm(_('usergroup_remove'), _('usergroup_remove_confirm'), function(e) { + if (e === 'yes') { + this.getStore().remove(record); } - },this); + }, this); } }); -Ext.reg('modx-grid-fc-profile-usergroups',MODx.grid.FCProfileUserGroups); +Ext.reg('modx-grid-fc-profile-usergroups', MODx.grid.FCProfileUserGroups); /** * @class MODx.window.AddGroupToProfile @@ -211,40 +227,41 @@ Ext.reg('modx-grid-fc-profile-usergroups',MODx.grid.FCProfileUserGroups); * @param {Object} config An object of options. * @xtype modx-window-fc-profile-add-usergroup */ -MODx.window.AddGroupToProfile = function(config) { - config = config || {}; - Ext.applyIf(config,{ - title: _('usergroup_create') - ,fields: [{ - fieldLabel: _('user_group') - ,name: 'usergroup' - ,hiddenName: 'usergroup' - ,id: 'modx-fcaug-usergroup' - ,xtype: 'modx-combo-usergroup' - ,editable: false - ,allowBlank: false - ,anchor: '100%' +MODx.window.AddGroupToProfile = function(config = {}) { + Ext.applyIf(config, { + title: _('usergroup_create'), + fields: [{ + fieldLabel: _('user_group'), + name: 'usergroup', + hiddenName: 'usergroup', + id: 'modx-fcaug-usergroup', + xtype: 'modx-combo-usergroup', + editable: false, + allowBlank: false, + anchor: '100%' }] }); - MODx.window.AddGroupToProfile.superclass.constructor.call(this,config); + MODx.window.AddGroupToProfile.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.AddGroupToProfile,MODx.Window,{ +Ext.extend(MODx.window.AddGroupToProfile, MODx.Window, { submit: function() { - var rec = {}; - rec.id = Ext.getCmp('modx-fcaug-usergroup').getValue(); - rec.name = Ext.getCmp('modx-fcaug-usergroup').getRawValue(); + const + record = {}, + grid = Ext.getCmp('modx-grid-fc-profile-usergroups'), + store = grid.getStore(), + match = store.findExact('id', record.id) + ; + record.id = Ext.getCmp('modx-fcaug-usergroup').getValue(); + record.name = Ext.getCmp('modx-fcaug-usergroup').getRawValue(); - var g = Ext.getCmp('modx-grid-fc-profile-usergroups'); - var s = g.getStore(); - var v = s.findExact('id',rec.id); - if (v != '-1') { - MODx.msg.alert(_('error'),_('profile_usergroup_err_ae')); + if (match !== -1) { + MODx.msg.alert(_('error'), _('profile_usergroup_err_ae')); return false; } - this.fireEvent('success',rec); + this.fireEvent('success', record); this.hide(); return false; } }); -Ext.reg('modx-window-fc-profile-add-usergroup',MODx.window.AddGroupToProfile); +Ext.reg('modx-window-fc-profile-add-usergroup', MODx.window.AddGroupToProfile); diff --git a/manager/assets/modext/widgets/fc/modx.panel.fcset.js b/manager/assets/modext/widgets/fc/modx.panel.fcset.js index c02841caf41..4fbd1aed282 100644 --- a/manager/assets/modext/widgets/fc/modx.panel.fcset.js +++ b/manager/assets/modext/widgets/fc/modx.panel.fcset.js @@ -6,88 +6,95 @@ */ MODx.panel.FCSet = function(config = {}) { Ext.applyIf(config, { - url: MODx.config.connector_url - ,baseParams: { + url: MODx.config.connector_url, + baseParams: { action: 'Security/Forms/Set/Update' - } - ,id: 'modx-panel-fc-set' - ,class_key: 'MODX\\Revolution\\modFormCustomizationSet' - ,cls: 'container' - ,items: [this.getPageHeader(config), MODx.getPageStructure([{ - title: _('set_and_fields') - ,xtype: 'panel' - ,border: false - ,defaults: { border: false } - ,items: [{ - html: '

    '+_('set_msg')+'

    ' - ,id: 'modx-fcs-msg' - ,xtype: 'modx-description' - },{ - layout: 'form' - ,id: 'modx-fcs-form' - ,defaults: { - anchor: '100%' - ,msgTarget: 'under' - ,validationEvent: 'change' - ,validateOnBlur: false - } - ,cls: 'main-wrapper' - ,labelWidth: 150 - ,items: [{ - xtype: 'hidden' - ,name: 'id' - ,id: 'modx-fcs-id' - ,value: config.record.id || MODx.request.id - },{ - xtype: 'modx-combo-fc-action' - ,fieldLabel: _('action') - ,name: 'action_id' - ,hiddenName: 'action_id' - ,id: 'modx-fcs-action' - ,allowBlank: false - ,value: config.record.action - ,listeners: { - 'select': {scope:this,fn:function(f,e) { - Ext.getCmp('modx-header-breadcrumbs').updateHeader(Ext.util.Format.htmlEncode(f.getRawValue())); - }} - } - },{ - xtype: 'modx-combo-template' - ,fieldLabel: _('template') - ,description: _('set_template_desc') - ,name: 'template' - ,hiddenName: 'template' - ,value: config.record.template || 0 - ,lazyInit: false - ,lazyRender: false - ,baseParams: { - action: 'Element/Template/GetList' - ,combo: true + }, + id: 'modx-panel-fc-set', + class_key: 'MODX\\Revolution\\modFormCustomizationSet', + cls: 'container', + items: [this.getPageHeader(config), MODx.getPageStructure([{ + title: _('set_and_fields'), + xtype: 'panel', + border: false, + defaults: { border: false }, + items: [{ + html: `

    ${_('set_msg')}

    `, + id: 'modx-fcs-msg', + xtype: 'modx-description' + }, { + layout: 'form', + id: 'modx-fcs-form', + defaults: { + anchor: '100%', + msgTarget: 'under', + validationEvent: 'change', + validateOnBlur: false + }, + cls: 'main-wrapper', + labelWidth: 150, + items: [{ + xtype: 'hidden', + name: 'id', + id: 'modx-fcs-id', + value: config.record.id || MODx.request.id + }, { + xtype: 'modx-combo-fc-action', + fieldLabel: _('action'), + name: 'action_id', + hiddenName: 'action_id', + id: 'modx-fcs-action', + allowBlank: false, + value: config.record.action, + listeners: { + select: { + fn: function(f, e) { + Ext.getCmp('modx-header-breadcrumbs').updateHeader(Ext.util.Format.htmlEncode(f.getRawValue())); + }, + scope: this + } } - ,listeners: { - 'select': {fn:this.changeTemplate,scope:this} + }, { + xtype: 'modx-combo-template', + fieldLabel: _('template'), + description: _('set_template_desc'), + name: 'template', + hiddenName: 'template', + value: config.record.template || 0, + valueNotFoundText: _('template_missing_reassign'), + lazyInit: false, + lazyRender: false, + baseParams: { + action: 'Element/Template/GetList', + combo: true + }, + listeners: { + select: { + fn: this.changeTemplate, + scope: this + } } - },{ - xtype: 'textarea' - ,fieldLabel: _('description') - ,name: 'description' - ,id: 'modx-fcs-description' - ,maxLength: 255 - ,grow: false - ,value: config.record.description - },{ - xtype: 'hidden' - ,fieldLabel: _('constraint_class') - ,name: 'constraint_class' - ,value: 'MODX\\Revolution\\modResource' - ,allowBlank: true - },{ - xtype: 'textfield' - ,fieldLabel: _('constraint_field') - ,description: _('set_constraint_field_desc') - ,name: 'constraint_field' - ,value: config.record.constraint_field - ,listeners: { + }, { + xtype: 'textarea', + fieldLabel: _('description'), + name: 'description', + id: 'modx-fcs-description', + maxLength: 255, + grow: false, + value: config.record.description + }, { + xtype: 'hidden', + fieldLabel: _('constraint_class'), + name: 'constraint_class', + value: 'MODX\\Revolution\\modResource', + allowBlank: true + }, { + xtype: 'textfield', + fieldLabel: _('constraint_field'), + description: _('set_constraint_field_desc'), + name: 'constraint_field', + value: config.record.constraint_field, + listeners: { change: { fn: function(cmp, newValue, oldValue) { if (!Ext.isEmpty(newValue)) { @@ -100,13 +107,13 @@ MODx.panel.FCSet = function(config = {}) { scope: this } } - },{ - xtype: 'textfield' - ,fieldLabel: _('constraint') - ,description: _('set_constraint_desc') - ,name: 'constraint' - ,value: config.record.constraint - ,listeners: { + }, { + xtype: 'textfield', + fieldLabel: _('constraint'), + description: _('set_constraint_desc'), + name: 'constraint', + value: config.record.constraint, + listeners: { change: { fn: function(cmp, newValue, oldValue) { if (!Ext.isEmpty(newValue)) { @@ -119,125 +126,128 @@ MODx.panel.FCSet = function(config = {}) { scope: this } } - },{ - xtype: 'xcheckbox' - ,fieldLabel: _('active') - ,name: 'active' - ,inputValue: true - ,value: Boolean(config.record.active) + }, { + xtype: 'xcheckbox', + fieldLabel: _('active'), + ctCls: 'display-switch', + name: 'active', + inputValue: true, + value: Boolean(config.record.active) }] - },{ - html: '

    '+_('set_fields_msg')+'

    ' - ,xtype: 'modx-description' - },{ - id: 'modx-fcs-fields-form' - ,msgTarget: 'side' - ,cls: 'main-wrapper' - ,layout: 'anchor' - ,items: [{ - xtype: 'modx-grid-fc-set-fields' - ,data: config.record.fields || [] - ,preventRender: true + }, { + html: `

    ${_('set_fields_msg')}

    `, + xtype: 'modx-description' + }, { + id: 'modx-fcs-fields-form', + msgTarget: 'side', + cls: 'main-wrapper', + layout: 'anchor', + items: [{ + xtype: 'modx-grid-fc-set-fields', + data: config.record.fields || [], + preventRender: true }] }] - },{ - title: _('regions') - ,border: false - ,layout: 'anchor' - ,items: [{ - html: '

    '+_('set_tabs_msg')+'

    ' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-fc-set-tabs' - ,cls: 'main-wrapper' - ,data: config.record.tabs || [] - ,preventRender: true + }, { + title: _('regions'), + border: false, + layout: 'anchor', + items: [{ + html: `

    ${_('set_tabs_msg')}

    `, + xtype: 'modx-description' + }, { + xtype: 'modx-grid-fc-set-tabs', + cls: 'main-wrapper', + data: config.record.tabs || [], + preventRender: true }] - },{ - title: _('tvs') - ,border: false - ,layout: 'anchor' - ,items: [{ - html: '

    '+_('set_tvs_msg')+'

    ' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-fc-set-tvs' - ,cls: 'main-wrapper' - ,data: config.record.tvs || [] - ,preventRender: true + }, { + title: _('tvs'), + border: false, + layout: 'anchor', + items: [{ + html: `

    ${_('set_tvs_msg')}

    `, + xtype: 'modx-description' + }, { + xtype: 'modx-grid-fc-set-tvs', + cls: 'main-wrapper', + data: config.record.tvs || [], + preventRender: true }] - }],{ + }], { id: 'modx-fc-set-tabs' - })] - ,listeners: { - 'setup': {fn:this.setup,scope:this} - ,'success': {fn:this.success,scope:this} - ,'beforeSubmit': {fn:this.beforeSubmit,scope:this} + })], + listeners: { + setup: { fn: this.setup, scope: this }, + success: { fn: this.success, scope: this }, + beforeSubmit: { fn: this.beforeSubmit, scope: this } } }); - MODx.panel.FCSet.superclass.constructor.call(this,config); + MODx.panel.FCSet.superclass.constructor.call(this, config); }; -Ext.extend(MODx.panel.FCSet,MODx.FormPanel,{ - initialized: false +Ext.extend(MODx.panel.FCSet, MODx.FormPanel, { + initialized: false, - ,setup: function() { - if (!this.initialized) {this.getForm().setValues(this.config.record);} + setup: function() { + if (!this.initialized) { + this.getForm().setValues(this.config.record); + } Ext.getCmp('modx-header-breadcrumbs').updateHeader(_('set')); - this.fireEvent('ready',this.config.record); + this.fireEvent('ready', this.config.record); this.clearDirty(); this.initialized = true; MODx.fireEvent('ready'); return true; - } + }, - ,beforeSubmit: function(o) { - Ext.apply(o.form.baseParams,{ - fields: Ext.getCmp('modx-grid-fc-set-fields').encode() - ,tabs: Ext.getCmp('modx-grid-fc-set-tabs').encode() - ,tvs: Ext.getCmp('modx-grid-fc-set-tvs').encode() + beforeSubmit: function(o) { + Ext.apply(o.form.baseParams, { + fields: Ext.getCmp('modx-grid-fc-set-fields').encode(), + tabs: Ext.getCmp('modx-grid-fc-set-tabs').encode(), + tvs: Ext.getCmp('modx-grid-fc-set-tvs').encode() }); - return this.fireEvent('save',{ + return this.fireEvent('save', { values: this.getForm().getValues() }); - } + }, - ,success: function(r) { + success: function(r) { this.getForm().setValues(r.result.object); Ext.getCmp('modx-grid-fc-set-fields').getStore().commitChanges(); Ext.getCmp('modx-grid-fc-set-tabs').getStore().commitChanges(); Ext.getCmp('modx-grid-fc-set-tvs').getStore().commitChanges(); - } + }, - ,changeTemplate: function(cb) { - if (cb.getValue() != this.config.record.template) { - Ext.Msg.confirm(_('set_change_template'),_('set_change_template_confirm'),function(e) { - if (e == 'yes') { - this.on('success',function() { - location.href = location.href; - },this); + changeTemplate: function(cb) { + if (cb.getValue() !== this.config.record.template) { + Ext.Msg.confirm(_('set_change_template'), _('set_change_template_confirm'), function(e) { + if (e === 'yes') { + this.on('success', function() { + window.location.reload(); + }, this); this.submit(); } else { cb.setValue(this.config.record.template); } - },this); + }, this); } return false; - } + }, - ,getPageHeader: function(config) { - var profile = config.record.profile; + getPageHeader: function(config) { + const { profile } = config.record; return MODx.util.getHeaderBreadCrumbs('modx-fcs-header', [{ text: _('form_customization'), href: MODx.getPage('security/forms') - },{ + }, { text: _('profile'), - href: MODx.getPage('security/forms/profile/update&id='+profile) + href: MODx.getPage(`security/forms/profile/update&id=${profile}`) }]); } }); -Ext.reg('modx-panel-fc-set',MODx.panel.FCSet); +Ext.reg('modx-panel-fc-set', MODx.panel.FCSet); /** * @class MODx.grid.FCSetFields @@ -245,71 +255,72 @@ Ext.reg('modx-panel-fc-set',MODx.panel.FCSet); * @param {Object} config An object of configuration properties * @xtype modx-grid-fc-set-fields */ -MODx.grid.FCSetFields = function(config) { - config = config || {}; +MODx.grid.FCSetFields = function(config = {}) { this.vcb = new Ext.ux.grid.CheckColumn({ - header: _('visible') - ,dataIndex: 'visible' - ,width: 40 - ,sortable: false + header: _('visible'), + dataIndex: 'visible', + width: 40, + sortable: false }); - Ext.applyIf(config,{ - id: 'modx-grid-fc-set-fields' - ,showActionsColumn: false - ,fields: ['id','action','name','tab','tab_rank','other','rank','visible','label','default_value'] - ,autoHeight: true - ,grouping: true - ,groupBy: 'tab_rank' - ,plugins: [this.vcb] - ,stateful: false - ,remoteSort: false - ,sortBy: 'rank' - ,sortDir: 'ASC' - ,hideGroupedColumn: true - ,groupTextTpl: '{[values.rs[0].data.tab]} ({[values.rs.length]} {[values.rs.length > 1 ? "'+_('fields')+'" : "'+_('field')+'"]})' - ,columns: [{ - header: _('name') - ,dataIndex: 'name' - ,width: 200 - },{ - header: _('region')+' ('+_('tab_id')+')' - ,dataIndex: 'tab' - ,width: 100 - },{ - header: _('tab_rank') - ,dataIndex: 'tab_rank' - ,width: 100 - },this.vcb,{ - header: _('label') - ,dataIndex: 'label' - ,editor: { xtype: 'textfield' } - ,renderer: function(v,md) { - return Ext.util.Format.htmlEncode(v); + Ext.applyIf(config, { + id: 'modx-grid-fc-set-fields', + showActionsColumn: false, + fields: [ + 'id', + 'action', + 'name', + 'tab', + 'tab_rank', + 'other', + 'rank', + 'visible', + 'label', + 'default_value' + ], + autoHeight: true, + grouping: true, + groupBy: 'tab_rank', + plugins: [this.vcb], + stateful: false, + remoteSort: false, + sortBy: 'rank', + sortDir: 'ASC', + hideGroupedColumn: true, + groupTextTpl: `{[values.rs[0].data.tab]} ({[values.rs.length]} {[values.rs.length > 1 ? "${_('fields')}" : "${_('field')}"]})`, + columns: [{ + header: _('name'), + dataIndex: 'name', + width: 200 + }, { + header: `${_('region')} (${_('tab_id')})`, + dataIndex: 'tab', + width: 100 + }, { + header: _('tab_rank'), + dataIndex: 'tab_rank', + width: 100 + }, this.vcb, { + header: _('label'), + dataIndex: 'label', + editor: { xtype: 'textfield' }, + renderer: function(value, metaData) { + return Ext.util.Format.htmlEncode(value); } - },{ - header: _('default_value') - ,dataIndex: 'default_value' - ,editor: { xtype: 'textfield' } - ,renderer: function(v,md) { + }, { + header: _('default_value'), + dataIndex: 'default_value', + editor: { xtype: 'textfield' }, + renderer: function(v, md) { return Ext.util.Format.htmlEncode(v); } - }] - ,viewConfig: { - forceFit:true - ,enableRowBody:true - ,scrollOffset: 0 - ,autoFill: true - ,showPreview: true - ,getRowClass : function(rec, ri, p){ - return rec.data.visible ? 'grid-row-active' : 'grid-row-inactive'; - } - } + }], + viewConfig: this.getViewConfig(false, false, true) }); - MODx.grid.FCSetFields.superclass.constructor.call(this,config); + MODx.grid.FCSetFields.superclass.constructor.call(this, config); this.propRecord = Ext.data.Record.create(config.fields); }; -Ext.extend(MODx.grid.FCSetFields,MODx.grid.LocalGrid); -Ext.reg('modx-grid-fc-set-fields',MODx.grid.FCSetFields); +Ext.extend(MODx.grid.FCSetFields, MODx.grid.LocalGrid); +Ext.reg('modx-grid-fc-set-fields', MODx.grid.FCSetFields); /** * @class MODx.grid.FCSetTabs @@ -317,90 +328,95 @@ Ext.reg('modx-grid-fc-set-fields',MODx.grid.FCSetFields); * @param {Object} config An object of configuration properties * @xtype modx-grid-fc-set-tabs */ -MODx.grid.FCSetTabs = function(config) { - config = config || {}; +MODx.grid.FCSetTabs = function(config = {}) { this.vcb = new Ext.ux.grid.CheckColumn({ - header: _('visible') - ,dataIndex: 'visible' - ,width: 40 - ,sortable: false + header: _('visible'), + dataIndex: 'visible', + width: 40, + sortable: false }); - Ext.applyIf(config,{ - id: 'modx-grid-fc-set-tabs' - ,showActionsColumn: false - ,fields: ['id','action','name','form','other','rank','visible','label','type'] - ,autoHeight: true - ,plugins: [this.vcb] - ,stateful: false - ,columns: [{ - header: _('region')+' ('+_('tab_id')+')' - ,dataIndex: 'name' - ,width: 100 - },this.vcb,{ - header: _('tab_title') - ,dataIndex: 'label' - ,editor: { xtype: 'textfield' } - }] - ,viewConfig: { - forceFit:true - ,enableRowBody:true - ,scrollOffset: 0 - ,autoFill: true - ,showPreview: true - ,getRowClass : function(rec, ri, p){ - return rec.data.visible ? 'grid-row-active' : 'grid-row-inactive'; - } - } - ,tbar: [{ - text: _('create') - ,cls: 'primary-button' - ,handler: this.createTab - ,scope: this + Ext.applyIf(config, { + id: 'modx-grid-fc-set-tabs', + showActionsColumn: false, + fields: [ + 'id', + 'action', + 'name', + 'form', + 'other', + 'rank', + 'visible', + 'label', + 'type' + ], + autoHeight: true, + plugins: [this.vcb], + stateful: false, + columns: [{ + header: `${_('region')} (${_('tab_id')})`, + dataIndex: 'name', + width: 100 + }, this.vcb, { + header: _('tab_title'), + dataIndex: 'label', + editor: { xtype: 'textfield' } + }], + viewConfig: this.getViewConfig(false, false, true), + tbar: [{ + text: _('create'), + cls: 'primary-button', + handler: this.createTab, + scope: this }] }); - MODx.grid.FCSetTabs.superclass.constructor.call(this,config); + MODx.grid.FCSetTabs.superclass.constructor.call(this, config); this.propRecord = Ext.data.Record.create(config.fields); }; -Ext.extend(MODx.grid.FCSetTabs,MODx.grid.LocalGrid,{ - getMenu: function(g,ri) { - var rec = this.getStore().getAt(ri); - if (rec.data.type == 'new') { +Ext.extend(MODx.grid.FCSetTabs, MODx.grid.LocalGrid, { + getMenu: function(g, ri) { + const record = this.getStore().getAt(ri); + if (record.data.type === 'new') { return [{ - text: _('delete') - ,handler: this.removeTab - ,scope: this + text: _('delete'), + handler: this.removeTab, + scope: this }]; } return []; - } + }, - ,createTab: function(btn,e) { + createTab: function(btn, e) { if (!this.windows.ctab) { this.windows.ctab = MODx.load({ - xtype: 'modx-window-fc-set-add-tab' - ,listeners: { - 'success': {fn:function(r) { - var s = this.getStore(); - var rec = new this.propRecord(r); - s.add(rec); - },scope:this} + xtype: 'modx-window-fc-set-add-tab', + listeners: { + success: { + fn: function(response) { + const + store = this.getStore(), + record = new this.propRecord(response) + ; + store.add(record); + }, + scope: this + } } }); } this.windows.ctab.reset(); this.windows.ctab.show(e.target); - } + }, - ,removeTab: function(btn,e) { - var rec = this.getSelectionModel().getSelected(); - Ext.Msg.confirm(_('delete'),_('tab_remove_confirm'),function(e) { - if (e == 'yes') { - this.getStore().remove(rec); + removeTab: function(btn, e) { + const record = this.getSelectionModel().getSelected(); + Ext.Msg.confirm(_('delete'), _('tab_remove_confirm'), function(e) { + if (e === 'yes') { + this.getStore().remove(record); } - },this); + }, this); } }); -Ext.reg('modx-grid-fc-set-tabs',MODx.grid.FCSetTabs); +Ext.reg('modx-grid-fc-set-tabs', MODx.grid.FCSetTabs); /** * @class MODx.grid.FCSetTVs @@ -408,81 +424,88 @@ Ext.reg('modx-grid-fc-set-tabs',MODx.grid.FCSetTabs); * @param {Object} config An object of configuration properties * @xtype modx-grid-fc-set-tvs */ -MODx.grid.FCSetTVs = function(config) { - config = config || {}; +MODx.grid.FCSetTVs = function(config = {}) { this.vcb = new Ext.ux.grid.CheckColumn({ - header: _('visible') - ,dataIndex: 'visible' - ,width: 40 - ,sortable: false + header: _('visible'), + dataIndex: 'visible', + width: 40, + sortable: false }); - Ext.applyIf(config,{ - id: 'modx-grid-fc-set-tvs' - ,showActionsColumn: false - ,fields: ['id','name','tab','rank','visible','label','default_value','category','default_text'] - ,autoHeight: true - ,grouping: true - ,groupBy: 'category' - ,sortBy: 'rank' - ,sortDir: 'ASC' - ,stateful: false - ,groupTextTpl: '{group} ({[values.rs.length]} {[values.rs.length > 1 ? "'+_('tvs')+'" : "'+_('tv')+'"]})' - ,plugins: [this.vcb] - ,hideGroupedColumn: true - ,columns: [{ - header: _('category') - ,dataIndex: 'category' - },{ - header: _('tv_name') - ,dataIndex: 'name' - ,width: 200 - ,renderer: { fn: function(v,md,record) { - return this.renderLink(v, { - href: '?a=element/tv/update&id=' + record.data.id - ,target: '_blank' - }); - }, scope: this } - },this.vcb,{ - header: _('label') - ,dataIndex: 'label' - ,editor: { xtype: 'textfield' } - },{ - header: _('default_value') - ,dataIndex: 'default_value' - ,editor: { xtype: 'textfield' } - ,renderer: function(v) { return Ext.util.Format.htmlEncode(v); } - },{ - header: _('original_value') - ,dataIndex: 'default_text' - ,editable: false - },{ - header: _('region')+' ('+_('tab_id')+')' - ,dataIndex: 'tab' - ,width: 100 - ,editor: { xtype: 'textfield' } - },{ - header: _('tab_rank') - ,dataIndex: 'rank' - ,width: 70 - ,editor: { xtype: 'textfield' } - }] - ,viewConfig: { - forceFit:true - ,enableRowBody:true - ,scrollOffset: 0 - ,autoFill: true - ,showPreview: true - ,getRowClass : function(rec, ri, p){ - return rec.data.visible ? 'grid-row-active' : 'grid-row-inactive'; + Ext.applyIf(config, { + id: 'modx-grid-fc-set-tvs', + showActionsColumn: false, + fields: [ + 'id', + 'name', + 'tab', + 'rank', + 'visible', + 'label', + 'default_value', + 'category', + 'default_text' + ], + autoHeight: true, + grouping: true, + groupBy: 'category', + sortBy: 'rank', + sortDir: 'ASC', + stateful: false, + groupTextTpl: `{group} ({[values.rs.length]} {[values.rs.length > 1 ? "${_('tvs')}" : "${_('tv')}"]})`, + plugins: [this.vcb], + hideGroupedColumn: true, + columns: [{ + header: _('category'), + dataIndex: 'category' + }, { + header: _('tv_name'), + dataIndex: 'name', + width: 200, + renderer: { + fn: function(value, metaData, record) { + const canEditTvs = MODx.perm.edit_tv && MODx.perm.save_tv; + return canEditTvs + ? this.renderLink(value, { + href: `?a=element/tv/update&id=${record.data.id}`, + target: '_blank' + }) + : value + ; + }, + scope: this } - } + }, this.vcb, { + header: _('label'), + dataIndex: 'label', + editor: { xtype: 'textfield' } + }, { + header: _('default_value'), + dataIndex: 'default_value', + editor: { xtype: 'textfield' }, + renderer: function(v) { return Ext.util.Format.htmlEncode(v); } + }, { + header: _('original_value'), + dataIndex: 'default_text', + editable: false + }, { + header: `${_('region')} (${_('tab_id')})`, + dataIndex: 'tab', + width: 100, + editor: { xtype: 'textfield' } + }, { + header: _('tab_rank'), + dataIndex: 'rank', + width: 70, + editor: { xtype: 'textfield' } + }], + viewConfig: this.getViewConfig(false, false, true) }); - MODx.grid.FCSetTVs.superclass.constructor.call(this,config); + MODx.grid.FCSetTVs.superclass.constructor.call(this, config); this.propRecord = Ext.data.Record.create(config.fields); }; -Ext.extend(MODx.grid.FCSetTVs,MODx.grid.LocalGrid,{ +Ext.extend(MODx.grid.FCSetTVs, MODx.grid.LocalGrid, { }); -Ext.reg('modx-grid-fc-set-tvs',MODx.grid.FCSetTVs); +Ext.reg('modx-grid-fc-set-tvs', MODx.grid.FCSetTVs); /** * @class MODx.window.AddTabToSet @@ -490,58 +513,58 @@ Ext.reg('modx-grid-fc-set-tvs',MODx.grid.FCSetTVs); * @param {Object} config An object of options. * @xtype modx-window-fc-set-add-tab */ -MODx.window.AddTabToSet = function(config) { - config = config || {}; - Ext.applyIf(config,{ - title: _('create') - ,fields: [{ - xtype: 'hidden' - ,name: 'container' - ,value: 'modx-resource-tabs' - },{ - xtype: 'hidden' - ,name: 'visible' - ,value: true - },{ - xtype: 'hidden' - ,name: 'type' - ,value: 'new' - },{ - xtype: 'textfield' - ,name: 'name' - ,fieldLabel: _('region')+' ('+_('tab_id')+')' - ,id: 'modx-fcatab-id' - ,allowBlank: false - ,anchor: '100%' - },{ - xtype: 'textfield' - ,fieldLabel: _('tab_title') - ,name: 'value' - ,id: 'modx-fcatab-name' - ,allowBlank: false - ,anchor: '100%' +MODx.window.AddTabToSet = function(config = {}) { + Ext.applyIf(config, { + title: _('create'), + fields: [{ + xtype: 'hidden', + name: 'container', + value: 'modx-resource-tabs' + }, { + xtype: 'hidden', + name: 'visible', + value: true + }, { + xtype: 'hidden', + name: 'type', + value: 'new' + }, { + xtype: 'textfield', + name: 'name', + fieldLabel: `${_('region')} (${_('tab_id')})`, + id: 'modx-fcatab-id', + allowBlank: false, + anchor: '100%' + }, { + xtype: 'textfield', + fieldLabel: _('tab_title'), + name: 'value', + id: 'modx-fcatab-name', + allowBlank: false, + anchor: '100%' }] }); - MODx.window.AddTabToSet.superclass.constructor.call(this,config); + MODx.window.AddTabToSet.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.AddTabToSet,MODx.Window,{ +Ext.extend(MODx.window.AddTabToSet, MODx.Window, { submit: function() { - var rec = this.fp.getForm().getValues(); - - var g = Ext.getCmp('modx-grid-fc-set-tabs'); - var s = g.getStore(); - var v = s.query('name',rec.name).items; - if (v.length > 0) { - MODx.msg.alert(_('error'),_('set_tab_err_ae')); + const + record = this.fp.getForm().getValues(), + grid = Ext.getCmp('modx-grid-fc-set-tabs'), + store = grid.getStore(), + matches = store.query('name', record.name).items + ; + if (matches.length > 0) { + MODx.msg.alert(_('error'), _('set_tab_err_ae')); return false; } - rec.label = rec.value; - rec.visible = true; - rec.type = 'new'; + record.label = record.value; + record.visible = true; + record.type = 'new'; - this.fireEvent('success',rec); + this.fireEvent('success', record); this.hide(); return false; } }); -Ext.reg('modx-window-fc-set-add-tab',MODx.window.AddTabToSet); +Ext.reg('modx-window-fc-set-add-tab', MODx.window.AddTabToSet); diff --git a/manager/assets/modext/widgets/resource/modx.grid.resource.security.local.js b/manager/assets/modext/widgets/resource/modx.grid.resource.security.local.js index db27310fdd0..6f6cae30997 100644 --- a/manager/assets/modext/widgets/resource/modx.grid.resource.security.local.js +++ b/manager/assets/modext/widgets/resource/modx.grid.resource.security.local.js @@ -4,43 +4,56 @@ * @param {Object} config An object of configuration properties * @xtype modx-grid-resource-security */ -MODx.grid.ResourceSecurity = function(config) { - config = config || {}; - var ac = new Ext.ux.grid.CheckColumn({ - header: _('access') - ,dataIndex: 'access' - ,width: 40 - ,sortable: true - ,hidden: MODx.perm.resourcegroup_resource_edit != 1 +MODx.grid.ResourceSecurity = function(config = {}) { + const accessCheckboxCol = new Ext.ux.grid.CheckColumn({ + header: _('access'), + dataIndex: 'access', + width: 40, + sortable: true, + hidden: !MODx.perm.resourcegroup_resource_edit }); - Ext.applyIf(config,{ - id: 'modx-grid-resource-security' - ,fields: ['id','name','access'] - ,showActionsColumn: false - ,paging: false - ,remoteSort: false - ,autoHeight: true - ,plugins: ac - ,columns: [{ - header: _('name') - ,dataIndex: 'name' - ,width: 200 - ,sortable: true - ,renderer: { fn: function(v,md,record) { - return this.renderLink(v, { - href: '?a=security/resourcegroup' - ,target: '_blank' - }); - }, scope: this } - },ac] + Ext.applyIf(config, { + id: 'modx-grid-resource-security', + fields: [ + 'id', + 'name', + 'access' + ], + showActionsColumn: false, + paging: false, + remoteSort: false, + autoHeight: true, + plugins: accessCheckboxCol, + columns: [ + { + header: _('name'), + dataIndex: 'name', + width: 200, + sortable: true, + renderer: { + fn: function(value, metaData, record) { + const canEditResourceGroups = MODx.perm.resourcegroup_edit || MODx.perm.resourcegroup_resource_edit; + return canEditResourceGroups + ? this.renderLink(value, { + href: `?a=security/resourcegroup&id=${record.data.id}`, + target: '_blank' + }) + : value + ; + }, + scope: this + } + }, + accessCheckboxCol + ] }); - MODx.grid.ResourceSecurity.superclass.constructor.call(this,config); + MODx.grid.ResourceSecurity.superclass.constructor.call(this, config); this.propRecord = Ext.data.Record.create(config.fields); - this.on('rowclick',MODx.fireResourceFormChange); + this.on('rowclick', MODx.fireResourceFormChange); this.store.sortInfo = { field: 'access', direction: 'DESC' }; }; -Ext.extend(MODx.grid.ResourceSecurity,MODx.grid.LocalGrid); -Ext.reg('modx-grid-resource-security',MODx.grid.ResourceSecurity); +Ext.extend(MODx.grid.ResourceSecurity, MODx.grid.LocalGrid); +Ext.reg('modx-grid-resource-security', MODx.grid.ResourceSecurity); diff --git a/manager/assets/modext/widgets/resource/modx.grid.trash.js b/manager/assets/modext/widgets/resource/modx.grid.trash.js index 0849f12cbcb..bbd1e2f814f 100644 --- a/manager/assets/modext/widgets/resource/modx.grid.trash.js +++ b/manager/assets/modext/widgets/resource/modx.grid.trash.js @@ -16,8 +16,7 @@ MODx.grid.Trash = function(config = {}) { 'parentPath', 'deletedon', 'deletedby', - 'deletedby_name', - 'cls' + 'deletedby_name' ], paging: true, autosave: true, @@ -46,7 +45,23 @@ MODx.grid.Trash = function(config = {}) { dataIndex: 'published', width: 40, sortable: true, - editor: {xtype: 'combo-boolean', renderer: 'boolean'} + editor: { + xtype: 'combo-boolean' + }, + renderer: { + fn: function(value, metaData, record) { + /* + This field depends on permission other than the typicaledit, + thus not using the base setEditableCellClasses() method here + */ + if (!record.json.permissions.publish) { + // eslint-disable-next-line no-param-reassign + metaData.css = 'editor-disabled'; + } + return this.rendYesNo(value, metaData); + }, + scope: this + } }, { header: _('trash.deletedon_title'), dataIndex: 'deletedon', @@ -61,39 +76,57 @@ MODx.grid.Trash = function(config = {}) { return record.data.deletedby_name; } }], - tbar: [ + /* + Not using base getBulkActionsButton() method here, as this menu utilizes + methods/actions specific to this class not supported by that method + */ { text: _('bulk_actions'), + id: 'modx-btn-bulk-actions', menu: [{ text: _('trash.selected_purge'), + itemId: 'modx-bulk-menu-opt-purge', handler: this.purgeSelected, scope: this }, { text: _('trash.selected_restore'), + itemId: 'modx-bulk-menu-opt-restore', handler: this.restoreSelected, scope: this - }] - }, { - text: _('trash.purge_all'), - id: 'modx-purge-all', - cls: 'x-btn-purge-all', + }], listeners: { click: { - fn: this.purgeAll, + fn: function(btn) { + const + menuOptPurge = btn.menu.getComponent('modx-bulk-menu-opt-purge'), + menuOptUndelete = btn.menu.getComponent('modx-bulk-menu-opt-restore') + ; + if (this.getSelectionModel().getCount() === 0) { + menuOptPurge.disable(); + menuOptUndelete.disable(); + } else { + if (this.userCanPurge) { + menuOptPurge.enable(); + } + if (this.userCanUndelete) { + menuOptUndelete.enable(); + } + } + }, scope: this } } + }, { + text: _('trash.purge_all'), + id: 'modx-btn-purge-all', + cls: 'x-btn-purge-all', + handler: this.purgeAll }, { text: _('trash.restore_all'), - id: 'modx-restore-all', + id: 'modx-btn-restore-all', cls: 'x-btn-restore-all', - listeners: { - click: { - fn: this.restoreAll, - scope: this - } - } + handler: this.restoreAll }, '->', { @@ -122,51 +155,88 @@ MODx.grid.Trash = function(config = {}) { }); MODx.grid.Trash.superclass.constructor.call(this, config); + + this.gridMenuActions = ['purge', 'undelete']; + this.setUserHasPermissions('purge', ['purge_deleted']); + this.setUserHasPermissions('undelete', ['undelete_document']); + this.setShowActionsMenu(); + + this.on({ + render: grid => { + const buttonsToHide = []; + if (!this.userCanPurge && !this.userCanUndelete) { + buttonsToHide.push('modx-btn-bulk-actions', 'modx-btn-purge-all', 'modx-btn-restore-all'); + } else { + const bulkMenu = Ext.getCmp('modx-btn-bulk-actions').menu; + if (!this.userCanPurge) { + buttonsToHide.push('modx-btn-purge-all'); + bulkMenu.getComponent('modx-bulk-menu-opt-purge').disable(); + } + if (!this.userCanUndelete) { + buttonsToHide.push('modx-btn-restore-all'); + bulkMenu.getComponent('modx-bulk-menu-opt-restore').disable(); + } + } + if (buttonsToHide.length > 0) { + buttonsToHide.forEach(btnId => Ext.getCmp(btnId)?.hide()); + } + }, + beforeedit: function(e) { + if (e.field === 'published' && !this.userCanEditRecord(e.record, 'publish')) { + return false; + } + } + }); }; Ext.extend(MODx.grid.Trash, MODx.grid.Grid, { - getMenu: function () { - var r = this.getSelectionModel().getSelected(); - var p = r.data.cls; - - var m = []; - if (this.getSelectionModel().getCount() > 1) { - m.push({ - text: _('trash.selected_purge'), - handler: this.purgeSelected, - scope: this - }); - m.push({ - text: _('trash.selected_restore'), - handler: this.restoreSelected, - scope: this - }); + getMenu: function() { + const + model = this.getSelectionModel(), + record = model.getSelected(), + canPurge = this.userCanPurge && this.userCanDeleteRecord(record, 'purge'), + canUndelete = this.userCanUndelete && this.userCanEditRecord(record, 'undelete'), + menu = [] + ; + if (model.getCount() > 1) { + if (canPurge) { + menu.push({ + text: _('trash.selected_purge'), + handler: this.purgeSelected, + scope: this + }); + } + if (canUndelete) { + menu.push({ + text: _('trash.selected_restore'), + handler: this.restoreSelected, + scope: this + }); + } } else { - if (p.indexOf('trashpurge') !== -1) { - m.push({ + if (canPurge) { + menu.push({ text: _('trash.purge'), handler: this.purgeResource }); } - if (p.indexOf('trashundelete') !== -1) { - m.push({ + if (canUndelete) { + menu.push({ text: _('trash.restore'), handler: this.restoreResource }); } } - if (m.length > 0) { - this.addContextMenuItem(m); - } + return menu; }, - purgeResource: function () { + purgeResource: function() { MODx.msg.confirm({ minWidth: 500, title: _('trash.purge_confirm_title'), text: _('trash.purge_confirm_message', { - 'list': this.listResources('') + list: this.listResources('') }), url: this.config.url, params: { @@ -174,33 +244,35 @@ Ext.extend(MODx.grid.Trash, MODx.grid.Grid, { ids: this.menu.record.id }, listeners: { - 'success': { - fn: function (data) { + success: { + fn: function(data) { this.refreshEverything(data.total); - }, scope: this + }, + scope: this }, - 'error': { - fn: function (data) { + error: { + fn: function(data) { MODx.msg.status({ title: _('error'), message: data.message }); - }, scope: this + }, + scope: this } } }); }, - restoreResource: function () { - var withPublish = ''; + restoreResource: function() { + let withPublish = ''; if (this.menu.record.published) { withPublish = '_with_publish'; } MODx.msg.confirm({ minWidth: 500, title: _('trash.restore_confirm_title'), - text: _('trash.restore_confirm_message' + withPublish, { - 'list': this.listResources('') + text: _(`trash.restore_confirm_message${withPublish}`, { + list: this.listResources('') }), url: this.config.url, params: { @@ -208,52 +280,57 @@ Ext.extend(MODx.grid.Trash, MODx.grid.Grid, { id: this.menu.record.id }, listeners: { - 'success': { - fn: function (data) { + success: { + fn: function(data) { this.refreshEverything(data.total); - }, scope: this + }, + scope: this }, - 'error': { - fn: function (data) { + error: { + fn: function(data) { MODx.msg.status({ title: _('error'), message: data.message }); - }, scope: this + }, + scope: this } } }); }, - purgeSelected: function () { - var cs = this.getSelectedAsList(); - if (cs === false) return false; - + purgeSelected: function() { + const selections = this.getSelectedAsList(); + if (selections === false) { + return false; + } MODx.msg.confirm({ minWidth: 500, title: _('trash.purge_confirm_title'), text: _('trash.purge_confirm_message', { - 'list': this.listResources('') + list: this.listResources('') }), url: this.config.url, params: { action: 'Resource/Trash/Purge', - ids: cs + ids: selections }, listeners: { - 'success': { - fn: function (data) { + success: { + fn: function(data) { this.getSelectionModel().clearSelections(true); this.refreshEverything(data.object.deletedCount); - }, scope: this + }, + scope: this }, - 'error': { - fn: function (data) { + error: { + fn: function(data) { MODx.msg.status({ title: _('error'), message: data.message }); - }, scope: this + }, + scope: this } } }); @@ -261,52 +338,56 @@ Ext.extend(MODx.grid.Trash, MODx.grid.Grid, { return true; }, - restoreSelected: function () { - var cs = this.getSelectedAsList(); - if (cs === false) return false; - + restoreSelected: function() { + const selections = this.getSelectedAsList(); + if (selections === false) { + return false; + } MODx.msg.confirm({ minWidth: 500, title: _('trash.restore_confirm_title'), text: _('trash.restore_confirm_message', { - 'list': this.listResources('') + list: this.listResources('') }), url: this.config.url, params: { action: 'Resource/Trash/Restore', - ids: cs + ids: selections }, listeners: { - 'success': { - fn: function (data) { + success: { + fn: function(data) { this.refreshEverything(data.total); - }, scope: this + }, + scope: this }, - 'error': { - fn: function (data) { + error: { + fn: function(data) { MODx.msg.status({ title: _('error'), message: data.message }); - }, scope: this + }, + scope: this } } }); return true; }, - purgeAll: function () { - var sm = this.getSelectionModel(); - sm.selectAll(); - var cs = this.getSelectedAsList(); - if (cs === false) return false; - + purgeAll: function() { + const model = this.getSelectionModel(); + model.selectAll(); + const selections = this.getSelectedAsList(); + if (selections === false) { + return false; + } MODx.msg.confirm({ minWidth: 500, title: _('trash.purge_confirm_title'), text: _('trash.purge_all_confirm_message', { - 'count': sm.selections.length, - 'list': this.listResources('') + count: model.selections.length, + list: this.listResources('') }), url: this.config.url, params: { @@ -316,11 +397,11 @@ Ext.extend(MODx.grid.Trash, MODx.grid.Grid, { // shown in the trash manager list because of missing reload. // in that case we would purge something unreviewed/blindly. // therefore we have to pass all ids which are shown in our list here - ids: cs + ids: selections }, listeners: { - 'success': { - fn: function (data) { + success: { + fn: function(data) { MODx.msg.status({ title: _('success'), message: data.message @@ -329,32 +410,35 @@ Ext.extend(MODx.grid.Trash, MODx.grid.Grid, { this.refreshEverything(data.total); // no need to refresh if nothing was purged this.fireEvent('emptyTrash'); } - }, scope: this + }, + scope: this }, - 'error': { - fn: function (data) { + error: { + fn: function(data) { MODx.msg.status({ title: _('error'), message: data.message }); - }, scope: this + }, + scope: this } } - }) + }); }, - restoreAll: function () { - var sm = this.getSelectionModel(); - sm.selectAll(); - var cs = this.getSelectedAsList(); - if (cs === false) return false; - + restoreAll: function() { + const model = this.getSelectionModel(); + model.selectAll(); + const selections = this.getSelectedAsList(); + if (selections === false) { + return false; + } MODx.msg.confirm({ minWidth: 500, title: _('trash.restore_confirm_title'), text: _('trash.restore_all_confirm_message', { - 'count': sm.selections.length, - 'list': this.listResources('') + count: model.selections.length, + list: this.listResources('') }), url: this.config.url, params: { @@ -364,11 +448,11 @@ Ext.extend(MODx.grid.Trash, MODx.grid.Grid, { // shown in the trash manager list because of missing reload. // in that case we would restore something unreviewed/blindly. // therefore we have to pass all ids which are shown in our list here - ids: cs + ids: selections }, listeners: { - 'success': { - fn: function (data) { + success: { + fn: function(data) { MODx.msg.status({ title: _('success'), message: data.message @@ -377,65 +461,67 @@ Ext.extend(MODx.grid.Trash, MODx.grid.Grid, { this.refreshEverything(data.total); // no need to refresh if nothing was purged this.fireEvent('emptyTrash'); } - }, scope: this + }, + scope: this }, - 'error': { - fn: function (data) { + error: { + fn: function(data) { MODx.msg.status({ title: _('error'), message: data.message }); - }, scope: this + }, + scope: this } } - }) + }); }, - refreshTree: function () { - var t = Ext.getCmp('modx-resource-tree'); - t.refresh(); + refreshTree: function() { + const tree = Ext.getCmp('modx-resource-tree'); + tree.refresh(); this.refreshRecycleBinButton(); }, - refreshEverything: function (total) { + refreshEverything: function(total) { this.refresh(); this.refreshTree(); this.refreshRecycleBinButton(total); }, - refreshRecycleBinButton: function (total) { + refreshRecycleBinButton: function(total) { Ext.getCmp('modx-trash-link')?.updateState(+total); }, - listResources: function (separator) { - separator = separator || ''; - + listResources: function(separator = '') { // creates a textual representation of the selected resources // we create a textlist of the resources here to show them again in the confirmation box - var selections = this.getSelectionModel().getSelections(); - var text = [], t; - selections.forEach(function (selection) { - t = selection.data.parentPath + "" + selection.data.pagetitle + " (" + selection.data.id + ")" + ""; + const + selections = this.getSelectionModel().getSelections(), + text = [] + ; + let resourceRef; + selections.forEach(function(selection) { + resourceRef = `${selection.data.parentPath}${selection.data.pagetitle} (${selection.data.id})`; if (selection.data.published) { - t = '' + t + ''; + resourceRef = `${resourceRef}`; } - t = "
    " + t + "
    "; - text.push(t); + resourceRef = `
    ${resourceRef}
    `; + text.push(resourceRef); }); return text.join(separator); }, - renderTooltip: function (value, metadata, record) { + renderTooltip: function(value, metadata, record) { if (value) { - var preview = ((record.json.pagetitle) ? '

    ' + _('pagetitle') + ': ' + record.json.pagetitle + '

    ' : '') - + ((record.json.longtitle) ? '

    ' + _('long_title') + ': ' + record.json.longtitle + '

    ' : '') - + ((record.data.parentPath) ? '

    ' + _('trash.parent_path') + ': ' + record.data.parentPath + '

    ' : '') - + ((record.json.content) ? '

    ' + _('content') + ': ' + Ext.util.Format.ellipsis(record.json.content.replace(/<\/?[^>]+>/gi, ''), 100) + '

    ' : ''); + let preview = ((record.json.pagetitle) ? `

    ${_('pagetitle')}: ${record.json.pagetitle}

    ` : '') + + ((record.json.longtitle) ? `

    ${_('long_title')}: ${record.json.longtitle}

    ` : '') + + ((record.data.parentPath) ? `

    ${_('trash.parent_path')}: ${record.data.parentPath}

    ` : '') + + ((record.json.content) ? `

    ${_('content')}: ${Ext.util.Format.ellipsis(record.json.content.replace(/<\/?[^>]+>/gi, ''), 100)}

    ` : ''); preview = Ext.util.Format.htmlEncode(preview); - return '
    ' + value + '
    '; - } else { - return ''; + return `
    ${value}
    `; } + return ''; } }); Ext.reg('modx-grid-trash', MODx.grid.Trash); diff --git a/manager/assets/modext/widgets/security/modx.grid.access.context.js b/manager/assets/modext/widgets/security/modx.grid.access.context.js index 3410bc15646..9e2bae55610 100644 --- a/manager/assets/modext/widgets/security/modx.grid.access.context.js +++ b/manager/assets/modext/widgets/security/modx.grid.access.context.js @@ -6,148 +6,191 @@ * @param {Object} config An object of options. * @xtype modx-grid-access-context */ -MODx.grid.AccessContext = function(config) { - config = config || {}; - Ext.applyIf(config,{ - id: 'modx-grid-access-context' - ,url: MODx.config.connector_url - ,baseParams: { - action: 'Security/Access/GetList' - ,type: config.type || 'MODX\\Revolution\\modAccessContext' - ,target: config.context_key - } - ,fields: ['id','target','target_name','principal_class','principal','principal_name','authority','policy','policy_name','cls'] - ,type: 'modAccessContext' - ,paging: true - ,columns: [{ - header: _('context') - ,dataIndex: 'target_name' - ,width: 100 - },{ - header: _('user_group') - ,dataIndex: 'principal_name' - ,width: 120 - ,renderer: { fn: function(v,md,record) { - return this.renderLink(v, { - href: '?a=security/usergroup/update&id=' + record.data.principal - ,target: '_blank' - }); - }, scope: this } - },{ - header: _('authority') - ,dataIndex: 'authority' - ,width: 50 - },{ - header: _('policy') - ,dataIndex: 'policy_name' - ,width: 175 - ,renderer: { fn: function(v,md,record) { - return this.renderLink(v, { - href: '?a=security/access/policy/update&id=' + record.data.policy - ,target: '_blank' - }); - }, scope: this } - }] - ,tbar: [{ - text: _('create') - ,cls: 'primary-button' - ,scope: this - ,handler: this.createAcl +MODx.grid.AccessContext = function(config = {}) { + Ext.applyIf(config, { + id: 'modx-grid-access-context', + url: MODx.config.connector_url, + baseParams: { + action: 'Security/Access/GetList', + type: config.type || 'MODX\\Revolution\\modAccessContext', + target: config.context_key + }, + fields: ['id', + 'target', + 'target_name', + 'principal_class', + 'principal', + 'principal_name', + 'authority', + 'policy', + 'policy_name' + ], + type: 'modAccessContext', + paging: true, + columns: [{ + header: _('context'), + dataIndex: 'target_name', + width: 100 + }, { + header: _('user_group'), + dataIndex: 'principal_name', + width: 120, + renderer: { + fn: function(value, metaData, record) { + return record.json.canEditGroups + ? this.renderLink(value, { + href: `?a=security/usergroup/update&id=${record.data.principal}`, + target: '_blank' + }) + : value + ; + }, + scope: this + } + }, { + header: _('authority'), + dataIndex: 'authority', + width: 50 + }, { + header: _('policy'), + dataIndex: 'policy_name', + width: 175, + renderer: { + fn: function(value, metaData, record) { + return record.json.canEditGroups + ? this.renderLink(value, { + href: `?a=security/access/policy/update&id=${record.data.policy}`, + target: '_blank' + }) + : value + ; + }, + scope: this + } + }], + tbar: [{ + text: _('create'), + cls: 'primary-button', + scope: this, + handler: this.createAcl }] }); - MODx.grid.AccessContext.superclass.constructor.call(this,config); -}; -Ext.extend(MODx.grid.AccessContext,MODx.grid.Grid,{ - combos: {} - ,windows: {} + MODx.grid.AccessContext.superclass.constructor.call(this, config); - ,getMenu: function() { - var r = this.getSelectionModel().getSelected(); - var p = r.data.cls; + this.gridMenuActions = ['edit', 'delete']; - var m = []; - if (this.getSelectionModel().getCount() > 1) { + // Note there are currently no action-specific permissions for Access Permissions + this.setUserCanEdit(['access_permissions']); + this.setUserCanCreate(['access_permissions']); + this.setUserCanDelete(['access_permissions']); + this.setShowActionsMenu(); - } else { - if (p.indexOf('pedit') != -1) { - m.push({ - text: _('edit') - ,handler: this.editAcl + this.on({ + beforerender: function(grid) { + grid.view = new Ext.grid.GridView(grid.getViewConfig(false, false)); + } + }); +}; +Ext.extend(MODx.grid.AccessContext, MODx.grid.Grid, { + combos: {}, + windows: {}, + + getMenu: function() { + const + record = this.getSelectionModel().getSelected(), + menu = [] + ; + if (this.getSelectionModel().getCount() === 1) { + if (this.userCanEdit && this.userCanEditRecord(record)) { + menu.push({ + text: _('edit'), + handler: this.editAcl }); } - if (p.indexOf('premove') != -1) { - if (m.length > 0) { m.push('-'); } - m.push({ - text: _('delete') - ,handler: this.removeAcl + if (this.userCanDelete && this.userCanDeleteRecord(record)) { + if (menu.length > 0) { + menu.push('-'); + } + menu.push({ + text: _('delete'), + handler: this.removeAcl }); } } - if (m.length > 0) { - this.addContextMenuItem(m); + if (menu.length > 0) { + this.addContextMenuItem(menu); } - } + }, - ,createAcl: function(itm,e) { - var r = { - target: this.config.context_key - ,principal_class: 'MODX\\Revolution\\modUserGroup' + createAcl: function(itm, e) { + const record = { + target: this.config.context_key, + principal_class: 'MODX\\Revolution\\modUserGroup' }; if (!this.windows.create_acl) { this.windows.create_acl = MODx.load({ - xtype: 'modx-window-access-context-create' - ,record: r - ,listeners: { - 'success': {fn:function(o) { - this.refresh(); - },scope:this} + xtype: 'modx-window-access-context-create', + record: record, + listeners: { + success: { + fn: function() { + this.refresh(); + }, + scope: this + } } }); } this.windows.create_acl.fp.getForm().reset(); - this.windows.create_acl.setValues(r); + this.windows.create_acl.setValues(record); this.windows.create_acl.show(e.target); - } + }, - ,editAcl: function(itm,e) { - var r = this.menu.record; - Ext.applyIf(r,{ - context: r.target - ,user_group: r.principal + editAcl: function(itm, e) { + const { record } = this.menu; + Ext.applyIf(record, { + context: record.target, + user_group: record.principal }); if (!this.windows.update_acl) { this.windows.update_acl = MODx.load({ - xtype: 'modx-window-access-context-update' - ,acl: r.id - ,record: r - ,listeners: { - 'success': {fn:this.refresh,scope:this} + xtype: 'modx-window-access-context-update', + acl: record.id, + record: record, + listeners: { + success: { + fn: this.refresh, + scope: this + } } }); } - this.windows.update_acl.setValues(r); + this.windows.update_acl.setValues(record); this.windows.update_acl.show(e.target); - } + }, - ,removeAcl: function(itm,e) { + removeAcl: function(itm, e) { MODx.msg.confirm({ - title: _('ugc_remove') - ,text: _('access_confirm_remove') - ,url: this.config.url - ,params: { - action: 'Security/Access/RemoveAcl' - ,id: this.menu.record.id - ,type: this.config.type || 'modAccessContext' - } - ,listeners: { - 'success': {fn:this.refresh,scope:this} + title: _('ugc_remove'), + text: _('access_confirm_remove'), + url: this.config.url, + params: { + action: 'Security/Access/RemoveAcl', + id: this.menu.record.id, + type: this.config.type || 'modAccessContext' + }, + listeners: { + success: { + fn: this.refresh, + scope: this + } } }); } }); -Ext.reg('modx-grid-access-context',MODx.grid.AccessContext); +Ext.reg('modx-grid-access-context', MODx.grid.AccessContext); /** * @class MODx.window.CreateAccessContext @@ -155,61 +198,59 @@ Ext.reg('modx-grid-access-context',MODx.grid.AccessContext); * @param {Object} config An object of options. * @xtype modx-window-access-context-create */ -MODx.window.CreateAccessContext = function(config) { - config = config || {}; - var r = config.record; - - Ext.applyIf(config,{ - title: _('ugc_mutate') - ,url: MODx.config.connector_url - ,baseParams: { - action: 'Security/Access/AddAcl' - ,type: config.type || 'modAccessContext' - } - ,type: 'modAccessContext' - ,acl: 0 - ,fields: [{ - xtype: 'hidden' - ,name: 'id' - ,value: r.id || '' - },{ - xtype: 'hidden' - ,name: 'target' - ,value: r.context || '' - },{ - xtype: 'hidden' - ,name: 'principal_class' - ,value: 'MODX\\Revolution\\modUserGroup' - },{ - xtype: 'modx-combo-usergroup' - ,fieldLabel: _('user_group') - ,name: 'principal' - ,hiddenName: 'principal' - ,anchor: '100%' - ,value: r.principal || '' - ,baseParams: { - action: 'Security/Group/GetList' - ,combo: true +MODx.window.CreateAccessContext = function(config = {}) { + const { record } = config; + Ext.applyIf(config, { + title: _('ugc_mutate'), + url: MODx.config.connector_url, + baseParams: { + action: 'Security/Access/AddAcl', + type: config.type || 'modAccessContext' + }, + type: 'modAccessContext', + acl: 0, + fields: [{ + xtype: 'hidden', + name: 'id', + value: record.id || '' + }, { + xtype: 'hidden', + name: 'target', + value: record.context || '' + }, { + xtype: 'hidden', + name: 'principal_class', + value: 'MODX\\Revolution\\modUserGroup' + }, { + xtype: 'modx-combo-usergroup', + fieldLabel: _('user_group'), + name: 'principal', + hiddenName: 'principal', + anchor: '100%', + value: record.principal || '', + baseParams: { + action: 'Security/Group/GetList', + combo: true } - },{ - xtype: 'modx-combo-policy' - ,fieldLabel: _('policy') - ,name: 'policy' - ,hiddenName: 'policy' - ,value: r.policy || '' - ,anchor: '100%' - },{ - xtype: 'textfield' - ,fieldLabel: _('authority') - ,name: 'authority' - ,anchor: '100%' - ,value: r.authority || '' + }, { + xtype: 'modx-combo-policy', + fieldLabel: _('policy'), + name: 'policy', + hiddenName: 'policy', + value: record.policy || '', + anchor: '100%' + }, { + xtype: 'textfield', + fieldLabel: _('authority'), + name: 'authority', + anchor: '100%', + value: record.authority || '' }] }); - MODx.window.CreateAccessContext.superclass.constructor.call(this,config); + MODx.window.CreateAccessContext.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.CreateAccessContext,MODx.Window); -Ext.reg('modx-window-access-context-create',MODx.window.CreateAccessContext); +Ext.extend(MODx.window.CreateAccessContext, MODx.Window); +Ext.reg('modx-window-access-context-create', MODx.window.CreateAccessContext); /** * @class MODx.window.UpdateAccessContext @@ -217,18 +258,16 @@ Ext.reg('modx-window-access-context-create',MODx.window.CreateAccessContext); * @param {Object} config An object of options. * @xtype modx-window-access-context-update */ -MODx.window.UpdateAccessContext = function(config) { - config = config || {}; - var r = config.record; - this.ident = config.ident || 'uactx'+Ext.id(); - Ext.applyIf(config,{ - title: _('ugc_mutate') - ,baseParams: { - action: 'Security/Access/UpdateAcl' - ,type: config.type || 'modAccessContext' +MODx.window.UpdateAccessContext = function(config = {}) { + this.ident = config.ident || `uactx${Ext.id()}`; + Ext.applyIf(config, { + title: _('ugc_mutate'), + baseParams: { + action: 'Security/Access/UpdateAcl', + type: config.type || 'modAccessContext' } }); - MODx.window.UpdateAccessContext.superclass.constructor.call(this,config); + MODx.window.UpdateAccessContext.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.UpdateAccessContext,MODx.window.CreateAccessContext); -Ext.reg('modx-window-access-context-update',MODx.window.UpdateAccessContext); +Ext.extend(MODx.window.UpdateAccessContext, MODx.window.CreateAccessContext); +Ext.reg('modx-window-access-context-update', MODx.window.UpdateAccessContext); diff --git a/manager/assets/modext/widgets/security/modx.grid.access.policy.js b/manager/assets/modext/widgets/security/modx.grid.access.policy.js index 4631ca43d44..c5d5cf9626a 100644 --- a/manager/assets/modext/widgets/security/modx.grid.access.policy.js +++ b/manager/assets/modext/widgets/security/modx.grid.access.policy.js @@ -7,30 +7,30 @@ * @xtype modx-panel-access-policies */ MODx.panel.AccessPolicies = function(config = {}) { - Ext.applyIf(config,{ - id: 'modx-panel-access-policies' - ,bodyStyle: '' - ,defaults: { collapsible: false, autoHeight: true } - ,items: [{ - html: _('policies') - ,id: 'modx-policies-header' - ,xtype: 'modx-header' - },{ - layout: 'form' - ,cls: 'main-wrapper' - ,items: [{ - html: '

    '+_('policy_management_msg')+'

    ' - ,border: false - },{ - xtype: 'modx-grid-access-policy' - ,preventRender: true + Ext.applyIf(config, { + id: 'modx-panel-access-policies', + bodyStyle: '', + defaults: { collapsible: false, autoHeight: true }, + items: [{ + html: _('policies'), + id: 'modx-policies-header', + xtype: 'modx-header' + }, { + layout: 'form', + cls: 'main-wrapper', + items: [{ + html: `

    ${_('policy_management_msg')}

    `, + border: false + }, { + xtype: 'modx-grid-access-policy', + preventRender: true }] }] }); - MODx.panel.AccessPolicies.superclass.constructor.call(this,config); + MODx.panel.AccessPolicies.superclass.constructor.call(this, config); }; -Ext.extend(MODx.panel.AccessPolicies,MODx.FormPanel); -Ext.reg('modx-panel-access-policies',MODx.panel.AccessPolicies); +Ext.extend(MODx.panel.AccessPolicies, MODx.FormPanel); +Ext.reg('modx-panel-access-policies', MODx.panel.AccessPolicies); /** * Loads a grid of modAccessPolicies. @@ -43,212 +43,252 @@ Ext.reg('modx-panel-access-policies',MODx.panel.AccessPolicies); MODx.grid.AccessPolicy = function(config = {}) { const queryValue = this.applyRequestFilter(2, 'query', 'tab', true); this.sm = new Ext.grid.CheckboxSelectionModel(); - Ext.applyIf(config,{ - id: 'modx-grid-access-policy' - ,url: MODx.config.connector_url - ,baseParams: { + Ext.applyIf(config, { + id: 'modx-grid-access-policy', + url: MODx.config.connector_url, + baseParams: { action: 'Security/Access/Policy/GetList' - } - ,fields: [ + }, + fields: [ 'id', 'name', 'description', 'description_trans', - 'class', - 'data', 'parent', 'template', 'template_name', 'active_permissions', 'total_permissions', 'active_of', - 'cls' - ] - ,paging: true - ,autosave: true - ,save_action: 'Security/Access/Policy/UpdateFromGrid' - ,remoteSort: true - ,sm: this.sm - ,columns: [this.sm,{ - header: _('policy_name') - ,dataIndex: 'name' - ,width: 200 - ,editor: { xtype: 'textfield' ,allowBlank: false } - ,sortable: true - ,renderer: { fn: function(v,md,record) { - return this.renderLink(v, { - href: '?a=security/access/policy/update&id=' + record.data.id - }); - }, scope: this } - },{ - header: _('description') - ,dataIndex: 'description' - ,width: 375 - ,renderer: function(value, metaData, record) { - return Ext.util.Format.htmlEncode(record['data']['description_trans']); + 'creator' + ], + paging: true, + autosave: true, + save_action: 'Security/Access/Policy/UpdateFromGrid', + remoteSort: true, + sm: this.sm, + columns: [this.sm, { + header: _('policy_name'), + dataIndex: 'name', + width: 200, + editor: { + xtype: 'textfield', + allowBlank: false + }, + sortable: true, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record, [record.json.isProtected]); + return this.userCanEditRecord(record) + ? this.renderLink(value, { + href: `?a=security/access/policy/update&id=${record.data.id}`, + title: _('policy_edit') + }) + : value + ; + }, + scope: this } - ,editable: false - },{ - header: _('policy_template') - ,dataIndex: 'template_name' - ,width: 375 - ,renderer: { fn: function(v,md,record) { - return this.renderLink(v, { - href: '?a=security/access/policy/template/update&id=' + record.data.template - ,target: '_blank' - }); - }, scope: this } - },{ - header: _('active_permissions') - ,dataIndex: 'active_of' - ,width: 100 - ,editable: false - }] - ,tbar: [ + }, { + header: _('description'), + dataIndex: 'description', + width: 375, + editor: { + xtype: 'textarea' + }, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record, [record.json.isProtected]); + return record.json.description_trans || value; + }, + scope: this + } + }, { + header: _('policy_template'), + dataIndex: 'template_name', + width: 375, + renderer: { + fn: function(value, metaData, record) { + const objPermissions = record.json.permissions; + return !Ext.isEmpty(objPermissions) && objPermissions.updateTemplate === true + ? this.renderLink(value, { + href: `?a=security/access/policy/template/update&id=${record.data.template}`, + title: _('policy_template_edit'), + target: '_blank' + }) + : value + ; + }, + scope: this + } + }, + this.getCreatorColumnConfig('policy'), + { + header: _('active_permissions'), + dataIndex: 'active_of', + width: 100, + editable: false + }], + tbar: [ + this.getCreateButton('policy', 'createPolicy'), { - text: _('create') - ,cls:'primary-button' - ,scope: this - ,handler: this.createPolicy - },{ - text: _('import') - ,scope: this - ,handler: this.importPolicy - },{ - text: _('bulk_actions') - ,menu: [{ - text: _('selected_remove') - ,handler: this.removeSelected - ,scope: this - }] + text: _('import'), + scope: this, + handler: this.importPolicy, + listeners: { + render: { + fn: function(btn) { + if (!this.userCanCreate) { + btn.hide(); + } + }, + scope: this + } + } }, + this.getBulkActionsButton('policy', 'Security/Access/Policy/RemoveMultiple'), '->', this.getQueryFilterField(`filter-query-policy:${queryValue}`), this.getClearFiltersButton('filter-query-policy') - ] + ], + viewConfig: this.getViewConfig() + }); + MODx.grid.AccessPolicy.superclass.constructor.call(this, config); + + this.gridMenuActions = ['edit', 'delete', 'duplicate', 'export']; + + this.setUserCanEdit(['policy_save', 'policy_edit']); + this.setUserCanCreate(['policy_save', 'policy_new']); + this.setUserCanDelete(['policy_delete']); + this.setShowActionsMenu(); + + this.on({ + beforeedit: function(e) { + if (!this.userCanEdit || e.record.json.isProtected || !this.userCanEditRecord(e.record)) { + return false; + } + }, + afteredit: function(e) { + this.refresh(); + } }); - MODx.grid.AccessPolicy.superclass.constructor.call(this,config); }; -Ext.extend(MODx.grid.AccessPolicy,MODx.grid.Grid,{ - editPolicy: function(itm,e) { - MODx.loadPage('security/access/policy/update', 'id='+this.menu.record.id); - } +Ext.extend(MODx.grid.AccessPolicy, MODx.grid.Grid, { + getMenu: function() { + const + model = this.getSelectionModel(), + record = model.getSelected(), + menu = [] + ; + if (model.getCount() > 1) { + const records = model.getSelections(); + if (this.userCanDelete && this.userCanDeleteRecords(records)) { + menu.push({ + text: _('selected_remove'), + handler: this.removeSelected.bind(this, 'policy', 'Security/Access/Policy/RemoveMultiple') + }); + } + } else { + if (this.userCanEdit && this.userCanEditRecord(record)) { + menu.push({ + text: _('edit'), + handler: this.editPolicy + }); + } + if (this.userCanCreate && this.userCanDuplicateRecord(record)) { + menu.push({ + text: _('duplicate'), + handler: this.confirm.createDelegate(this, ['Security/Access/Policy/Duplicate', 'policy_duplicate_confirm']) + }); + } + if (menu.length > 0) { + menu.push('-'); + } + menu.push({ + text: _('export'), + handler: this.exportPolicy + }); + if (this.userCanDelete && this.userCanDeleteRecord(record)) { + if (menu.length > 0) { + menu.push('-'); + } + menu.push({ + text: _('delete'), + handler: this.confirm.createDelegate(this, ['Security/Access/Policy/Remove', 'policy_remove_confirm']) + }); + } + } + return menu; + }, + + editPolicy: function(itm, e) { + MODx.loadPage('security/access/policy/update', `id=${this.menu.record.id}`); + }, - ,createPolicy: function(btn,e) { - var r = this.menu.record; + createPolicy: function(btn, e) { + const { record } = this.menu; if (!this.windows.apc) { this.windows.apc = MODx.load({ - xtype: 'modx-window-access-policy-create' - ,record: r - ,plugin: this.config.plugin - ,listeners: { - 'success': {fn:function(r) { - this.refresh(); - },scope:this} + xtype: 'modx-window-access-policy-create', + record: record, + plugin: this.config.plugin, + listeners: { + success: { + fn: function() { + this.refresh(); + }, + scope: this + } } }); } this.windows.apc.reset(); this.windows.apc.show(e.target); - } + }, - ,exportPolicy: function(btn,e) { - var id = this.menu.record.id; + exportPolicy: function(btn, e) { + const { id } = this.menu.record; MODx.Ajax.request({ - url: this.config.url - ,params: { - action: 'Security/Access/Policy/Export' - ,id: id - } - ,listeners: { - 'success': {fn:function(r) { - location.href = this.config.url+'?action=Security/Access/Policy/Export&download=1&id='+id+'&HTTP_MODAUTH='+MODx.siteId; - },scope:this} + url: this.config.url, + params: { + action: 'Security/Access/Policy/Export', + id: id + }, + listeners: { + success: { + fn: function(r) { + window.location.href = `${this.config.url}?action=Security/Access/Policy/Export&download=1&id=${id}&HTTP_MODAUTH=${MODx.siteId}`; + }, + scope: this + } } }); - } + }, - ,importPolicy: function(btn,e) { - var r = {}; + importPolicy: function(btn, e) { + const record = {}; if (!this.windows.importPolicy) { this.windows.importPolicy = MODx.load({ - xtype: 'modx-window-policy-import' - ,record: r - ,listeners: { - 'success': {fn:function(o) { - this.refresh(); - },scope:this} + xtype: 'modx-window-policy-import', + record: record, + listeners: { + success: { + fn: function(o) { + this.refresh(); + }, + scope: this + } } }); } this.windows.importPolicy.reset(); - this.windows.importPolicy.setValues(r); + this.windows.importPolicy.setValues(record); this.windows.importPolicy.show(e.target); } - - ,getMenu: function() { - var r = this.getSelectionModel().getSelected(); - var p = r.data.cls; - - var m = []; - if (this.getSelectionModel().getCount() > 1) { - m.push({ - text: _('selected_remove') - ,handler: this.removeSelected - }); - } else { - if (p.indexOf('pedit') != -1) { - m.push({ - text: _('edit') - ,handler: this.editPolicy - }); - m.push({ - text: _('duplicate') - ,handler: this.confirm.createDelegate(this,["Security/Access/Policy/Duplicate","policy_duplicate_confirm"]) - }); - } - if (m.length > 0) { m.push('-'); } - m.push({ - text: _('export') - ,handler: this.exportPolicy - }); - if (p.indexOf('premove') != -1) { - if (m.length > 0) m.push('-'); - m.push({ - text: _('delete') - ,handler: this.confirm.createDelegate(this,["Security/Access/Policy/Remove","policy_remove_confirm"]) - }); - } - } - - if (m.length > 0) { - this.addContextMenuItem(m); - } - } - - ,removeSelected: function() { - var cs = this.getSelectedAsList(); - if (cs === false) return false; - - MODx.msg.confirm({ - title: _('selected_remove') - ,text: _('policy_remove_multiple_confirm') - ,url: this.config.url - ,params: { - action: 'Security/Access/Policy/RemoveMultiple' - ,policies: cs - } - ,listeners: { - 'success': {fn:function(r) { - this.getSelectionModel().clearSelections(true); - this.refresh(); - },scope:this} - } - }); - return true; - } }); -Ext.reg('modx-grid-access-policy',MODx.grid.AccessPolicy); +Ext.reg('modx-grid-access-policy', MODx.grid.AccessPolicy); /** * Generates a window for creating Access Policies. @@ -259,65 +299,60 @@ Ext.reg('modx-grid-access-policy',MODx.grid.AccessPolicy); * @xtype modx-window-access-policy-create */ MODx.window.CreateAccessPolicy = function(config = {}) { - this.ident = config.ident || 'cacp'+Ext.id(); - Ext.applyIf(config,{ - title: _('create') - ,url: MODx.config.connector_url - ,action: 'Security/Access/Policy/Create' - ,fields: [{ - fieldLabel: _('name') - ,description: MODx.expandHelp ? '' : _('policy_desc_name') - ,name: 'name' - ,id: 'modx-'+this.ident+'-name' - ,xtype: 'textfield' - ,allowBlank: false - ,anchor: '100%' - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-'+this.ident+'-name' - ,html: _('policy_desc_name') - ,cls: 'desc-under' - },{ - fieldLabel: _('policy_template') - ,description: MODx.expandHelp ? '' : _('policy_desc_template') - ,name: 'template' - ,hiddenName: 'template' - ,id: 'modx-'+this.ident+'-template' - ,xtype: 'modx-combo-access-policy-template' - ,anchor: '100%' - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-'+this.ident+'-template' - ,html: _('policy_desc_template') - ,cls: 'desc-under' - },{ - fieldLabel: _('description') - ,description: MODx.expandHelp ? '' : _('policy_desc_description') - ,name: 'description' - ,id: 'modx-'+this.ident+'-description' - ,xtype: 'textarea' - ,anchor: '100%' - ,height: 50 - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-'+this.ident+'-description' - ,html: _('policy_desc_description') - ,cls: 'desc-under' - },{ - name: 'class' - ,id: 'modx-'+this.ident+'-class' - ,xtype: 'hidden' - },{ - name: 'id' - ,id: 'modx-'+this.ident+'-id' - ,xtype: 'hidden' - }] - ,keys: [] + this.ident = config.ident || `window--create-policy-${Ext.id()}`; + Ext.applyIf(config, { + title: _('create'), + url: MODx.config.connector_url, + action: 'Security/Access/Policy/Create', + fields: [{ + fieldLabel: _('name'), + description: MODx.expandHelp ? '' : _('policy_desc_name'), + name: 'name', + xtype: 'textfield', + allowBlank: false, + anchor: '100%' + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('policy_desc_name'), + cls: 'desc-under' + }, { + fieldLabel: _('policy_template'), + description: MODx.expandHelp ? '' : _('policy_desc_template'), + name: 'template', + hiddenName: 'template', + xtype: 'modx-combo-access-policy-template', + anchor: '100%' + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('policy_desc_template'), + cls: 'desc-under' + }, { + fieldLabel: _('description'), + description: MODx.expandHelp ? '' : _('policy_desc_description'), + name: 'description', + xtype: 'textarea', + anchor: '100%', + height: 50 + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('policy_desc_description'), + cls: 'desc-under' + }, { + name: 'class', + xtype: 'hidden' + }, { + name: 'id', + xtype: 'hidden' + }], + keys: [] }); - MODx.window.CreateAccessPolicy.superclass.constructor.call(this,config); + MODx.window.CreateAccessPolicy.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.CreateAccessPolicy,MODx.Window); -Ext.reg('modx-window-access-policy-create',MODx.window.CreateAccessPolicy); +Ext.extend(MODx.window.CreateAccessPolicy, MODx.Window); +Ext.reg('modx-window-access-policy-create', MODx.window.CreateAccessPolicy); /** * @class MODx.window.AccessPolicyTemplate @@ -326,26 +361,37 @@ Ext.reg('modx-window-access-policy-create',MODx.window.CreateAccessPolicy); * @xtype modx-combo-access-policy-template */ MODx.combo.AccessPolicyTemplate = function(config = {}) { - Ext.applyIf(config,{ - name: 'template' - ,hiddenName: 'template' - ,fields: ['id','name','description','description_trans'] - ,forceSelection: true - ,typeAhead: false - ,editable: false - ,allowBlank: false - ,pageSize: 20 - ,url: MODx.config.connector_url - ,baseParams: { + Ext.applyIf(config, { + name: 'template', + hiddenName: 'template', + fields: [ + 'id', + 'name', + 'description', + 'description_trans' + ], + forceSelection: true, + typeAhead: false, + editable: false, + allowBlank: false, + pageSize: 20, + url: MODx.config.connector_url, + baseParams: { action: 'Security/Access/Policy/Template/GetList' - } - ,tpl: new Ext.XTemplate('
    {name:htmlEncode}' - ,'

    {description_trans:htmlEncode}

    ') + }, + tpl: new Ext.XTemplate(` + +
    + {name:htmlEncode} +

    {description_trans:htmlEncode}

    +
    +
    + `) }); - MODx.combo.AccessPolicyTemplate.superclass.constructor.call(this,config); + MODx.combo.AccessPolicyTemplate.superclass.constructor.call(this, config); }; -Ext.extend(MODx.combo.AccessPolicyTemplate,MODx.combo.ComboBox); -Ext.reg('modx-combo-access-policy-template',MODx.combo.AccessPolicyTemplate); +Ext.extend(MODx.combo.AccessPolicyTemplate, MODx.combo.ComboBox); +Ext.reg('modx-combo-access-policy-template', MODx.combo.AccessPolicyTemplate); /** * @class MODx.window.ImportPolicy @@ -354,29 +400,27 @@ Ext.reg('modx-combo-access-policy-template',MODx.combo.AccessPolicyTemplate); * @xtype modx-window-policy-import */ MODx.window.ImportPolicy = function(config = {}) { - this.ident = config.ident || 'imppol-'+Ext.id(); - Ext.applyIf(config,{ - title: _('import') - ,id: 'modx-window-policy-import' - ,url: MODx.config.connector_url - ,action: 'Security/Access/Policy/Import' - ,fileUpload: true - ,saveBtnText: _('import') - ,fields: [{ - html: _('policy_import_msg') - ,id: this.ident+'-desc' - ,xtype: 'modx-description' - ,style: 'margin-bottom: 10px;' - },{ - xtype: 'fileuploadfield' - ,fieldLabel: _('file') - ,buttonText: _('upload.buttons.upload') - ,name: 'file' - ,id: this.ident+'-file' - ,anchor: '100%' + this.ident = config.ident || `window--import-policy-${Ext.id()}`; + Ext.applyIf(config, { + title: _('import'), + id: 'modx-window-policy-import', + url: MODx.config.connector_url, + action: 'Security/Access/Policy/Import', + fileUpload: true, + saveBtnText: _('import'), + fields: [{ + html: _('policy_import_msg'), + xtype: 'modx-description', + style: 'margin-bottom: 10px;' + }, { + xtype: 'fileuploadfield', + fieldLabel: _('file'), + buttonText: _('upload.buttons.upload'), + name: 'file', + anchor: '100%' }] }); - MODx.window.ImportPolicy.superclass.constructor.call(this,config); + MODx.window.ImportPolicy.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.ImportPolicy,MODx.Window); -Ext.reg('modx-window-policy-import',MODx.window.ImportPolicy); +Ext.extend(MODx.window.ImportPolicy, MODx.Window); +Ext.reg('modx-window-policy-import', MODx.window.ImportPolicy); diff --git a/manager/assets/modext/widgets/security/modx.grid.access.policy.template.js b/manager/assets/modext/widgets/security/modx.grid.access.policy.template.js index 8fee8c4f595..fa5ac267113 100644 --- a/manager/assets/modext/widgets/security/modx.grid.access.policy.template.js +++ b/manager/assets/modext/widgets/security/modx.grid.access.policy.template.js @@ -7,30 +7,30 @@ * @xtype modx-panel-access-policy-templates */ MODx.panel.AccessPolicyTemplates = function(config = {}) { - Ext.applyIf(config,{ - id: 'modx-panel-access-policy-templates' - ,bodyStyle: '' - ,defaults: { collapsible: false ,autoHeight: true } - ,items: [{ - html: _('policies') - ,id: 'modx-policy-templates-header' - ,xtype: 'modx-header' - },{ - layout: 'form' - ,bodyStyle: 'padding: 15px' - ,items: [{ - html: '

    '+_('policy_templates.intro_msg')+'

    ' - ,border: false - },{ - xtype: 'modx-grid-access-policy-templates' - ,preventRender: true + Ext.applyIf(config, { + id: 'modx-panel-access-policy-templates', + bodyStyle: '', + defaults: { collapsible: false, autoHeight: true }, + items: [{ + html: _('policies'), + id: 'modx-policy-templates-header', + xtype: 'modx-header' + }, { + layout: 'form', + bodyStyle: 'padding: 15px', + items: [{ + html: `

    ${_('policy_templates.intro_msg')}

    `, + border: false + }, { + xtype: 'modx-grid-access-policy-templates', + preventRender: true }] }] }); - MODx.panel.AccessPolicyTemplates.superclass.constructor.call(this,config); + MODx.panel.AccessPolicyTemplates.superclass.constructor.call(this, config); }; -Ext.extend(MODx.panel.AccessPolicyTemplates,MODx.FormPanel); -Ext.reg('modx-panel-access-policy-templates',MODx.panel.AccessPolicyTemplates); +Ext.extend(MODx.panel.AccessPolicyTemplates, MODx.FormPanel); +Ext.reg('modx-panel-access-policy-templates', MODx.panel.AccessPolicyTemplates); /** * Loads a grid of modAccessPolicyTemplates. @@ -43,13 +43,13 @@ Ext.reg('modx-panel-access-policy-templates',MODx.panel.AccessPolicyTemplates); MODx.grid.AccessPolicyTemplate = function(config = {}) { const queryValue = this.applyRequestFilter(3, 'query', 'tab', true); this.sm = new Ext.grid.CheckboxSelectionModel(); - Ext.applyIf(config,{ - id: 'modx-grid-access-policy-template' - ,url: MODx.config.connector_url - ,baseParams: { + Ext.applyIf(config, { + id: 'modx-grid-access-policy-template', + url: MODx.config.connector_url, + baseParams: { action: 'Security/Access/Policy/Template/GetList' - } - ,fields: [ + }, + fields: [ 'id', 'name', 'description', @@ -58,214 +58,337 @@ MODx.grid.AccessPolicyTemplate = function(config = {}) { 'template_group_name', 'total_permissions', 'policy_count', - 'cls' - ] - ,paging: true - ,autosave: true - ,save_action: 'Security/Access/Policy/Template/UpdateFromGrid' - ,remoteSort: true - ,sm: this.sm - ,columns: [this.sm,{ - header: _('name') - ,dataIndex: 'name' - ,width: 200 - ,editor: { xtype: 'textfield' ,allowBlank: false } - ,sortable: true - ,renderer: { fn: function(v,md,record) { - return this.renderLink(v, { - href: '?a=security/access/policy/template/update&id=' + record.data.id - }); - }, scope: this } - },{ - header: _('description') - ,dataIndex: 'description' - ,width: 375 - ,editable: false - ,renderer: function(value, metaData, record) { - return Ext.util.Format.htmlEncode(record['data']['description_trans']); + 'creator' + ], + paging: true, + autosave: true, + save_action: 'Security/Access/Policy/Template/UpdateFromGrid', + remoteSort: true, + sm: this.sm, + columns: [this.sm, { + header: _('name'), + dataIndex: 'name', + width: 200, + editor: { + xtype: 'textfield', + allowBlank: false + }, + sortable: true, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record, [record.json.isProtected]); + return this.userCanEditRecord(record) + ? this.renderLink(value, { + href: `?a=security/access/policy/template/update&id=${record.data.id}`, + title: _('policy_template_edit') + }) + : value + ; + }, + scope: this } - ,sortable: true - },{ - header: _('template_group') - ,dataIndex: 'template_group_name' - ,width: 375 - ,sortable: true - },{ - header: _('policy_count') - ,dataIndex: 'policy_count' - ,width: 100 - ,editable: false - ,sortable: true - },{ - header: _('permissions') - ,dataIndex: 'total_permissions' - ,width: 100 - ,editable: false - ,sortable: true - }] - ,tbar: [ + }, { + header: _('description'), + dataIndex: 'description', + width: 375, + editor: { + xtype: 'textarea' + }, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record, [record.json.isProtected]); + return record.json.description_trans || value; + }, + scope: this + } + }, { + header: _('template_group'), + dataIndex: 'template_group_name', + width: 375, + sortable: true + }, { + header: _('policy_count'), + dataIndex: 'policy_count', + width: 100, + editable: false, + sortable: true + }, { + header: _('permissions'), + dataIndex: 'total_permissions', + width: 100, + editable: false, + sortable: true + }, + this.getCreatorColumnConfig('policy-template') + ], + tbar: [ + this.getCreateButton('policy_template', 'createPolicyTemplate'), { - text: _('create') - ,cls:'primary-button' - ,scope: this - ,handler: this.createPolicyTemplate - },{ - text: _('import') - ,scope: this - ,handler: this.importPolicyTemplate - },{ - text: _('bulk_actions') - ,menu: [{ - text: _('selected_remove') - ,handler: this.removeSelected - ,scope: this - }] + text: _('import'), + scope: this, + handler: this.importPolicyTemplate, + listeners: { + render: { + fn: function(btn) { + if (!this.userCanCreate) { + btn.hide(); + } + }, + scope: this + } + } + }, { + /* + * Note: Using local this.removeSelected method instead of shared base this.getBulkActionsButton() method here, + * as additional validation processing is needed for removal of Policy Templates + */ + text: _('bulk_actions'), + menu: [{ + text: _('selected_remove'), + itemId: 'modx-bulk-menu-opt-remove', + handler: this.removeSelected, + scope: this + }], + listeners: { + render: { + fn: function(btn) { + if (!this.userCanDelete) { + btn.hide(); + } + }, + scope: this + }, + click: { + fn: function(btn) { + const + removableItems = this.getRemovableItemsFromSelection('int'), + menuOptRemove = btn.menu.getComponent('modx-bulk-menu-opt-remove') + ; + if (removableItems.length === 0) { + menuOptRemove.disable(); + } else { + menuOptRemove.enable(); + } + }, + scope: this + } + } }, '->', this.getQueryFilterField(`filter-query-policy-template:${queryValue}`), this.getClearFiltersButton('filter-query-policy-template') - ] + ], + viewConfig: this.getViewConfig() + }); + MODx.grid.AccessPolicyTemplate.superclass.constructor.call(this, config); + + this.gridMenuActions = ['edit', 'delete', 'duplicate', 'export']; + + this.setUserCanEdit(['policy_template_save', 'policy_template_edit']); + this.setUserCanCreate(['policy_template_save', 'policy_template_new']); + this.setUserCanDelete(['policy_template_delete']); + this.setShowActionsMenu(); + + this.on({ + beforeedit: function(e) { + if (!this.userCanEdit || e.record.json.isProtected || !this.userCanEditRecord(e.record)) { + return false; + } + }, + afteredit: function(e) { + this.refresh(); + } }); - MODx.grid.AccessPolicyTemplate.superclass.constructor.call(this,config); }; -Ext.extend(MODx.grid.AccessPolicyTemplate,MODx.grid.Grid,{ +Ext.extend(MODx.grid.AccessPolicyTemplate, MODx.grid.Grid, { getMenu: function() { - var r = this.getSelectionModel().getSelected(); - var p = r.data.cls; - - var m = []; + const + model = this.getSelectionModel(), + record = model.getSelected(), + menu = [] + ; - if (this.getSelectionModel().getCount() > 1) { - m.push({ - text: _('selected_remove') - ,handler: this.removeSelected - }); + if (model.getCount() > 1) { + const records = model.getSelections(); + if (this.userCanDelete && this.userCanDeleteRecords(records)) { + menu.push({ + text: _('selected_remove'), + handler: this.removeSelected + }); + } } else { - if (p.indexOf('pedit') !== -1) { - m.push({ - text: _('edit') - ,handler: this.editPolicyTemplate + if (this.userCanEdit && this.userCanEditRecord(record)) { + menu.push({ + text: _('edit'), + handler: this.editPolicyTemplate }); - m.push({ - text: _('duplicate') - ,handler: this.confirm.createDelegate(this,["Security/Access/Policy/Template/Duplicate","policy_template_duplicate_confirm"]) + } + if (this.userCanCreate && this.userCanDuplicateRecord(record)) { + menu.push({ + text: _('duplicate'), + handler: this.confirm.createDelegate( + this, + [ + 'Security/Access/Policy/Template/Duplicate', + 'policy_template_duplicate_confirm' + ] + ) }); } - if (m.length > 0) { m.push('-'); } - m.push({ - text: _('export') - ,handler: this.exportPolicyTemplate + if (menu.length > 0) { + menu.push('-'); + } + menu.push({ + text: _('export'), + handler: this.exportPolicyTemplate }); - - if (p.indexOf('premove') !== -1) { - if (m.length > 0) m.push('-'); - m.push({ + if (this.userCanDelete && this.userCanDeleteRecord(record)) { + if (menu.length > 0) { + menu.push('-'); + } + /* + * Note: Using local this.removePolicyTemplate method instead of shared base this.remove() method here, + * as additional validation processing is needed for removal of Policy Templates + */ + menu.push({ text: _('delete'), handler: this.removePolicyTemplate }); } } + return menu; + }, - if (m.length > 0) { - this.addContextMenuItem(m); - } - } - - ,createPolicyTemplate: function(btn,e) { - var r = this.menu.record; - if (!this.windows.aptc) { - this.windows.aptc = MODx.load({ - xtype: 'modx-window-access-policy-template-create' - ,record: r - ,plugin: this.config.plugin - ,listeners: { - 'success': {fn:function(r) { - this.refresh(); - },scope:this} + createPolicyTemplate: function(btn, e) { + const { record } = this.menu; + if (!this.windows.create_policy_template) { + this.windows.create_policy_template = MODx.load({ + xtype: 'modx-window-access-policy-template-create', + record: record, + plugin: this.config.plugin, + listeners: { + success: { + fn: function(response) { + this.refresh(); + }, + scope: this + } } }); } - this.windows.aptc.reset(); - this.windows.aptc.show(e.target); - } + this.windows.create_policy_template.reset(); + this.windows.create_policy_template.show(e.target); + }, - ,importPolicyTemplate: function(btn,e) { - var r = {}; + importPolicyTemplate: function(btn, e) { + const record = {}; if (!this.windows.importPolicyTemplate) { this.windows.importPolicyTemplate = MODx.load({ - xtype: 'modx-window-policy-template-import' - ,record: r - ,listeners: { - 'success': {fn:function(o) { - this.refresh(); - },scope:this} + xtype: 'modx-window-policy-template-import', + record: record, + listeners: { + success: { + fn: function(response) { + this.refresh(); + }, + scope: this + } } }); } this.windows.importPolicyTemplate.reset(); - this.windows.importPolicyTemplate.setValues(r); + this.windows.importPolicyTemplate.setValues(record); this.windows.importPolicyTemplate.show(e.target); - } + }, - ,exportPolicyTemplate: function(btn,e) { - var id = this.menu.record.id; + exportPolicyTemplate: function(btn, e) { + const { id } = this.menu.record; MODx.Ajax.request({ - url: this.config.url - ,params: { - action: 'Security/Access/Policy/Template/Export' - ,id: id - } - ,listeners: { - 'success': {fn:function(r) { - location.href = this.config.url+'?action=Security/Access/Policy/Template/Export&download=1&id='+id+'&HTTP_MODAUTH='+MODx.siteId; - },scope:this} + url: this.config.url, + params: { + action: 'Security/Access/Policy/Template/Export', + id: id + }, + listeners: { + success: { + fn: function(r) { + window.location.href = `${this.config.url}?action=Security/Access/Policy/Template/Export&download=1&id=${id}&HTTP_MODAUTH=${MODx.siteId}`; + }, + scope: this + } } }); - } + }, - ,editPolicyTemplate: function(itm,e) { - MODx.loadPage('security/access/policy/template/update', 'id='+this.menu.record.id); - } + editPolicyTemplate: function(itm, e) { + MODx.loadPage('security/access/policy/template/update', `id=${this.menu.record.id}`); + }, - ,removeSelected: function() { - var cs = this.getSelectedAsList(); - if (cs === false) return false; - - var store = this.getStore(); - var policiesCount = 0; - cs.split(',').forEach(function(item){ + removeSelected: function() { + const selectedTemplates = this.getSelectedAsList(); + if (selectedTemplates === false) { + return false; + } + const + store = this.getStore(), + selectedTemplatesArr = selectedTemplates.split(','), + totalSelected = selectedTemplatesArr.length + ; + let + policiesCount = 0, + selectionsProtected = 0, + confirmationMessage + ; + selectedTemplatesArr.forEach(item => { const record = store.getById(item); - if (record) { - policiesCount += parseInt(record.data.policy_count); + if (!record.json.isProtected) { + policiesCount += parseInt(record.data.policy_count, 10); + } else { + selectionsProtected++; + } } - - }) - + }); + if (policiesCount) { + confirmationMessage = selectionsProtected > 0 + ? _('policy_template_remove_multiple_confirm_in_use_ignoring_protected', { 'count-policies': policiesCount, protected: selectionsProtected, 'count-templates': totalSelected }) + : _('policy_template_remove_multiple_confirm_in_use', { count: policiesCount, total: totalSelected }) + ; + } else { + confirmationMessage = _('policy_template_remove_multiple_confirm'); + } MODx.msg.confirm({ - title: _('selected_remove') - ,text: policiesCount ? _('policy_template_remove_multiple_confirm_in_use', {count: policiesCount}) : _('policy_template_remove_multiple_confirm') - ,url: this.config.url - ,params: { - action: 'Security/Access/Policy/Template/RemoveMultiple' - ,templates: cs - } - ,listeners: { - 'success': {fn:function(r) { - this.getSelectionModel().clearSelections(true); - this.refresh(); - },scope:this} + title: _('selected_remove'), + text: confirmationMessage, + url: this.config.url, + params: { + action: 'Security/Access/Policy/Template/RemoveMultiple', + templates: selectedTemplates + }, + listeners: { + success: { + fn: function(response) { + this.getSelectionModel().clearSelections(true); + this.refresh(); + }, + scope: this + } } }); return true; - } - - ,removePolicyTemplate: function() { - if (!this.menu.record) return; + }, + removePolicyTemplate: function() { + if (!this.menu.record) { + return; + } MODx.msg.confirm({ title: _('warning'), - text: parseInt(this.menu.record.policy_count) ? _('policy_template_remove_confirm_in_use', {count: this.menu.record.policy_count}) : _('policy_template_remove_confirm'), + text: parseInt(this.menu.record.policy_count, 10) + ? _('policy_template_remove_confirm_in_use', { count: this.menu.record.policy_count }) + : _('policy_template_remove_confirm'), url: this.config.url, params: { action: 'Security/Access/Policy/Template/Remove', @@ -274,13 +397,13 @@ Ext.extend(MODx.grid.AccessPolicyTemplate,MODx.grid.Grid,{ listeners: { success: { fn: this.refresh, - scope:this + scope: this } } }); } }); -Ext.reg('modx-grid-access-policy-templates',MODx.grid.AccessPolicyTemplate); +Ext.reg('modx-grid-access-policy-templates', MODx.grid.AccessPolicyTemplate); /** * Generates a window for creating Access Policies. @@ -291,53 +414,50 @@ Ext.reg('modx-grid-access-policy-templates',MODx.grid.AccessPolicyTemplate); * @xtype modx-window-access-policy-create */ MODx.window.CreateAccessPolicyTemplate = function(config = {}) { - this.ident = config.ident || 'cacpt'+Ext.id(); - Ext.applyIf(config,{ - title: _('create') - ,url: MODx.config.connector_url - ,action: 'Security/Access/Policy/Template/Create' - ,fields: [{ - fieldLabel: _('name') - ,name: 'name' - ,id: 'modx-'+this.ident+'-name' - ,xtype: 'textfield' - ,anchor: '100%' - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-'+this.ident+'-name' - ,html: _('policy_template_desc_name') - ,cls: 'desc-under' - },{ - fieldLabel: _('template_group') - ,name: 'template_group' - ,id: 'modx-'+this.ident+'-template-group' - ,xtype: 'modx-combo-access-policy-template-group' - ,anchor: '100%' - ,value: 1 - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-'+this.ident+'-template-group' - ,html: _('policy_template_desc_template_group') - ,cls: 'desc-under' - },{ - fieldLabel: _('description') - ,name: 'description' - ,id: 'modx-'+this.ident+'-description' - ,xtype: 'textarea' - ,anchor: '100%' - ,height: 50 - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-'+this.ident+'-description' - ,html: _('policy_template_desc_description') - ,cls: 'desc-under' - }] - ,keys: [] + this.ident = config.ident || `window-import-policy-template-${Ext.id()}`; + Ext.applyIf(config, { + title: _('create'), + url: MODx.config.connector_url, + action: 'Security/Access/Policy/Template/Create', + fields: [{ + fieldLabel: _('name'), + name: 'name', + xtype: 'textfield', + anchor: '100%' + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('policy_template_desc_name'), + cls: 'desc-under' + }, { + fieldLabel: _('template_group'), + name: 'template_group', + xtype: 'modx-combo-access-policy-template-group', + anchor: '100%', + value: 1 + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('policy_template_desc_template_group'), + cls: 'desc-under' + }, { + fieldLabel: _('description'), + name: 'description', + xtype: 'textarea', + anchor: '100%', + height: 50 + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('policy_template_desc_description'), + cls: 'desc-under' + }], + keys: [] }); - MODx.window.CreateAccessPolicyTemplate.superclass.constructor.call(this,config); + MODx.window.CreateAccessPolicyTemplate.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.CreateAccessPolicyTemplate,MODx.Window); -Ext.reg('modx-window-access-policy-template-create',MODx.window.CreateAccessPolicyTemplate); +Ext.extend(MODx.window.CreateAccessPolicyTemplate, MODx.Window); +Ext.reg('modx-window-access-policy-template-create', MODx.window.CreateAccessPolicyTemplate); /** * @class MODx.window.ImportPolicyTemplate @@ -346,29 +466,27 @@ Ext.reg('modx-window-access-policy-template-create',MODx.window.CreateAccessPoli * @xtype modx-window-policy-template-import */ MODx.window.ImportPolicyTemplate = function(config = {}) { - this.ident = config.ident || 'imppt-'+Ext.id(); - Ext.applyIf(config,{ - title: _('import') - ,id: 'modx-window-policy-template-import' - ,url: MODx.config.connector_url - ,action: 'Security/Access/Policy/Template/Import' - ,fileUpload: true - ,saveBtnText: _('import') - ,fields: [{ - html: _('policy_template_import_msg') - ,id: this.ident+'-desc' - ,xtype: 'modx-description' - ,style: 'margin-bottom: 10px;' - },{ - xtype: 'fileuploadfield' - ,fieldLabel: _('file') - ,buttonText: _('upload.buttons.upload') - ,name: 'file' - ,id: this.ident+'-file' - ,anchor: '100%' + this.ident = config.ident || `window-import-policy-template-${Ext.id()}`; + Ext.applyIf(config, { + title: _('import'), + id: 'modx-window-policy-template-import', + url: MODx.config.connector_url, + action: 'Security/Access/Policy/Template/Import', + fileUpload: true, + saveBtnText: _('import'), + fields: [{ + html: _('policy_template_import_msg'), + xtype: 'modx-description', + style: 'margin-bottom: 10px;' + }, { + xtype: 'fileuploadfield', + fieldLabel: _('file'), + buttonText: _('upload.buttons.upload'), + name: 'file', + anchor: '100%' }] }); - MODx.window.ImportPolicyTemplate.superclass.constructor.call(this,config); + MODx.window.ImportPolicyTemplate.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.ImportPolicyTemplate,MODx.Window); -Ext.reg('modx-window-policy-template-import',MODx.window.ImportPolicyTemplate); +Ext.extend(MODx.window.ImportPolicyTemplate, MODx.Window); +Ext.reg('modx-window-policy-template-import', MODx.window.ImportPolicyTemplate); diff --git a/manager/assets/modext/widgets/security/modx.grid.role.js b/manager/assets/modext/widgets/security/modx.grid.role.js index dd31b8344ee..e4d229699c8 100644 --- a/manager/assets/modext/widgets/security/modx.grid.role.js +++ b/manager/assets/modext/widgets/security/modx.grid.role.js @@ -20,7 +20,7 @@ MODx.grid.Role = function(config = {}) { 'name', 'description', 'authority', - 'perm' + 'creator' ], paging: true, autosave: true, @@ -36,11 +36,27 @@ MODx.grid.Role = function(config = {}) { width: 150, sortable: true, editor: { - xtype: 'textfield' + xtype: 'textfield', + allowBlank: false, + blankText: _('role_err_ns_name'), + validationEvent: 'change', + validator: function(value) { + const + grid = Ext.getCmp('modx-grid-role'), + reserved = this.gridEditor.record.json.reserved.name + ; + if (grid.valueIsReserved(reserved, value)) { + const msg = _('role_err_name_reserved', { reservedName: value }); + Ext.Msg.alert(_('error'), msg); + return false; + } + return true; + } }, renderer: { fn: function(value, metaData, record, rowIndex, colIndex, store) { - metaData.css = this.setEditableCellClasses(record); + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record, [record.json.isProtected]); return Ext.util.Format.htmlEncode(value); }, scope: this @@ -49,18 +65,24 @@ MODx.grid.Role = function(config = {}) { header: _('description'), dataIndex: 'description', width: 350, - editor: { xtype: 'textarea' }, + editor: { + xtype: 'textarea' + }, renderer: { fn: function(value, metaData, record, rowIndex, colIndex, store) { - metaData.css = this.setEditableCellClasses(record); + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record, [record.json.isProtected]); return Ext.util.Format.htmlEncode(value); }, scope: this } - }, { + }, + this.getCreatorColumnConfig('role'), + { header: _('authority'), dataIndex: 'authority', width: 60, + align: 'center', sortable: true, editor: { xtype: 'numberfield', @@ -72,7 +94,8 @@ MODx.grid.Role = function(config = {}) { }, renderer: { fn: function(value, metaData, record, rowIndex, colIndex, store) { - metaData.css = this.setEditableCellClasses(record, [record.json.isAssigned]); + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record, [record.json.isAssigned, record.json.isProtected], '', false); return value; }, scope: this @@ -84,7 +107,7 @@ MODx.grid.Role = function(config = {}) { selectedRecord = grid.getSelectionModel().getSelected(), roleIsAssigned = selectedRecord.json.isAssigned === 1 ; - if (roleIsAssigned) { + if (!selectedRecord.json.isProtected && roleIsAssigned) { Ext.Msg.show({ title: _('warning'), msg: _('role_warn_authority_locked'), @@ -98,24 +121,34 @@ MODx.grid.Role = function(config = {}) { } } }], - tbar: [{ - text: _('create'), - cls: 'primary-button', - handler: this.createRole, - scope: this - }] + tbar: [this.getCreateButton('role', 'createRole')], + viewConfig: this.getViewConfig(false, false) }); MODx.grid.Role.superclass.constructor.call(this, config); - this.on('beforeedit', this.checkCellIsEditable, this); + + this.gridMenuActions = ['delete']; + + this.setUserCanEdit(['save_role', 'edit_role']); + this.setUserCanCreate(['save_role', 'new_role']); + this.setUserCanDelete(['delete_role']); + this.setShowActionsMenu(); + + this.on({ + beforeedit: function(e) { + if (!this.userCanEdit || e.record.json.isProtected || (e.field === 'authority' && e.record.json.isAssigned)) { + return false; + } + } + }); }; Ext.extend(MODx.grid.Role, MODx.grid.Grid, { + getMenu: function() { const record = this.getSelectionModel().getSelected(), - permissions = record.data.perm || '', menu = [] ; - if (permissions.indexOf('remove') !== -1) { + if (this.userCanDeleteRecord(record)) { menu.push({ text: _('delete'), handler: this.remove.createDelegate(this, ['role_remove_confirm', 'Security/Role/Remove']) @@ -137,6 +170,7 @@ Ext.extend(MODx.grid.Role, MODx.grid.Grid, { } }); } + }); Ext.reg('modx-grid-role', MODx.grid.Role); @@ -161,17 +195,20 @@ MODx.window.CreateRole = function(config = {}) { fieldLabel: _('name'), xtype: 'textfield' }, { - xtype: MODx.expandHelp ? 'box' : 'hidden', + xtype: 'box', + hidden: !MODx.expandHelp, html: _('role_desc_name'), cls: 'desc-under' }, { name: 'authority', fieldLabel: _('authority'), - xtype: 'textfield', + xtype: 'numberfield', allowNegative: false, - value: 0 + value: 0, + maxValue: 9999 }, { - xtype: MODx.expandHelp ? 'box' : 'hidden', + xtype: 'box', + hidden: !MODx.expandHelp, html: _('role_desc_authority'), cls: 'desc-under' }, { @@ -181,7 +218,8 @@ MODx.window.CreateRole = function(config = {}) { allowBlank: true, grow: true }, { - xtype: MODx.expandHelp ? 'box' : 'hidden', + xtype: 'box', + hidden: !MODx.expandHelp, html: _('role_desc_description'), cls: 'desc-under' }], diff --git a/manager/assets/modext/widgets/security/modx.grid.user.group.base.js b/manager/assets/modext/widgets/security/modx.grid.user.group.base.js index 1a025ae3678..ef78bf52cb1 100644 --- a/manager/assets/modext/widgets/security/modx.grid.user.group.base.js +++ b/manager/assets/modext/widgets/security/modx.grid.user.group.base.js @@ -55,6 +55,14 @@ MODx.grid.UserGroupBase = function UserGroupBase(config = {}) { MODx.grid.UserGroupBase.superclass.constructor.call(this, config); + this.gridMenuActions = ['edit', 'delete']; + + this.setUserCanEdit(['usergroup_edit', 'usergroup_save']); + this.userCanEditAcls = this.userCanEdit; + this.setUserCanCreate(['usergroup_create', 'usergroup_save']); + this.setUserCanDelete(['usergroup_delete']); + this.setShowActionsMenu(); + this.addEvents('createAcl', 'updateAcl'); this.on({ @@ -80,7 +88,9 @@ Ext.extend(MODx.grid.UserGroupBase, MODx.grid.Grid, { tpl: new Ext.XTemplate( `
      - {[ values.permissions.split(',').map(item => '
    • ' + item.trim() + '
    • ').join('') ]} + +
    • {.}
    • +
    ` ), @@ -90,33 +100,23 @@ Ext.extend(MODx.grid.UserGroupBase, MODx.grid.Grid, { return [this.rowExpander, ...columns]; }, getMenu: function() { - const record = this.getSelectionModel().getSelected(), - permissions = record.data.cls, - menu = [] - ; + const menu = []; if (this.getSelectionModel().getCount() > 1) { // Currently not allowing bulk actions for this grid - } else { - if (permissions.indexOf('pedit') !== -1) { - menu.push({ - text: _(`access_${this.aclType}_update`), - handler: this.updateAcl - }); - } - if (permissions.indexOf('premove') !== -1) { - if (menu.length > 0) { - menu.push('-'); - } - menu.push({ - text: _(`access_${this.aclType}_remove`), - handler: this.remove.createDelegate(this, ['confirm_remove', ACL_TYPES_CONFIG[this.aclType].actions.remove]) - }); + } else if (this.userCanEditAcls) { + menu.push({ + text: _(`access_${this.aclType}_update`), + handler: this.updateAcl + }); + if (menu.length > 0) { + menu.push('-'); } + menu.push({ + text: _(`access_${this.aclType}_remove`), + handler: this.remove.createDelegate(this, ['confirm_remove', ACL_TYPES_CONFIG[this.aclType].actions.remove]) + }); } - - if (menu.length > 0) { - this.addContextMenuItem(menu); - } + return menu; }, /** @@ -371,7 +371,7 @@ Ext.extend(MODx.window.UserGroupAclBase, MODx.Window, { */ getPermissionsList: function(window, record = {}) { const - permissions = record?.data?.permissions || window.record.permissions, + permissions = record?.json?.policyPermissions || window.record.policyPermissions, permissionsListContainer = window.fp?.getComponent(`${this.idPrefix}-permissions`), permissionsListCmp = permissionsListContainer?.getComponent(`${this.idPrefix}-permissions-list`), permissionsListLabelCmp = permissionsListContainer?.getComponent(`${this.idPrefix}-permissions-list-label`) diff --git a/manager/assets/modext/widgets/security/modx.grid.user.group.category.js b/manager/assets/modext/widgets/security/modx.grid.user.group.category.js index 189576c9d87..733263cd95d 100644 --- a/manager/assets/modext/widgets/security/modx.grid.user.group.category.js +++ b/manager/assets/modext/widgets/security/modx.grid.user.group.category.js @@ -29,8 +29,7 @@ MODx.grid.UserGroupCategory = function UserGroupCategory(config = {}) { 'policy', 'policy_name', 'context_key', - 'permissions', - 'cls' + 'policyPermissions' ], columns: this.getColumns([ { diff --git a/manager/assets/modext/widgets/security/modx.grid.user.group.context.js b/manager/assets/modext/widgets/security/modx.grid.user.group.context.js index f977aa85172..5ebd9a811bb 100644 --- a/manager/assets/modext/widgets/security/modx.grid.user.group.context.js +++ b/manager/assets/modext/widgets/security/modx.grid.user.group.context.js @@ -27,8 +27,7 @@ MODx.grid.UserGroupContext = function UserGroupContext(config = {}) { 'role_display', 'policy', 'policy_name', - 'permissions', - 'cls' + 'policyPermissions' ], sortBy: 'target', columns: this.getColumns([ diff --git a/manager/assets/modext/widgets/security/modx.grid.user.group.js b/manager/assets/modext/widgets/security/modx.grid.user.group.js index 26a56481394..8cc52f1a18f 100644 --- a/manager/assets/modext/widgets/security/modx.grid.user.group.js +++ b/manager/assets/modext/widgets/security/modx.grid.user.group.js @@ -6,161 +6,243 @@ * @param {Object} config An object of options. * @xtype modx-grid-user-groups */ -MODx.grid.UserGroups = function(config) { - config = config || {}; +MODx.grid.UserGroups = function(config = {}) { this.exp = new Ext.grid.RowExpander({ - tpl : new Ext.Template( + tpl: new Ext.Template( '

    {user_group_desc}

    ' ) }); - Ext.applyIf(config,{ - title: '' - ,id: 'modx-grid-user-groups' - ,url: MODx.config.connector_url - ,baseParams: { + Ext.applyIf(config, { + title: '', + id: 'modx-grid-user-groups', + /* + url and baseParams are not utilized by the core when this + grid is used (only in User > Access Permissions). Should remove + if this class is not meant to be somehow used externally (via Extra) + */ + url: MODx.config.connector_url, + baseParams: { action: 'Security/Group/GetList' - } - ,fields: ['usergroup','name','member','role','rolename','primary_group','rank','user_group_desc'] - ,cls: 'modx-grid modx-grid-draggable' - ,columns: [this.exp, - { - header: _('user_group') - ,dataIndex: 'name' - ,width: 175 - ,renderer: { fn: function(v,md,record) { - return this.renderLink(v, { - href: '?a=security/usergroup/update&id=' + record.data.usergroup - ,target: '_blank' - }); - }, scope: this } - },{ - header: _('role') - ,dataIndex: 'rolename' - ,width: 175 - ,renderer: { fn: function(v,md,record) { - return this.renderLink(v, { - href: '?a=security/permission' - ,target: '_blank' - }); - }, scope: this } - },{ - header: _('rank') - ,dataIndex: 'rank' - ,width: 80 - ,editor: { xtype: 'numberfield', allowBlank: false, allowNegative: false } - }] - ,plugins: [new Ext.ux.dd.GridDragDropRowOrder({ - copy: false - ,scrollable: true - ,targetCfg: {} - ,listeners: { - 'afterrowmove': {fn:this.onAfterRowMove,scope:this} - ,'beforerowmove': {fn:this.onBeforeRowMove,scope:this} + }, + fields: [ + 'usergroup', + 'name', + 'member', + 'role', + 'rolename', + 'primary_group', + 'rank', + 'user_group_desc' + ], + cls: 'modx-grid modx-grid-draggable', + columns: [ + this.exp, + { + header: _('user_group'), + dataIndex: 'name', + width: 175, + renderer: { + fn: function(value, metaData, record) { + return this.userCanEditGroups + ? this.renderLink(value, { + href: `?a=security/usergroup/update&id=${record.data.usergroup}`, + target: '_blank' + }) + : value + ; + }, + scope: this + } + }, { + header: _('role'), + dataIndex: 'rolename', + width: 175, + renderer: { + fn: function(value, metaData, record) { + return this.userCanEditRoles + ? this.renderLink(value, { + href: `?a=security/permission&tab=1&role=${record.data.role}`, + target: '_blank' + }) + : value + ; + }, + scope: this + } + }, { + header: _('rank'), + dataIndex: 'rank', + width: 80, + editor: { + xtype: 'numberfield', + allowBlank: false, + allowNegative: false + } } - }), - this.exp] - ,tbar: [{ - text: _('user_group_user_add') - ,cls:'primary-button' - ,handler: this.addGroup - }] + ], + plugins: [this.exp], + tbar: [ + this.getCreateButton('user_group_user', 'addGroup', 'userCanEditGroupUsers') + ] }); - MODx.grid.UserGroups.superclass.constructor.call(this,config); - this.userRecord = new Ext.data.Record.create(['usergroup','name','member','role','rolename','primary_group']); - this.addEvents('beforeUpdateRole','afterUpdateRole','beforeAddGroup','afterAddGroup','beforeReorderGroup','afterReorderGroup'); + + this.gridMenuActions = ['editGroupUsers']; + this.setUserHasPermissions('editGroups', ['usergroup_edit', 'usergroup_save']); + this.setUserHasPermissions('editGroupUsers', ['usergroup_user_edit']); + this.setUserHasPermissions('editRoles', ['edit_role', 'save_role']); + + if (this.userCanEditGroupUsers) { + config.plugins.push( + new Ext.ux.dd.GridDragDropRowOrder({ + copy: false, + scrollable: true, + targetCfg: {}, + listeners: { + afterrowmove: { + fn: this.onAfterRowMove, + scope: this + }, + /** + * @deprecated In 3.1, appears to be unused + */ + beforerowmove: { + fn: this.onBeforeRowMove, + scope: this + } + } + }) + ); + } + + MODx.grid.UserGroups.superclass.constructor.call(this, config); + + this.userRecord = new Ext.data.Record.create([ + 'usergroup', + 'name', + 'member', + 'role', + 'rolename', + 'primary_group' + ]); + this.addEvents( + 'beforeUpdateRole', + 'afterUpdateRole', + 'beforeAddGroup', + 'afterAddGroup', + 'beforeReorderGroup', + 'afterReorderGroup' + ); + + this.setShowActionsMenu(); }; -Ext.extend(MODx.grid.UserGroups,MODx.grid.LocalGrid,{ - _showMenu: function(g,ri,e) { - e.stopEvent(); - e.preventDefault(); - var m = this.menu; - m.recordIndex = ri; - m.record = this.getStore().getAt(ri).data; - if (!this.getSelectionModel().isSelected(ri)) { - this.getSelectionModel().selectRow(ri); +Ext.extend(MODx.grid.UserGroups, MODx.grid.LocalGrid, { + getMenu: function() { + const menu = []; + if (this.userCanEditGroupUsers) { + menu.push({ + text: _('user_role_update'), + handler: this.updateRole, + scope: this + }); + menu.push('-'); + menu.push({ + text: _('user_group_user_remove'), + handler: this.remove.createDelegate(this, [{ + text: _('user_group_user_remove_confirm') + }]), + scope: this + }); } - m.removeAll(); - m.add({ - text: _('user_role_update') - ,handler: this.updateRole - ,scope: this - },'-',{ - text: _('user_group_user_remove') - ,handler: this.remove.createDelegate(this,[{text: _('user_group_user_remove_confirm')}]) - ,scope: this - }); - m.showAt(e.xy); - } + return menu; + }, - ,onBeforeRowMove: function(dt,sri,ri,sels) { - if (!this.fireEvent('beforeReorderGroup',{dt:dt,sri:sri,ri:ri,sels:sels})) { + /** + * @deprecated In 3.1, appears to be unused (including the beforeReorderGroup event) + */ + onBeforeRowMove: function(dropTarget, fromRowIndex, toRowIndex, selections) { + if (!this.fireEvent('beforeReorderGroup', { + dt: dropTarget, + sri: fromRowIndex, + ri: toRowIndex, + sels: selections + })) { return false; } return true; - } + }, - ,onAfterRowMove: function(dt,sri,ri,sels) { - var s = this.getStore(); - var sourceRec = s.getAt(sri); - var belowRec = s.getAt(ri); - var total = s.getTotalCount(); + onAfterRowMove: function(dropTarget, fromRowIndex, toRowIndex, selections) { + const + store = this.getStore(), + firstDraggedRecord = store.getAt(fromRowIndex), + total = store.getTotalCount() + ; + firstDraggedRecord.set('rank', fromRowIndex); + firstDraggedRecord.commit(); - sourceRec.set('rank',sri); - sourceRec.commit(); - - /* get all rows below ri, and up their rank by 1 */ - var brec; - for (var x=(ri-1);x'+_('user_management_msg')+'

    ' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-user' - ,cls:'main-wrapper' - ,preventRender: true + Ext.applyIf(config, { + id: 'modx-panel-users', + cls: 'container', + bodyStyle: '', + defaults: { collapsible: false, autoHeight: true }, + items: [{ + html: _('users'), + id: 'modx-users-header', + xtype: 'modx-header' + }, MODx.getPageStructure([{ + title: _('users'), + layout: 'form', + items: [{ + html: `

    ${_('user_management_msg')}

    `, + xtype: 'modx-description' + }, { + xtype: 'modx-grid-user', + cls: 'main-wrapper', + preventRender: true }] }])] }); - MODx.panel.Users.superclass.constructor.call(this,config); + MODx.panel.Users.superclass.constructor.call(this, config); }; -Ext.extend(MODx.panel.Users,MODx.FormPanel); -Ext.reg('modx-panel-users',MODx.panel.Users); +Ext.extend(MODx.panel.Users, MODx.FormPanel); +Ext.reg('modx-panel-users', MODx.panel.Users); /** * Loads a grid of User. @@ -44,13 +44,13 @@ Ext.reg('modx-panel-users',MODx.panel.Users); */ MODx.grid.User = function(config = {}) { this.sm = new Ext.grid.CheckboxSelectionModel(); - Ext.applyIf(config,{ - url: MODx.config.connector_url - ,baseParams: { - action: 'Security/User/GetList' - ,usergroup: MODx.request.usergroup || null - } - ,fields: [ + Ext.applyIf(config, { + url: MODx.config.connector_url, + baseParams: { + action: 'Security/User/GetList', + usergroup: MODx.request.usergroup || null + }, + fields: [ 'id', 'username', 'fullname', @@ -58,104 +58,134 @@ MODx.grid.User = function(config = {}) { 'gender', 'blocked', 'role', - 'active', - 'cls' - ] - ,paging: true - ,autosave: true - ,save_action: 'Security/User/UpdateFromGrid' - ,autosaveErrorMsg: _('user_err_save') - ,remoteSort: true - ,viewConfig: { - forceFit:true - ,enableRowBody:true - ,scrollOffset: 0 - ,autoFill: true - ,showPreview: true - ,getRowClass : function(rec){ - return rec.data.active ? 'grid-row-active' : 'grid-row-inactive'; + 'active' + ], + paging: true, + autosave: true, + save_action: 'Security/User/UpdateFromGrid', + autosaveErrorMsg: _('user_err_save'), + remoteSort: true, + viewConfig: { + forceFit: true, + enableRowBody: true, + scrollOffset: 0, + autoFill: true, + showPreview: true, + getRowClass: function(record) { + return record.data.active ? 'grid-row-active' : 'grid-row-inactive'; } - } - ,sm: this.sm - ,columns: [this.sm,{ - header: _('id') - ,dataIndex: 'id' - ,width: 50 - ,sortable: true - },{ - header: _('username') - ,dataIndex: 'username' - ,width: 150 - ,sortable: true - ,renderer: { fn: function(v,md,record) { - return this.renderLink(v, { - href: '?a=security/user/update&id=' + record.data.id - }); - }, scope: this } - },{ - header: _('user_full_name') - ,dataIndex: 'fullname' - ,width: 180 - ,sortable: true - ,editor: { xtype: 'textfield' } - ,renderer: Ext.util.Format.htmlEncode - },{ - header: _('email') - ,dataIndex: 'email' - ,width: 180 - ,sortable: true - ,editor: { xtype: 'textfield' } - },{ - header: _('active') - ,dataIndex: 'active' - ,width: 80 - ,sortable: true - ,editor: { xtype: 'combo-boolean', renderer: 'boolean' } - },{ - header: _('user_block') - ,dataIndex: 'blocked' - ,width: 80 - ,sortable: true - ,editor: { xtype: 'combo-boolean', renderer: 'boolean' } - }] - ,tbar: [ - { - text: _('create') - ,handler: this.createUser - ,scope: this - ,cls:'primary-button' - },{ - text: _('bulk_actions') - ,menu: [ - { - text: _('selected_activate') - ,handler: this.activateSelected - ,scope: this - },{ - text: _('selected_deactivate') - ,handler: this.deactivateSelected - ,scope: this - },{ - text: _('selected_remove') - ,handler: this.removeSelected - ,scope: this - } - ] + }, + sm: this.sm, + columns: [this.sm, { + header: _('id'), + dataIndex: 'id', + width: 50, + sortable: true + }, { + header: _('username'), + dataIndex: 'username', + width: 150, + sortable: true, + renderer: { + fn: function(value, metaData, record) { + return this.userCanEditRecord(record) + ? this.renderLink(value, { + href: `?a=security/user/update&id=${record.data.id}`, + title: _('user_edit_account') + }) + : value + ; + }, + scope: this + } + }, { + header: _('user_full_name'), + dataIndex: 'fullname', + width: 180, + sortable: true, + editor: { xtype: 'textfield' }, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record); + return value; + }, + scope: this + } + }, { + header: _('email'), + dataIndex: 'email', + width: 180, + sortable: true, + editor: { + xtype: 'textfield' }, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record); + return value; + }, + scope: this + } + }, { + header: _('active'), + dataIndex: 'active', + width: 80, + sortable: true, + editor: { + xtype: 'combo-boolean' + }, + renderer: { + fn: function(value, metaData, record) { + const + displayValue = this.rendYesNo(value, metaData), + classes = `${metaData.css} ${this.setEditableCellClasses(record)}` + ; + // eslint-disable-next-line no-param-reassign + metaData.css = classes; + return displayValue; + }, + scope: this + } + }, { + header: _('user_block'), + dataIndex: 'blocked', + width: 80, + sortable: true, + editor: { + xtype: 'combo-boolean' + }, + renderer: { + fn: function(value, metaData, record) { + const + displayValue = this.rendYesNo(value, metaData), + classes = `${metaData.css} ${this.setEditableCellClasses(record)}` + ; + // eslint-disable-next-line no-param-reassign + metaData.css = classes; + return displayValue; + }, + scope: this + } + }], + tbar: [ + this.getCreateButton('user', 'createUser'), + this.getBulkActionsButton('user', 'Security/User/RemoveMultiple', 'int', 'activate', 'deactivate'), '->', { - xtype: 'modx-combo-usergroup' - ,itemId: 'filter-usergroup' - ,emptyText: `${_('user_group')}...` - ,baseParams: { - action: 'Security/Group/GetList' - ,addAll: true - } - ,value: MODx.request.usergroup || null - ,width: 200 - ,listeners: { + xtype: 'modx-combo-usergroup', + itemId: 'filter-usergroup', + emptyText: `${_('user_group')}...`, + baseParams: { + action: 'Security/Group/GetList', + addAll: true + }, + value: MODx.request.usergroup || null, + width: 200, + listeners: { select: { - fn: function (cmp, record, selectedIndex) { + fn: function(cmp, record, selectedIndex) { this.applyGridFilter(cmp, 'usergroup'); }, scope: this @@ -166,165 +196,153 @@ MODx.grid.User = function(config = {}) { this.getClearFiltersButton('filter-usergroup, filter-query') ] }); - MODx.grid.User.superclass.constructor.call(this,config); + MODx.grid.User.superclass.constructor.call(this, config); + + this.gridMenuActions = ['edit', 'delete', 'duplicate', 'activate']; + + this.setUserCanEdit(['edit_user', 'save_user']); + this.setUserCanCreate(['new_user', 'save_user']); + this.setUserCanDelete(['delete_user']); + this.setShowActionsMenu(); + + this.on({ + beforeedit: function(e) { + if (!this.userCanEdit || !this.userCanEditRecord(e.record)) { + return false; + } + } + }); }; -Ext.extend(MODx.grid.User,MODx.grid.Grid,{ +Ext.extend(MODx.grid.User, MODx.grid.Grid, { getMenu: function() { - var r = this.getSelectionModel().getSelected(); - var p = r.data.cls; - - var m = []; + const menu = []; if (this.getSelectionModel().getCount() > 1) { - m.push({ - text: _('selected_activate') - ,handler: this.activateSelected - ,scope: this - }); - m.push({ - text: _('selected_deactivate') - ,handler: this.deactivateSelected - ,scope: this - }); - m.push('-'); - m.push({ - text: _('selected_remove') - ,handler: this.removeSelected - ,scope: this - }); + if (this.userCanEdit) { + menu.push({ + text: _('selected_activate'), + handler: this.activateSelected, + scope: this + }); + menu.push({ + text: _('selected_deactivate'), + handler: this.deactivateSelected, + scope: this + }); + } + if (this.userCanDelete) { + menu.push('-'); + menu.push({ + text: _('selected_remove'), + handler: this.removeSelected.bind(this, 'user', 'Security/User/RemoveMultiple') + }); + } } else { - if (p.indexOf('pupdate') != -1) { - m.push({ - text: _('edit') - ,handler: this.updateUser + if (this.userCanEdit) { + menu.push({ + text: _('edit'), + handler: this.updateUser }); } - if (p.indexOf('pcopy') != -1) { - if (m.length > 0) m.push('-'); - m.push({ - text: _('duplicate') - ,handler: this.duplicateUser + if (this.userCanCreate) { + if (menu.length > 0) { menu.push('-'); } + menu.push({ + text: _('duplicate'), + handler: this.duplicateUser }); } - if (p.indexOf('premove') != -1) { - if (m.length > 0) m.push('-'); - m.push({ - text: _('delete') - ,handler: this.removeUser + if (this.userCanDelete) { + if (menu.length > 0) { menu.push('-'); } + menu.push({ + text: _('delete'), + handler: this.removeUser }); } } - if (m.length > 0) { - this.addContextMenuItem(m); - } - } + return menu; + }, - ,createUser: function() { + createUser: function() { MODx.loadPage('security/user/create'); - } + }, - ,updateUser: function() { - MODx.loadPage('security/user/update', 'id='+this.menu.record.id); - } + updateUser: function() { + MODx.loadPage('security/user/update', `id=${this.menu.record.id}`); + }, - ,duplicateUser: function() { + duplicateUser: function() { MODx.Ajax.request({ - url: this.config.url - ,params: { - action: 'Security/User/Duplicate' - ,id: this.menu.record.id - } - ,listeners: { - 'success': {fn:this.refresh,scope:this} + url: this.config.url, + params: { + action: 'Security/User/Duplicate', + id: this.menu.record.id + }, + listeners: { + success: { fn: this.refresh, scope: this } } }); - } + }, - ,removeUser: function() { + removeUser: function() { MODx.msg.confirm({ - title: _('delete') - ,text: _('user_confirm_remove') - ,url: this.config.url - ,params: { - action: 'Security/User/Delete' - ,id: this.menu.record.id - } - ,listeners: { - 'success': {fn:this.refresh,scope:this} + title: _('delete'), + text: _('user_confirm_remove'), + url: this.config.url, + params: { + action: 'Security/User/Delete', + id: this.menu.record.id + }, + listeners: { + success: { fn: this.refresh, scope: this } } }); - } - - ,activateSelected: function() { - var cs = this.getSelectedAsList(); - if (cs === false) return false; + }, + activateSelected: function() { + const selections = this.getSelectedAsList(); + if (selections === false) { + return false; + } MODx.Ajax.request({ - url: this.config.url - ,params: { - action: 'Security/User/ActivateMultiple' - ,users: cs - } - ,listeners: { - 'success': {fn:function(r) { - this.getSelectionModel().clearSelections(true); - this.refresh(); - },scope:this} + url: this.config.url, + params: { + action: 'Security/User/ActivateMultiple', + users: selections + }, + listeners: { + success: { + fn: function() { + this.getSelectionModel().clearSelections(true); + this.refresh(); + }, + scope: this + } } }); return true; - } - - ,deactivateSelected: function() { - var cs = this.getSelectedAsList(); - if (cs === false) return false; + }, + deactivateSelected: function() { + const selections = this.getSelectedAsList(); + if (selections === false) { + return false; + } MODx.Ajax.request({ - url: this.config.url - ,params: { - action: 'Security/User/DeactivateMultiple' - ,users: cs - } - ,listeners: { - 'success': {fn:function(r) { - this.getSelectionModel().clearSelections(true); - this.refresh(); - },scope:this} - } - }); - return true; - } - - ,removeSelected: function() { - var cs = this.getSelectedAsList(); - if (cs === false) return false; - - MODx.msg.confirm({ - title: _('selected_remove') - ,text: _('user_remove_multiple_confirm') - ,url: this.config.url - ,params: { - action: 'Security/User/RemoveMultiple' - ,users: cs - } - ,listeners: { - 'success': {fn:function(r) { - this.getSelectionModel().clearSelections(true); - this.refresh(); - },scope:this} + url: this.config.url, + params: { + action: 'Security/User/DeactivateMultiple', + users: selections + }, + listeners: { + success: { + fn: function() { + this.getSelectionModel().clearSelections(true); + this.refresh(); + }, + scope: this + } } }); return true; } - - ,rendGender: function(d,c) { - switch(d.toString()) { - case '0': - return '-'; - case '1': - return _('male'); - case '2': - return _('female'); - } - } }); -Ext.reg('modx-grid-user',MODx.grid.User); +Ext.reg('modx-grid-user', MODx.grid.User); diff --git a/manager/assets/modext/widgets/security/modx.grid.user.recent.resource.js b/manager/assets/modext/widgets/security/modx.grid.user.recent.resource.js index a64f3929cde..ffddb242ac8 100644 --- a/manager/assets/modext/widgets/security/modx.grid.user.recent.resource.js +++ b/manager/assets/modext/widgets/security/modx.grid.user.recent.resource.js @@ -6,72 +6,116 @@ * @param {Object} config An object of options. * @xtype modx-grid-user-recent-resource */ -MODx.grid.RecentlyEditedResourcesByUser = function(config) { - config = config || {}; - var dateFormat = MODx.config.manager_date_format + ' ' + MODx.config.manager_time_format; - Ext.applyIf(config,{ - title: _('recent_docs') - ,url: MODx.config.connector_url - ,baseParams: { - action: 'Security/User/GetRecentlyEditedResources' - ,user: config.user - } - ,autosave: true - ,save_action: 'Resource/UpdateFromGrid' - ,pageSize: 10 - ,fields: ['id','pagetitle','description','editedon','deleted','published','context_key','menu', 'link', 'occurred'] - ,columns: [{ - header: _('id') - ,dataIndex: 'id' - ,width: 75 - ,fixed: true - },{ - header: _('pagetitle') - ,dataIndex: 'pagetitle' - ,renderer: { fn: function(v,md,record) { - return this.renderLink(v, { - href: '?a=resource/update&id=' + record.data.id - ,target: '_blank' - }); - }, scope: this } - },{ - header: _('editedon') - ,dataIndex: 'occurred' - },{ - header: _('published') - ,dataIndex: 'published' - ,width: 120 - ,fixed: true - ,editor: { xtype: 'combo-boolean' ,renderer: 'boolean' } - }] - ,paging: true - ,listeners: { - afteredit: this.refresh - ,afterrender: this.onAfterRender - ,scope: this +MODx.grid.RecentlyEditedResourcesByUser = function(config = {}) { + const dateFormat = `${MODx.config.manager_date_format} ${MODx.config.manager_time_format}`; + Ext.applyIf(config, { + title: _('recent_docs'), + url: MODx.config.connector_url, + baseParams: { + action: 'Security/User/GetRecentlyEditedResources', + user: config.user + }, + autosave: true, + save_action: 'Resource/UpdateFromGrid', + pageSize: 10, + fields: [ + 'id', + 'pagetitle', + 'description', + 'editedon', + 'deleted', + 'published', + 'context_key', + 'menu', + 'link', + 'occurred' + ], + columns: [{ + header: _('id'), + dataIndex: 'id', + width: 75, + fixed: true + }, { + header: _('pagetitle'), + dataIndex: 'pagetitle', + renderer: { + fn: function(value, metaData, record) { + return this.renderLink(value, { + href: `?a=resource/update&id=${record.data.id}`, + target: '_blank' + }); + }, + scope: this + } + }, { + header: _('editedon'), + dataIndex: 'occurred', + renderer: Ext.util.Format.dateRenderer(dateFormat) + }, { + header: _('published'), + dataIndex: 'published', + width: 120, + fixed: true, + editor: { + xtype: 'combo-boolean', + renderer: 'boolean' + } + }], + paging: true, + listeners: { + afteredit: this.refresh, + afterrender: this.onAfterRender, + scope: this } }); - MODx.grid.RecentlyEditedResourcesByUser.superclass.constructor.call(this,config); + MODx.grid.RecentlyEditedResourcesByUser.superclass.constructor.call(this, config); }; -Ext.extend(MODx.grid.RecentlyEditedResourcesByUser,MODx.grid.Grid,{ +Ext.extend(MODx.grid.RecentlyEditedResourcesByUser, MODx.grid.Grid, { + getMenu: function() { + const menu = []; + menu.push({ + text: _('resource_overview'), + params: { + a: 'resource/data', + type: 'view' + } + }); + if (MODx.perm.edit_document) { + menu.push({ + text: _('resource_edit'), + params: { + a: 'resource/update', + type: 'edit' + } + }); + } + menu.push('-'); + menu.push({ + text: _('resource_view'), + handler: this.preview + }); + + return menu; + }, + preview: function() { window.open(this.menu.record.link); - } - ,refresh: function() { - var tree = Ext.getCmp('modx-resource-tree'); + }, + refresh: function() { + const tree = Ext.getCmp('modx-resource-tree'); if (tree && tree.rendered) { tree.refresh(); } - } + }, // Workaround to resize the grid when in a dashboard widget - ,onAfterRender: function() { - var cnt = Ext.getCmp('modx-content') - // Dashboard widget "parent" (renderTo) - ,parent = Ext.get('modx-grid-user-recent-resource'); - - if (cnt && parent) { - cnt.on('afterlayout', function(elem, layout) { - var width = parent.getWidth(); + onAfterRender: function() { + const + contentCmp = Ext.getCmp('modx-content'), + grid = Ext.get('modx-grid-user-recent-resource') + ; + if (contentCmp && grid) { + contentCmp.on('afterlayout', function(elem, layout) { + const width = grid.getWidth(); // Only resize when more than 500px (else let's use/enable the horizontal scrolling) if (width > 500) { this.setWidth(width); @@ -80,4 +124,4 @@ Ext.extend(MODx.grid.RecentlyEditedResourcesByUser,MODx.grid.Grid,{ } } }); -Ext.reg('modx-grid-user-recent-resource',MODx.grid.RecentlyEditedResourcesByUser); +Ext.reg('modx-grid-user-recent-resource', MODx.grid.RecentlyEditedResourcesByUser); diff --git a/manager/assets/modext/widgets/security/modx.panel.user.group.js b/manager/assets/modext/widgets/security/modx.panel.user.group.js index d1bb58f287a..da842026514 100644 --- a/manager/assets/modext/widgets/security/modx.panel.user.group.js +++ b/manager/assets/modext/widgets/security/modx.panel.user.group.js @@ -4,240 +4,242 @@ * @param {Object} config An object of configuration properties * @xtype modx-panel-user-group */ -MODx.panel.UserGroup = function(config) { - config = config || {}; - Ext.applyIf(config,{ - id: 'modx-panel-user-group' - ,cls: 'container form-with-labels' - ,url: MODx.config.connector_url - ,baseParams: { +MODx.panel.UserGroup = function(config = {}) { + Ext.applyIf(config, { + id: 'modx-panel-user-group', + cls: 'container form-with-labels', + url: MODx.config.connector_url, + baseParams: { action: 'Security/Group/Update' - } - ,defaults: { collapsible: false ,autoHeight: true } - ,items: [this.getPageHeader(config),{ - xtype: 'modx-tabs' - ,defaults: { - autoHeight: true - ,border: true - ,bodyCssClass: 'tab-panel-wrapper' - ,hideMode: 'offsets' - } - ,id: 'modx-usergroup-tabs' - ,forceLayout: true - ,deferredRender: false - ,items: [{ - title: _('general_information') - ,defaults: { - border: false - ,msgTarget: 'side' - } - ,layout: 'form' - ,itemId: 'modx-usergroup-general-panel' - ,labelAlign: 'top' - ,labelSeparator: '' - ,items: [{ - xtype: 'panel' - ,border: false - ,cls: 'main-wrapper' - ,layout: 'form' - ,items: [{ - layout: 'column' - ,border: false - ,defaults: { - layout: 'form' - ,labelAlign: 'top' - ,labelSeparator: '' - ,anchor: '100%' - ,border: false - } - ,items: [{ - columnWidth: .6 - ,items: [{ - xtype: 'hidden' - ,name: 'id' - ,id: 'modx-usergroup-id' - ,value: config.record.id - },{ - name: 'name' - ,id: 'modx-usergroup-name' - ,xtype: config.record && (config.record.name === 'Administrator' || config.record.id === 0) ? 'statictextfield' : 'textfield' - ,fieldLabel: _('name') - ,allowBlank: false - ,enableKeyEvents: true - ,disabled: config.record.id === 0 - ,anchor: '100%' - ,listeners: { - 'keyup': {scope:this,fn:function(f,e) { - Ext.getCmp('modx-header-breadcrumbs').updateHeader(Ext.util.Format.htmlEncode(f.getValue())); - }} + }, + defaults: { + collapsible: false, + autoHeight: true + }, + items: [this.getPageHeader(config), { + xtype: 'modx-tabs', + defaults: { + autoHeight: true, + border: true, + bodyCssClass: 'tab-panel-wrapper', + hideMode: 'offsets' + }, + id: 'modx-usergroup-tabs', + forceLayout: true, + deferredRender: false, + items: [{ + title: _('general_information'), + defaults: { + border: false, + msgTarget: 'side' + }, + layout: 'form', + itemId: 'modx-usergroup-general-panel', + labelAlign: 'top', + labelSeparator: '', + items: [{ + xtype: 'panel', + border: false, + cls: 'main-wrapper', + layout: 'form', + items: [{ + layout: 'column', + border: false, + defaults: { + layout: 'form', + labelAlign: 'top', + labelSeparator: '', + anchor: '100%', + border: false + }, + items: [{ + columnWidth: 0.6, + items: [{ + xtype: 'hidden', + name: 'id', + id: 'modx-usergroup-id', + value: config.record.id + }, { + name: 'name', + xtype: config.record && (config.record.name === 'Administrator' || config.record.id === 0) ? 'statictextfield' : 'textfield', + fieldLabel: _('name'), + allowBlank: false, + enableKeyEvents: true, + disabled: config.record.id === 0, + anchor: '100%', + listeners: { + keyup: { + fn: function(f, e) { + Ext.getCmp('modx-header-breadcrumbs').updateHeader(Ext.util.Format.htmlEncode(f.getValue())); + }, + scope: this + } } - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-usergroup-name' - ,html: _('user_group_desc_name') - ,cls: 'desc-under' - },{ - name: 'description' - ,id: 'modx-usergroup-description' - ,xtype: 'textarea' - ,fieldLabel: _('description') - ,anchor: '100%' - ,grow: true - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-usergroup-description' - ,html: _('user_group_desc_description') - ,cls: 'desc-under' + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('user_group_desc_name'), + cls: 'desc-under' + }, { + name: 'description', + xtype: 'textarea', + fieldLabel: _('description'), + anchor: '100%', + grow: true + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('user_group_desc_description'), + cls: 'desc-under' }] - },{ - columnWidth: .4 - ,items: [{ - name: 'parent' - ,hiddenName: 'parent' - ,id: 'modx-usergroup-parent' - ,xtype: 'modx-combo-usergroup' - ,fieldLabel: _('user_group_parent') - ,editable: false - ,anchor: '100%' - ,disabled: config.record.id === 0 || config.record.name === 'Administrator' - ,baseParams: { - action: 'Security/Group/GetList' - ,addNone: true - ,exclude: config.record.id + }, { + columnWidth: 0.4, + items: [{ + name: 'parent', + hiddenName: 'parent', + xtype: 'modx-combo-usergroup', + fieldLabel: _('user_group_parent'), + editable: false, + anchor: '100%', + disabled: config.record.id === 0 || config.record.name === 'Administrator', + baseParams: { + action: 'Security/Group/GetList', + addNone: true, + exclude: config.record.id } - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-usergroup-parent' - ,html: _('user_group_desc_parent') - ,cls: 'desc-under' - },{ - name: 'dashboard' - ,id: 'modx-usergroup-dashboard' - ,xtype: 'modx-combo-dashboard' - ,fieldLabel: _('dashboard') - ,anchor: '100%' - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-usergroup-dashboard' - ,html: _('user_group_desc_dashboard') - ,cls: 'desc-under' + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('user_group_desc_parent'), + cls: 'desc-under' + }, { + name: 'dashboard', + xtype: 'modx-combo-dashboard', + fieldLabel: _('dashboard'), + anchor: '100%' + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('user_group_desc_dashboard'), + cls: 'desc-under' }] }] }] }] - },{ - title: _('access_permissions') - ,itemId: 'modx-usergroup-permissions-panel' - ,items: [{ - xtype: 'modx-vtabs' - ,items: [{ - title: _('user_group_context_access') - ,itemId: 'user-group-context-access' - ,hideMode: 'offsets' - ,layout: 'form' - ,autoWidth: false - ,items: [{ - html: '

    '+_('user_group_context_access_msg')+'

    ' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-user-group-context' - ,preventRender: true - ,usergroup: config.record.id - ,autoHeight: true - ,cls: 'main-wrapper' - ,listeners: { - 'afterRemoveRow': {fn:this.markDirty,scope:this} - ,'afteredit': {fn:this.markDirty,scope:this} - ,'updateAcl': {fn:this.markDirty,scope:this} - ,'createAcl': {fn:this.markDirty,scope:this} + }, { + title: _('access_permissions'), + itemId: 'modx-usergroup-permissions-panel', + items: [{ + xtype: 'modx-vtabs', + items: [{ + title: _('user_group_context_access'), + itemId: 'user-group-context-access', + hideMode: 'offsets', + layout: 'form', + autoWidth: false, + items: [{ + html: `

    ${_('user_group_context_access_msg')}

    `, + xtype: 'modx-description' + }, { + xtype: 'modx-grid-user-group-context', + preventRender: true, + usergroup: config.record.id, + autoHeight: true, + cls: 'main-wrapper', + listeners: { + afterRemoveRow: { fn: this.markDirty, scope: this }, + afteredit: { fn: this.markDirty, scope: this }, + updateAcl: { fn: this.markDirty, scope: this }, + createAcl: { fn: this.markDirty, scope: this } } }] - },{ - title: _('user_group_resourcegroup_access') - ,itemId: 'user-group-resourcegroup-access' - ,hideMode: 'offsets' - ,layout: 'form' - ,items: [{ - html: '

    '+_('user_group_resourcegroup_access_msg')+'

    ' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-user-group-resource-group' - ,cls: 'main-wrapper' - ,preventRender: true - ,usergroup: config.record.id - ,autoHeight: true - ,listeners: { - 'afterRemoveRow': {fn:this.markDirty,scope:this} - ,'afteredit': {fn:this.markDirty,scope:this} - ,'updateAcl': {fn:this.markDirty,scope:this} - ,'createAcl': {fn:this.markDirty,scope:this} + }, { + title: _('user_group_resourcegroup_access'), + itemId: 'user-group-resourcegroup-access', + hideMode: 'offsets', + layout: 'form', + items: [{ + html: `

    ${_('user_group_resourcegroup_access_msg')}

    `, + xtype: 'modx-description' + }, { + xtype: 'modx-grid-user-group-resource-group', + cls: 'main-wrapper', + preventRender: true, + usergroup: config.record.id, + autoHeight: true, + listeners: { + afterRemoveRow: { fn: this.markDirty, scope: this }, + afteredit: { fn: this.markDirty, scope: this }, + updateAcl: { fn: this.markDirty, scope: this }, + createAcl: { fn: this.markDirty, scope: this } } }] - },{ - title: _('user_group_category_access') - ,itemId: 'user-group-category-access' - ,hideMode: 'offsets' - ,layout: 'form' - ,items: [{ - html: '

    '+_('user_group_category_access_msg')+'

    ' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-user-group-category' - ,cls: 'main-wrapper' - ,preventRender: true - ,usergroup: config.record.id - ,autoHeight: true - ,listeners: { - 'afterRemoveRow': {fn:this.markDirty,scope:this} - ,'afteredit': {fn:this.markDirty,scope:this} - ,'updateAcl': {fn:this.markDirty,scope:this} - ,'createAcl': {fn:this.markDirty,scope:this} + }, { + title: _('user_group_category_access'), + itemId: 'user-group-category-access', + hideMode: 'offsets', + layout: 'form', + items: [{ + html: `

    ${_('user_group_category_access_msg')}

    `, + xtype: 'modx-description' + }, { + xtype: 'modx-grid-user-group-category', + cls: 'main-wrapper', + preventRender: true, + usergroup: config.record.id, + autoHeight: true, + listeners: { + afterRemoveRow: { fn: this.markDirty, scope: this }, + afteredit: { fn: this.markDirty, scope: this }, + updateAcl: { fn: this.markDirty, scope: this }, + createAcl: { fn: this.markDirty, scope: this } } }] - },{ - title: _('user_group_source_access') - ,itemId: 'user-group-source-access' - ,hideMode: 'offsets' - ,layout: 'form' - ,items: [{ - html: '

    '+_('user_group_source_access_msg')+'

    ' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-user-group-source' - ,cls: 'main-wrapper' - ,preventRender: true - ,usergroup: config.record.id - ,autoHeight: true - ,listeners: { - 'afterRemoveRow': {fn:this.markDirty,scope:this} - ,'afteredit': {fn:this.markDirty,scope:this} - ,'updateAcl': {fn:this.markDirty,scope:this} - ,'createAcl': {fn:this.markDirty,scope:this} + }, { + title: _('user_group_source_access'), + itemId: 'user-group-source-access', + hideMode: 'offsets', + layout: 'form', + items: [{ + html: `

    ${_('user_group_source_access_msg')}

    `, + xtype: 'modx-description' + }, { + xtype: 'modx-grid-user-group-source', + cls: 'main-wrapper', + preventRender: true, + usergroup: config.record.id, + autoHeight: true, + listeners: { + afterRemoveRow: { fn: this.markDirty, scope: this }, + afteredit: { fn: this.markDirty, scope: this }, + updateAcl: { fn: this.markDirty, scope: this }, + createAcl: { fn: this.markDirty, scope: this } } }] - },{ - title: _('user_group_namespace_access') - ,itemId: 'user-group-namespace-access' - ,hideMode: 'offsets' - ,layout: 'form' - ,items: [{ - html: '

    ' + _('user_group_namespace_access_desc') + '

    ' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-user-group-namespace' - ,cls: 'main-wrapper' - ,preventRender: true - ,usergroup: config.record.id - ,autoHeight: true + }, { + title: _('user_group_namespace_access'), + itemId: 'user-group-namespace-access', + hideMode: 'offsets', + layout: 'form', + items: [{ + html: `

    ${_('user_group_namespace_access_desc')}

    `, + xtype: 'modx-description' + }, { + xtype: 'modx-grid-user-group-namespace', + cls: 'main-wrapper', + preventRender: true, + usergroup: config.record.id, + autoHeight: true }] - }] - ,listeners: { + }], + listeners: { render: function(vtabPanel) { - var elCatsPanelKey = vtabPanel.items.keys.indexOf('user-group-category-access'), + const + elCatsPanelKey = vtabPanel.items.keys.indexOf('user-group-category-access'), mediaSrcPanelKey = vtabPanel.items.keys.indexOf('user-group-source-access'), - namespacePanelKey = vtabPanel.items.keys.indexOf('user-group-namespace-access') + namespacePanelKey = vtabPanel.items.keys.indexOf('user-group-namespace-access'), form = Ext.getCmp('modx-panel-user-group').getForm() - ; + ; if (form.record.id === 0) { vtabPanel.hideTabStripItem(elCatsPanelKey); vtabPanel.hideTabStripItem(mediaSrcPanelKey); @@ -246,45 +248,46 @@ MODx.panel.UserGroup = function(config) { } } }] - },{ - title: _('users') - ,itemId: 'modx-usergroup-users-panel' - ,items: [{ - html: '

    '+_('user_group_user_access_msg')+'

    ' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-user-group-users' - ,cls: 'main-wrapper' - ,preventRender: true - ,usergroup: config.record.id - ,autoHeight: true - ,listeners: { - 'afterRemoveRow': {fn:this.markDirty,scope:this} - ,'updateRole': {fn:this.markDirty,scope:this} - ,'addUser': {fn:this.markDirty,scope:this} + }, { + title: _('users'), + itemId: 'modx-usergroup-users-panel', + items: [{ + html: `

    ${_('user_group_user_access_msg')}

    `, + xtype: 'modx-description' + }, { + xtype: 'modx-grid-user-group-users', + cls: 'main-wrapper', + preventRender: true, + usergroup: config.record.id, + autoHeight: true, + listeners: { + afterRemoveRow: { fn: this.markDirty, scope: this }, + updateRole: { fn: this.markDirty, scope: this }, + addUser: { fn: this.markDirty, scope: this } } }] - },{ - title: _('settings') - ,itemId: 'modx-usergroup-settings-panel' - ,layout: 'form' - ,items: [{ - html: '

    '+_('user_group_settings_desc')+'

    ' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-group-settings' - ,cls: 'main-wrapper' - ,preventRender: true - ,group: config.record.id - ,autoHeight: true + }, { + title: _('settings'), + itemId: 'modx-usergroup-settings-panel', + layout: 'form', + items: [{ + html: `

    ${_('user_group_settings_desc')}

    `, + xtype: 'modx-description' + }, { + xtype: 'modx-grid-group-settings', + cls: 'main-wrapper', + preventRender: true, + group: config.record.id, + autoHeight: true }] - }] - ,listeners: { + }], + listeners: { render: function(tabPanel) { - var usersPanelKey = tabPanel.items.keys.indexOf('modx-usergroup-users-panel'), + const + usersPanelKey = tabPanel.items.keys.indexOf('modx-usergroup-users-panel'), settingsPanelKey = tabPanel.items.keys.indexOf('modx-usergroup-settings-panel'), form = Ext.getCmp('modx-panel-user-group').getForm() - ; + ; if (form.record.id === 0) { tabPanel.hideTabStripItem(usersPanelKey); tabPanel.hideTabStripItem(settingsPanelKey); @@ -294,41 +297,41 @@ MODx.panel.UserGroup = function(config) { } } } - }] - ,useLoadingMask: false - ,listeners: { - 'setup': {fn:this.setup,scope:this} - ,'success': {fn:this.success,scope:this} - ,'beforeSubmit': {fn:this.beforeSubmit,scope:this} + }], + useLoadingMask: false, + listeners: { + setup: { fn: this.setup, scope: this }, + success: { fn: this.success, scope: this }, + beforeSubmit: { fn: this.beforeSubmit, scope: this } } }); - MODx.panel.UserGroup.superclass.constructor.call(this,config); + MODx.panel.UserGroup.superclass.constructor.call(this, config); }; -Ext.extend(MODx.panel.UserGroup,MODx.FormPanel,{ - initialized: false - ,setup: function() { - if (this.initialized || this.config.usergroup === '' || this.config.usergroup == undefined) { +Ext.extend(MODx.panel.UserGroup, MODx.FormPanel, { + initialized: false, + setup: function() { + if (this.initialized || this.config.usergroup === '' || this.config.usergroup === undefined) { this.fireEvent('ready'); return false; } - var r = this.config.record; - this.getForm().setValues(r); - Ext.getCmp('modx-header-breadcrumbs').updateHeader(Ext.util.Format.htmlEncode(r.name)); + const { record } = this.config; + this.getForm().setValues(record); + Ext.getCmp('modx-header-breadcrumbs').updateHeader(Ext.util.Format.htmlEncode(record.name)); - this.fireEvent('ready',r); + this.fireEvent('ready', record); MODx.fireEvent('ready'); this.initialized = true; - } - ,beforeSubmit: function(o) {} - ,success: function(o) {} - ,getPageHeader: function(config) { + }, + beforeSubmit: function(o) {}, + success: function(o) {}, + getPageHeader: function(config) { return MODx.util.getHeaderBreadCrumbs('modx-user-group-header', [{ text: _('user_group_management'), href: MODx.getPage('security/permission') }]); } }); -Ext.reg('modx-panel-user-group',MODx.panel.UserGroup); +Ext.reg('modx-panel-user-group', MODx.panel.UserGroup); /** * @class MODx.grid.FCProfileUserGroups @@ -339,153 +342,197 @@ Ext.reg('modx-panel-user-group',MODx.panel.UserGroup); MODx.grid.UserGroupUsers = function(config = {}) { const /** @var targetTab This grid shows in one of two places as of 3.0.x, in the ACLs summary view, and within a specific group’s ACLs view (in different tabs) */ - targetTab = MODx.request.a === 'security/permission' ? 0 : 2 , + targetTab = MODx.request.a === 'security/permission' ? 0 : 2, queryValue = this.applyRequestFilter(targetTab, 'query', 'tab', true) ; - Ext.applyIf(config,{ - title: '' - ,id: 'modx-grid-user-group-users' - ,url: MODx.config.connector_url - ,baseParams: { - action: 'Security/Group/User/GetList' - ,usergroup: config.usergroup - } - ,paging: true - ,grouping: true - ,remoteSort: true - ,groupBy: 'role_name' - ,singleText: _('user') - ,pluralText: _('users') - ,sortBy: 'authority' - ,sortDir: 'ASC' - ,fields: [ + Ext.applyIf(config, { + title: '', + id: 'modx-grid-user-group-users', + url: MODx.config.connector_url, + baseParams: { + action: 'Security/Group/User/GetList', + usergroup: config.usergroup + }, + paging: true, + grouping: true, + remoteSort: true, + groupBy: 'role_name', + singleText: _('user'), + pluralText: _('users'), + sortBy: 'authority', + sortDir: 'ASC', + fields: [ 'id', 'username', 'role', 'role_name', 'authority' - ] - ,columns: [{ - header: _('username') - ,dataIndex: 'username' - ,width: 175 - ,sortable: true - ,renderer: { fn: function(v,md,record) { - return this.renderLink(v, { - href: '?a=security/user/update&id=' + record.data.id - ,target: '_blank' - }); - }, scope: this } - },{ - header: _('role') - ,dataIndex: 'role_name' - ,width: 175 - ,sortable: true - ,renderer: { fn: function(v,md,record) { - return this.renderLink(v, { - href: '?a=security/permission' - ,target: '_blank' - }); - }, scope: this } - }] - ,tbar: [ + ], + columns: [{ + header: _('username'), + dataIndex: 'username', + width: 175, + sortable: true, + renderer: { + fn: function(value, metaData, record) { + return this.userCanEditUsers + ? this.renderLink(value, { + href: `?a=security/user/update&id=${record.id}`, + target: '_blank' + }) + : value + ; + }, + scope: this + } + }, { + header: _('role'), + dataIndex: 'role_name', + width: 175, + sortable: true, + renderer: { + fn: function(value, metaData, record) { + return this.userCanEditRoles + ? this.renderLink(value, { + href: `?a=security/permission&tab=1&role=${record.json.role}`, + target: '_blank' + }) + : value + ; + }, + scope: this + } + }], + tbar: [ + /* + Because visibility of these buttons is determined by non-standard + and differing create permissions, not using base method getCreateButton() + here; controlled by render listener below + */ { - text: _('user_group_update') - ,cls: 'primary-button' - ,handler: this.updateUserGroup - ,hidden: (MODx.perm.usergroup_edit == 0 || config.ownerCt.id != 'modx-tree-panel-usergroup') - },{ - text: _('user_group_user_add') - ,cls: 'primary-button' - ,handler: this.addUser - ,hidden: MODx.perm.usergroup_user_edit == 0 + text: _('user_group_update'), + id: 'modx-btn-user-group-edit', + cls: 'primary-button', + handler: this.updateUserGroup + }, { + text: _('user_group_user_add'), + id: 'modx-btn-user-group-add-user', + cls: 'primary-button', + handler: this.addUser }, '->', this.getQueryFilterField(`filter-query-users:${queryValue}`, 'user-group-users'), this.getClearFiltersButton('filter-query-users') ] }); - MODx.grid.UserGroupUsers.superclass.constructor.call(this,config); - this.addEvents('updateRole','addUser'); + MODx.grid.UserGroupUsers.superclass.constructor.call(this, config); + this.addEvents('updateRole', 'addUser'); + + this.gridMenuActions = ['editGroupUsers']; + this.setUserHasPermissions('editGroups', ['usergroup_edit', 'usergroup_save']); + this.setUserHasPermissions('editGroupUsers', ['usergroup_user_edit']); + this.setUserHasPermissions('editRoles', ['edit_role', 'save_role']); + this.setUserHasPermissions('editUsers', ['edit_user', 'save_user']); + this.setShowActionsMenu(); + + this.on({ + render: grid => { + const buttonsToHide = []; + if (!this.userCanEditGroups || grid.ownerCt.id !== 'modx-tree-panel-usergroup') { + buttonsToHide.push('modx-btn-user-group-edit'); + } + if (!this.userCanEditGroupUsers) { + buttonsToHide.push('modx-btn-user-group-add-user'); + } + if (buttonsToHide.length > 0) { + buttonsToHide.forEach(btnId => Ext.getCmp(btnId)?.hide()); + } + } + }); }; -Ext.extend(MODx.grid.UserGroupUsers,MODx.grid.Grid,{ +Ext.extend(MODx.grid.UserGroupUsers, MODx.grid.Grid, { getMenu: function() { - var m = []; - if (MODx.perm.usergroup_user_edit) { - m.push({ - text: _('user_role_update') - ,handler: this.updateRole + const menu = []; + if (this.userCanEditGroupUsers) { + menu.push({ + text: _('user_role_update'), + handler: this.updateRole }); - m.push('-'); - m.push({ - text: _('user_group_user_remove') - ,handler: this.removeUser + menu.push('-'); + menu.push({ + text: _('user_group_user_remove'), + handler: this.removeUser }); } - return m; - } + return menu; + }, - ,updateUserGroup: function() { - var id = this.config.usergroup; - MODx.loadPage('security/usergroup/update', 'id=' + id); - } + updateUserGroup: function() { + const id = this.config.usergroup; + MODx.loadPage('security/usergroup/update', `id=${id}`); + }, - ,updateRole: function(btn,e) { - var r = this.menu.record; - r.usergroup = this.config.usergroup; - r.user = r.id; + updateRole: function(btn, e) { + const { record } = this.menu; + record.usergroup = this.config.usergroup; + record.user = record.id; - this.loadWindow(btn,e,{ - xtype: 'modx-window-user-group-role-update' - ,record: r - ,listeners: { - 'success': {fn:function(r) { - this.refresh(); - this.fireEvent('updateRole',r); - },scope:this} + this.loadWindow(btn, e, { + xtype: 'modx-window-user-group-role-update', + record: record, + listeners: { + success: { + fn: function(response) { + this.refresh(); + this.fireEvent('updateRole', response); + }, + scope: this + } } }); - } + }, - ,addUser: function(btn,e) { - var r = {usergroup:this.config.usergroup}; + addUser: function(btn, e) { + const record = { usergroup: this.config.usergroup }; if (!this.windows['modx-window-user-group-adduser']) { this.windows['modx-window-user-group-adduser'] = Ext.ComponentMgr.create({ - xtype: 'modx-window-user-group-adduser' - ,record: r - ,grid: this - ,listeners: { - 'success': {fn:function(r) { - this.refresh(); - this.fireEvent('addUser',r); - },scope:this} + xtype: 'modx-window-user-group-adduser', + record: record, + grid: this, + listeners: { + success: { + fn: function(response) { + this.refresh(); + this.fireEvent('addUser', response); + }, + scope: this + } } }); } - - this.windows['modx-window-user-group-adduser'].setValues(r); + this.windows['modx-window-user-group-adduser'].setValues(record); this.windows['modx-window-user-group-adduser'].show(e.target); - } + }, - ,removeUser: function(btn,e) { - var r = this.menu.record; + removeUser: function(btn, e) { + const { record } = this.menu; MODx.msg.confirm({ - title: _('warning') - ,text: _('user_group_user_remove_confirm') || _('confirm_remove') - ,url: this.config.url - ,params: { - action: 'Security/Group/User/Remove' - ,user: r.id - ,usergroup: this.config.usergroup - } - ,listeners: { - 'success': {fn:this.refresh,scope:this} + title: _('warning'), + text: _('user_group_user_remove_confirm') || _('confirm_remove'), + url: this.config.url, + params: { + action: 'Security/Group/User/Remove', + user: record.id, + usergroup: this.config.usergroup + }, + listeners: { + success: { fn: this.refresh, scope: this } } }); } }); -Ext.reg('modx-grid-user-group-users',MODx.grid.UserGroupUsers); +Ext.reg('modx-grid-user-group-users', MODx.grid.UserGroupUsers); /** * @class MODx.window.UpdateUserGroupRole @@ -493,32 +540,31 @@ Ext.reg('modx-grid-user-group-users',MODx.grid.UserGroupUsers); * @param {Object} config An object of options. * @xtype modx-window-user-group-role-update */ -MODx.window.UpdateUserGroupRole = function(config) { - config = config || {}; - Ext.applyIf(config,{ - id: 'modx-window-user-group-role-update' - ,title: _('user_group_user_update_role') - ,url: MODx.config.connector_url - ,action: 'Security/Group/User/Update' - ,fields: [{ - xtype: 'hidden' - ,name: 'usergroup' - ,value: config.usergroup - },{ - xtype: 'hidden' - ,name: 'user' - ,value: config.user - },{ - xtype: 'modx-combo-usergrouprole' - ,id: 'modx-uugr-role' - ,name: 'role' - ,fieldLabel: _('role') +MODx.window.UpdateUserGroupRole = function(config = {}) { + Ext.applyIf(config, { + id: 'modx-window-user-group-role-update', + title: _('user_group_user_update_role'), + url: MODx.config.connector_url, + action: 'Security/Group/User/Update', + fields: [{ + xtype: 'hidden', + name: 'usergroup', + value: config.usergroup + }, { + xtype: 'hidden', + name: 'user', + value: config.user + }, { + xtype: 'modx-combo-usergrouprole', + id: 'modx-uugr-role', + name: 'role', + fieldLabel: _('role') }] }); - MODx.window.UpdateUserGroupRole.superclass.constructor.call(this,config); + MODx.window.UpdateUserGroupRole.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.UpdateUserGroupRole,MODx.Window); -Ext.reg('modx-window-user-group-role-update',MODx.window.UpdateUserGroupRole); +Ext.extend(MODx.window.UpdateUserGroupRole, MODx.Window); +Ext.reg('modx-window-user-group-role-update', MODx.window.UpdateUserGroupRole); /** * @class MODx.window.AddUserToUserGroup @@ -526,49 +572,46 @@ Ext.reg('modx-window-user-group-role-update',MODx.window.UpdateUserGroupRole); * @param {Object} config An object of options. * @xtype modx-window-user-group-adduser */ -MODx.window.AddUserToUserGroup = function(config) { - config = config || {}; - this.ident = config.ident || 'auug'+Ext.id(); - Ext.applyIf(config,{ - title: _('user_group_user_add') - ,url: MODx.config.connector_url - ,action: 'Security/Group/User/Create' - ,fields: [{ - fieldLabel: _('user') - ,description: MODx.expandHelp ? '' : _('user_group_user_add_user_desc') - ,name: 'user' - ,hiddenName: 'user' - ,id: 'modx-auug-user' - ,xtype: 'modx-combo-user' - ,editable: true - ,typeAhead: true - ,allowBlank: false - ,anchor: '100%' - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-'+this.ident+'-user' - ,html: _('user_group_user_add_user_desc') - ,cls: 'desc-under' - },{ - fieldLabel: _('role') - ,description: MODx.expandHelp ? '' : _('user_group_user_add_role_desc') - ,name: 'role' - ,hiddenName: 'role' - ,id: 'modx-auug-role' - ,xtype: 'modx-combo-role' - ,allowBlank: false - ,anchor: '100%' - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-'+this.ident+'-role' - ,html: _('user_group_user_add_role_desc') - ,cls: 'desc-under' - },{ - name: 'usergroup' - ,xtype: 'hidden' +MODx.window.AddUserToUserGroup = function(config = {}) { + this.ident = config.ident || `auug${Ext.id()}`; + Ext.applyIf(config, { + title: _('user_group_user_add'), + url: MODx.config.connector_url, + action: 'Security/Group/User/Create', + fields: [{ + fieldLabel: _('user'), + description: MODx.expandHelp ? '' : _('user_group_user_add_user_desc'), + name: 'user', + hiddenName: 'user', + xtype: 'modx-combo-user', + editable: true, + typeAhead: true, + allowBlank: false, + anchor: '100%' + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('user_group_user_add_user_desc'), + cls: 'desc-under' + }, { + fieldLabel: _('role'), + description: MODx.expandHelp ? '' : _('user_group_user_add_role_desc'), + name: 'role', + hiddenName: 'role', + xtype: 'modx-combo-role', + allowBlank: false, + anchor: '100%' + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('user_group_user_add_role_desc'), + cls: 'desc-under' + }, { + name: 'usergroup', + xtype: 'hidden' }] }); - MODx.window.AddUserToUserGroup.superclass.constructor.call(this,config); + MODx.window.AddUserToUserGroup.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.AddUserToUserGroup,MODx.Window); -Ext.reg('modx-window-user-group-adduser',MODx.window.AddUserToUserGroup); +Ext.extend(MODx.window.AddUserToUserGroup, MODx.Window); +Ext.reg('modx-window-user-group-adduser', MODx.window.AddUserToUserGroup); diff --git a/manager/assets/modext/widgets/source/modx.panel.source.js b/manager/assets/modext/widgets/source/modx.panel.source.js index cec222890e8..396151653e1 100644 --- a/manager/assets/modext/widgets/source/modx.panel.source.js +++ b/manager/assets/modext/widgets/source/modx.panel.source.js @@ -4,223 +4,252 @@ * @param {Object} config An object of configuration properties * @xtype modx-panel-source */ -MODx.panel.Source = function(config) { - config = config || {}; - Ext.applyIf(config,{ - id: 'modx-panel-source' - ,url: MODx.config.connector_url - ,baseParams: { +MODx.panel.Source = function(config = {}) { + let generalIntro = {}; + if (config.record.reserved) { + generalIntro = { + xtype: 'box', + cls: 'panel-desc', + html: _('source_reserved_general_desc') + }; + } + Ext.applyIf(config, { + id: 'modx-panel-source', + url: MODx.config.connector_url, + baseParams: { action: 'Source/Update' - } - ,defaults: { collapsible: false ,autoHeight: true } - ,cls: 'container form-with-labels' - ,items: [this.getPageHeader(config),{ - xtype: 'modx-tabs' - ,defaults: { - autoHeight: true - ,border: true - ,bodyCssClass: 'tab-panel-wrapper' - } - ,id: 'modx-source-tabs' - ,forceLayout: true - ,deferredRender: false - ,stateful: true - ,stateId: 'modx-source-tabpanel' - ,stateEvents: ['tabchange'] - ,getState:function() { - return {activeTab:this.items.indexOf(this.getActiveTab())}; - } - ,items: [{ - title: _('general_information') - ,defaults: { border: false, msgTarget: 'side' } - ,layout: 'form' - ,id: 'modx-source-form' - ,labelWidth: 150 - ,items: [{ - xtype: 'panel' - ,border: false - ,cls: 'main-wrapper' - ,layout: 'form' - ,labelAlign: 'top' - ,items: [{ - layout: 'column' - ,border: false - ,defaults: { - layout: 'form' - ,labelAlign: 'top' - ,anchor: '100%' - ,border: false - } - ,items: [{ - columnWidth: .65 - ,cls: 'main-content' - ,items: [{ - xtype: 'hidden' - ,name: 'id' - ,id: 'modx-source-id' - ,value: config.record.id - },{ - name: 'name' - ,id: 'modx-source-name' - ,xtype: 'textfield' - ,fieldLabel: _('name') - ,description: MODx.expandHelp ? '' : _('source_name_desc') - ,allowBlank: false - ,enableKeyEvents: true - ,anchor: '100%' - ,listeners: { - 'keyup': {scope:this,fn:function(f,e) { - Ext.getCmp('modx-header-breadcrumbs').updateHeader(Ext.util.Format.htmlEncode(f.getValue())); - }} + }, + defaults: { + collapsible: false, + autoHeight: true + }, + cls: 'container form-with-labels', + items: [this.getPageHeader(config), { + xtype: 'modx-tabs', + defaults: { + autoHeight: true, + border: true, + bodyCssClass: 'tab-panel-wrapper' + }, + id: 'modx-source-tabs', + forceLayout: true, + deferredRender: false, + stateful: true, + stateId: 'modx-source-tabpanel', + stateEvents: ['tabchange'], + getState: function() { + return { + activeTab: this.items.indexOf(this.getActiveTab()) + }; + }, + items: [{ + title: _('general_information'), + layout: 'form', + id: 'modx-source-form', + items: [generalIntro, { + xtype: 'panel', + border: false, + cls: 'main-wrapper', + layout: 'form', + labelAlign: 'top', + items: [{ + layout: 'column', + border: false, + defaults: { + layout: 'form', + labelAlign: 'top', + labelSeparator: '' + }, + items: [{ + columnWidth: 0.65, + defaults: { + anchor: '100%', + msgTarget: 'under' + }, + cls: 'main-content', + items: [{ + xtype: 'hidden', + name: 'id', + id: 'modx-source-id', + value: config.record.id + }, { + xtype: config.record.reserved ? 'statictextfield' : 'textfield', + name: 'name', + id: 'modx-source-name', + fieldLabel: _('name'), + description: MODx.expandHelp ? '' : _('source_name_desc'), + allowBlank: false, + enableKeyEvents: true, + listeners: { + keyup: { + scope: this, + fn: function(field, e) { + Ext.getCmp('modx-header-breadcrumbs').updateHeader(Ext.util.Format.htmlEncode(field.getValue())); + } + } } - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-source-name' - ,html: _('source_name_desc') - ,cls: 'desc-under' - },{ - name: 'description' - ,id: 'modx-source-description' - ,xtype: 'textarea' - ,fieldLabel: _('description') - ,description: MODx.expandHelp ? '' : _('source_description_desc') - ,anchor: '100%' - ,grow: true - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-source-description' - ,html: _('source_description_desc') - ,cls: 'desc-under' + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('source_name_desc'), + cls: 'desc-under' + }, { + xtype: config.record.reserved ? 'statictextarea' : 'textarea', + name: 'description', + id: 'modx-source-description', + fieldLabel: _('description'), + description: MODx.expandHelp ? '' : _('source_description_desc'), + grow: true + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('source_description_desc'), + cls: 'desc-under' }] - },{ - columnWidth: .35 - ,cls: 'main-content' - ,items: [{ - name: 'class_key' - ,hiddenName: 'class_key' - ,id: 'modx-source-type' - ,xtype: 'modx-combo-source-type' - ,fieldLabel: _('source_type') - ,description: MODx.expandHelp ? '' : _('source_type_desc') - ,anchor: '100%' - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-source-type' - ,html: _('source_type_desc') - ,cls: 'desc-under' + }, { + columnWidth: 0.35, + defaults: { + anchor: '100%', + msgTarget: 'under' + }, + cls: 'main-content', + items: [{ + disabled: config.record.reserved, + xtype: 'modx-combo-source-type', + name: 'class_key', + hiddenName: 'class_key', + id: 'modx-source-type', + fieldLabel: _('source_type'), + description: MODx.expandHelp ? '' : _('source_type_desc') + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('source_type_desc'), + cls: 'desc-under' }] }] }] - },{ - html: '

    '+_('source_properties.intro_msg')+'

    ' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-source-properties' - ,preventRender: true - ,source: config.record.id - ,defaultProperties: config.defaultProperties - ,autoHeight: true - ,cls: 'main-wrapper' - ,listeners: { - 'afterRemoveRow': {fn:this.markDirty,scope:this} + }, { + html: `

    ${_('source_properties.intro_msg')}

    `, + xtype: 'modx-description' + }, { + xtype: 'modx-grid-source-properties', + preventRender: true, + source: config.record.id, + defaultProperties: config.defaultProperties, + autoHeight: true, + cls: 'main-wrapper', + listeners: { + afterRemoveRow: { fn: this.markDirty, scope: this } } }] - },{ - title: _('access') - ,hideMode: 'offsets' - ,items: [{ - html: '

    '+_('source.access.intro_msg')+'

    ' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-source-access' - ,preventRender: true - ,source: config.record.id - ,autoHeight: true - ,cls: 'main-wrapper' - ,listeners: { - 'afterRemoveRow': {fn:this.markDirty,scope:this} - ,'updateRole': {fn:this.markDirty,scope:this} - ,'addMember': {fn:this.markDirty,scope:this} + }, { + title: _('access'), + hideMode: 'offsets', + items: [{ + html: `

    ${_('source.access.intro_msg')}

    `, + xtype: 'modx-description' + }, { + xtype: 'modx-grid-source-access', + preventRender: true, + source: config.record.id, + autoHeight: true, + cls: 'main-wrapper', + listeners: { + afterRemoveRow: { fn: this.markDirty, scope: this }, + updateRole: { fn: this.markDirty, scope: this }, + addMember: { fn: this.markDirty, scope: this } } }] }] - }] - ,listeners: { - 'setup': {fn:this.setup,scope:this} - ,'success': {fn:this.success,scope:this} - ,'beforeSubmit': {fn:this.beforeSubmit,scope:this} + }], + listeners: { + setup: { fn: this.setup, scope: this }, + success: { fn: this.success, scope: this }, + beforeSubmit: { fn: this.beforeSubmit, scope: this } } }); - MODx.panel.Source.superclass.constructor.call(this,config); + MODx.panel.Source.superclass.constructor.call(this, config); }; -Ext.extend(MODx.panel.Source,MODx.FormPanel,{ - initialized: false +Ext.extend(MODx.panel.Source, MODx.FormPanel, { + initialized: false, - ,setup: function() { - if (this.initialized) { return false; } + setup: function() { + if (this.initialized) { + return false; + } if (Ext.isEmpty(this.config.record.id)) { this.fireEvent('ready'); return false; } + this.getForm().setValues(this.config.record); + /* The component rendering is deferred since we are not using renderTo */ Ext.getCmp('modx-header-breadcrumbs').updateHeader(Ext.util.Format.htmlEncode(this.config.record.name)); - var g,d; if (!Ext.isEmpty(this.config.record.properties)) { - g = Ext.getCmp('modx-grid-source-properties'); - if (g) { - g.defaultProperties = this.config.defaultProperties; - g.getStore().loadData(this.config.record.properties); + const propsGrid = Ext.getCmp('modx-grid-source-properties'); + if (propsGrid) { + propsGrid.defaultProperties = this.config.defaultProperties; + propsGrid.getStore().loadData(this.config.record.properties); } } if (!Ext.isEmpty(this.config.record.access)) { - d = this.config.record.access; - g = Ext.getCmp('modx-grid-source-access'); - if (g) { - d = Ext.decode(d); - if (!Ext.isEmpty(d)) { - g.defaultProperties = d; - g.getStore().loadData(d); + let { access } = this.config.record; + const accessGrid = Ext.getCmp('modx-grid-source-access'); + if (accessGrid) { + access = Ext.decode(access); + if (!Ext.isEmpty(access)) { + accessGrid.defaultProperties = access; + accessGrid.getStore().loadData(access); } } } - this.fireEvent('ready',this.config.record); + this.fireEvent('ready', this.config.record); MODx.fireEvent('ready'); this.initialized = true; - } + }, - ,beforeSubmit: function(o) { - var bp = {}; - var sp = Ext.getCmp('modx-grid-source-properties'); - if (sp) { - bp.properties = sp.encode(); + beforeSubmit: function(o) { + const + sourceData = {}, + propsGrid = Ext.getCmp('modx-grid-source-properties'), + accessGrid = Ext.getCmp('modx-grid-source-access') + ; + if (propsGrid) { + sourceData.properties = propsGrid.encode(); } - var ap = Ext.getCmp('modx-grid-source-access'); - if (ap) { - bp.access = ap.encode(); + if (accessGrid) { + sourceData.access = accessGrid.encode(); } - Ext.apply(o.form.baseParams,bp); - } + Ext.apply(o.form.baseParams, sourceData); + }, - ,success: function(o) { + success: function(o) { if (Ext.isEmpty(this.config.record) || Ext.isEmpty(this.config.record.id)) { - MODx.loadPage('source/update', 'id='+o.result.object.id); + MODx.loadPage('source/update', `id=${o.result.object.id}`); } else { + const + propsGrid = Ext.getCmp('modx-grid-source-properties'), + accessGrid = Ext.getCmp('modx-grid-source-access') + ; Ext.getCmp('modx-abtn-save').setDisabled(false); - var wg = Ext.getCmp('modx-grid-source-properties'); - if (wg) { wg.getStore().commitChanges(); } - var ag = Ext.getCmp('modx-grid-source-access'); - if (ag) { ag.getStore().commitChanges(); } + if (propsGrid) { + propsGrid.getStore().commitChanges(); + } + if (accessGrid) { + accessGrid.getStore().commitChanges(); + } } - } + }, - ,getPageHeader: function(config) { + getPageHeader: function(config) { return MODx.util.getHeaderBreadCrumbs('modx-source-header', [{ text: _('sources'), href: MODx.getPage('source') }]); } }); -Ext.reg('modx-panel-source',MODx.panel.Source); +Ext.reg('modx-panel-source', MODx.panel.Source); diff --git a/manager/assets/modext/widgets/source/modx.panel.sources.js b/manager/assets/modext/widgets/source/modx.panel.sources.js index 7cce9d4e9a3..11ccc6c4818 100644 --- a/manager/assets/modext/widgets/source/modx.panel.sources.js +++ b/manager/assets/modext/widgets/source/modx.panel.sources.js @@ -6,45 +6,47 @@ * @param {Object} config An object of configuration options * @xtype modx-panel-sources */ -MODx.panel.Sources = function(config) { - config = config || {}; - Ext.applyIf(config,{ - id: 'modx-panel-sources' - ,cls: 'container' - ,bodyStyle: '' - ,defaults: { collapsible: false ,autoHeight: true } - ,items: [{ - html: _('sources') - ,id: 'modx-sources-header' - ,xtype: 'modx-header' - },MODx.getPageStructure([{ - title: _('sources') - ,layout: 'form' - ,items: [{ - html: '

    '+_('sources.intro_msg')+'

    ' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-sources' - ,cls: 'main-wrapper' - ,preventRender: true +MODx.panel.Sources = function(config = {}) { + Ext.applyIf(config, { + id: 'modx-panel-sources', + cls: 'container', + bodyStyle: '', + defaults: { + collapsible: false, + autoHeight: true + }, + items: [{ + html: _('sources'), + id: 'modx-sources-header', + xtype: 'modx-header' + }, MODx.getPageStructure([{ + title: _('sources'), + layout: 'form', + items: [{ + html: `

    ${_('sources.intro_msg')}

    `, + xtype: 'modx-description' + }, { + xtype: 'modx-grid-sources', + cls: 'main-wrapper', + preventRender: true }] - },{ - layout: 'form' - ,title: _('source_types') - ,items: [{ - html: '

    '+_('source_types.intro_msg')+'

    ' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-source-types' - ,cls: 'main-wrapper' - ,preventRender: true + }, { + layout: 'form', + title: _('source_types'), + items: [{ + html: `

    ${_('source_types.intro_msg')}

    `, + xtype: 'modx-description' + }, { + xtype: 'modx-grid-source-types', + cls: 'main-wrapper', + preventRender: true }] }])] }); - MODx.panel.Sources.superclass.constructor.call(this,config); + MODx.panel.Sources.superclass.constructor.call(this, config); }; -Ext.extend(MODx.panel.Sources,MODx.FormPanel); -Ext.reg('modx-panel-sources',MODx.panel.Sources); +Ext.extend(MODx.panel.Sources, MODx.FormPanel); +Ext.reg('modx-panel-sources', MODx.panel.Sources); /** * Loads a grid of Sources. @@ -56,168 +58,167 @@ Ext.reg('modx-panel-sources',MODx.panel.Sources); */ MODx.grid.Sources = function(config = {}) { this.sm = new Ext.grid.CheckboxSelectionModel(); - Ext.applyIf(config,{ - url: MODx.config.connector_url - ,baseParams: { + + Ext.applyIf(config, { + id: 'modx-grid-sources', + url: MODx.config.connector_url, + baseParams: { action: 'Source/GetList' - } - ,fields: [ + }, + fields: [ 'id', 'name', 'description', 'class_key', - 'cls' - ] - ,paging: true - ,autosave: true - ,save_action: 'Source/UpdateFromGrid' - ,remoteSort: true - ,sm: this.sm - ,columns: [this.sm,{ - header: _('id') - ,dataIndex: 'id' - ,width: 50 - ,sortable: true - },{ - header: _('name') - ,dataIndex: 'name' - ,width: 150 - ,sortable: true - ,editor: { xtype: 'textfield' ,allowBlank: false } - ,renderer: { fn: function(v,md,record) { - return this.renderLink(v, { - href: '?a=source/update&id=' + record.data.id - }); - }, scope: this } - },{ - header: _('description') - ,dataIndex: 'description' - ,width: 300 - ,sortable: false - ,editor: { xtype: 'textarea' } - ,renderer: Ext.util.Format.htmlEncode - }] - ,tbar: [ - { - text: _('create') - ,handler: { - xtype: 'modx-window-source-create', - blankValues: true + 'creator' + ], + paging: true, + autosave: true, + save_action: 'Source/UpdateFromGrid', + remoteSort: true, + sm: this.sm, + stateful: true, + stateId: 'modx-grid-sources-state', + columns: [this.sm, { + header: _('id'), + dataIndex: 'id', + width: 50, + sortable: true + }, { + header: _('name'), + dataIndex: 'name', + width: 150, + sortable: true, + editor: { + xtype: 'textfield', + allowBlank: false, + blankText: _('source_err_ns_name'), + validationEvent: 'change', + validator: function(value) { + const grid = Ext.getCmp('modx-grid-sources'), + reserved = this.gridEditor.record.json.reserved.name + ; + if (grid.valueIsReserved(reserved, value)) { + const msg = _('source_err_name_reserved', { reservedName: value }); + Ext.Msg.alert(_('error'), msg); + return false; + } + return true; } - ,cls:'primary-button' - },{ - text: _('bulk_actions') - ,menu: [{ - text: _('selected_remove') - ,handler: this.removeSelected - ,scope: this - }] }, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record, [record.json.isProtected]); + return this.userCanEditRecord(record) + ? this.renderLink(value, { + href: `?a=source/update&id=${record.data.id}`, + title: _('source_edit') + }) + : value + ; + }, + scope: this + } + }, { + header: _('description'), + dataIndex: 'description', + width: 300, + editor: { + xtype: 'textarea' + }, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record, [record.json.isProtected]); + return value; + }, + scope: this + } + }, + this.getCreatorColumnConfig('source') + ], + tbar: [ + this.getCreateButton('source', { + xtype: 'modx-window-source-create', + blankValues: true + }), + this.getBulkActionsButton('source', 'Source/RemoveMultiple'), '->', this.getQueryFilterField(), this.getClearFiltersButton() - ] + ], + viewConfig: this.getViewConfig() }); - MODx.grid.Sources.superclass.constructor.call(this,config); -}; -Ext.extend(MODx.grid.Sources,MODx.grid.Grid,{ - getMenu: function() { - var r = this.getSelectionModel().getSelected(); - var p = r.data.cls; + MODx.grid.Sources.superclass.constructor.call(this, config); - var m = []; - if (this.getSelectionModel().getCount() > 1) { - m.push({ - text: _('selected_remove') - ,handler: this.removeSelected - ,scope: this - }); - } else { - if (p.indexOf('pupdate') != -1) { - m.push({ - text: _('edit') - ,handler: this.updateSource - }); - } - if (p.indexOf('pduplicate') != -1) { - m.push({ - text: _('duplicate') - ,handler: this.duplicateSource - }); - } - if (p.indexOf('premove') != -1 && r.data.id != 1 && r.data.name != 'Filesystem') { - if (m.length > 0) m.push('-'); - m.push({ - text: _('delete') - ,handler: this.removeSource - }); - } - } - if (m.length > 0) { - this.addContextMenuItem(m); - } - } - - ,createSource: function() { - MODx.loadPage('system/source/create'); - } + this.gridMenuActions = ['edit', 'delete', 'duplicate']; - ,updateSource: function() { - MODx.loadPage('source/update', 'id='+this.menu.record.id); - } + this.setUserCanEdit(['source_save', 'source_edit']); + this.setUserCanCreate(['source_save']); + this.setUserCanDelete(['source_delete']); + this.setShowActionsMenu(); - ,duplicateSource: function(btn,e) { - MODx.Ajax.request({ - url: this.config.url - ,params: { - action: 'Source/Duplicate' - ,id: this.menu.record.id + this.on({ + beforeedit: function(e) { + if (e.record.json.isProtected || !this.userCanEditRecord(e.record)) { + return false; } - ,listeners: { - 'success': {fn:this.refresh,scope:this} - } - }); - } + } + }); +}; +Ext.extend(MODx.grid.Sources, MODx.grid.Grid, { - ,removeSource: function() { - MODx.msg.confirm({ - title: _('delete') - ,text: _('source_remove_confirm') - ,url: this.config.url - ,params: { - action: 'Source/Remove' - ,id: this.menu.record.id - } - ,listeners: { - 'success': {fn:this.refresh,scope:this} + getMenu: function() { + const + record = this.getSelectionModel().getSelected(), + menu = [] + ; + if (this.userCanEdit && this.userCanEditRecord(record)) { + menu.push({ + text: _('edit'), + handler: this.updateSource + }); + } + if (this.userCanCreate && this.userCanDuplicateRecord(record)) { + menu.push({ + text: _('duplicate'), + handler: this.duplicateSource + }); + } + if (this.userCanDelete && this.userCanDeleteRecord(record)) { + if (menu.length > 0) { + menu.push('-'); } - }); - } + menu.push({ + text: _('delete'), + handler: this.confirm.createDelegate(this, ['Source/Remove', 'source_remove_confirm']) + }); + } + return menu; + }, - ,removeSelected: function() { - var cs = this.getSelectedAsList(); - if (cs === false) return false; + updateSource: function() { + MODx.loadPage('source/update', `id=${this.menu.record.id}`); + }, - MODx.msg.confirm({ - title: _('selected_remove') - ,text: _('source_remove_multiple_confirm') - ,url: this.config.url - ,params: { - action: 'Source/RemoveMultiple' - ,sources: cs - } - ,listeners: { - 'success': {fn:function(r) { - this.getSelectionModel().clearSelections(true); - this.refresh(); - },scope:this} + duplicateSource: function(btn, e) { + MODx.Ajax.request({ + url: this.config.url, + params: { + action: 'Source/Duplicate', + id: this.menu.record.id + }, + listeners: { + success: { + fn: this.refresh, + scope: this + } } }); - return true; } - }); -Ext.reg('modx-grid-sources',MODx.grid.Sources); +Ext.reg('modx-grid-sources', MODx.grid.Sources); /** * Generates the create Source window. @@ -228,68 +229,69 @@ Ext.reg('modx-grid-sources',MODx.grid.Sources); * @xtype modx-window-source-create */ MODx.window.CreateSource = function(config = {}) { - Ext.applyIf(config,{ - title: _('create') - ,url: MODx.config.connector_url - ,autoHeight: true - ,action: 'Source/Create' - ,fields: [{ - xtype: 'textfield' - ,fieldLabel: _('name') - ,name: 'name' - ,anchor: '100%' - ,allowBlank: false - },{ - xtype: 'textarea' - ,fieldLabel: _('description') - ,name: 'description' - ,anchor: '100%' - ,grow: true - },{ - name: 'class_key' - ,hiddenName: 'class_key' - ,xtype: 'modx-combo-source-type' - ,fieldLabel: _('source_type') - ,anchor: '100%' - ,allowBlank: false - ,value: MODx.config.default_media_source_type - }] - ,keys: [] + Ext.applyIf(config, { + title: _('create'), + url: MODx.config.connector_url, + autoHeight: true, + action: 'Source/Create', + formDefaults: { + anchor: '100%', + validationEvent: 'change', + validateOnBlur: false + }, + fields: [{ + xtype: 'textfield', + fieldLabel: _('name'), + name: 'name', + allowBlank: false + }, { + xtype: 'textarea', + fieldLabel: _('description'), + name: 'description', + grow: true + }, { + name: 'class_key', + xtype: 'modx-combo-source-type', + fieldLabel: _('source_type'), + allowBlank: false, + value: MODx.config.default_media_source_type + }], + keys: [] }); - MODx.window.CreateSource.superclass.constructor.call(this,config); + MODx.window.CreateSource.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.CreateSource,MODx.Window); -Ext.reg('modx-window-source-create',MODx.window.CreateSource); +Ext.extend(MODx.window.CreateSource, MODx.Window); +Ext.reg('modx-window-source-create', MODx.window.CreateSource); MODx.grid.SourceTypes = function(config = {}) { - Ext.applyIf(config,{ - url: MODx.config.connector_url - ,baseParams: { + Ext.applyIf(config, { + url: MODx.config.connector_url, + baseParams: { action: 'Source/Type/GetList' - } - ,fields: [ + }, + fields: [ 'class', 'name', 'description' - ] - ,showActionsColumn: false - ,paging: true - ,remoteSort: true - ,columns: [{ - header: _('name') - ,dataIndex: 'name' - ,width: 150 - ,sortable: true - ,renderer: Ext.util.Format.htmlEncode - },{ - header: _('description') - ,dataIndex: 'description' - ,width: 300 - ,sortable: false - ,renderer: Ext.util.Format.htmlEncode + ], + showActionsColumn: false, + paging: true, + remoteSort: true, + columns: [{ + header: _('name'), + dataIndex: 'name', + width: 150, + sortable: true, + renderer: Ext.util.Format.htmlEncode + }, { + header: _('description'), + dataIndex: 'description', + width: 300, + sortable: false, + renderer: Ext.util.Format.htmlEncode }] }); - MODx.grid.SourceTypes.superclass.constructor.call(this,config); + MODx.grid.SourceTypes.superclass.constructor.call(this, config); }; -Ext.extend(MODx.grid.SourceTypes,MODx.grid.Grid); -Ext.reg('modx-grid-source-types',MODx.grid.SourceTypes); +Ext.extend(MODx.grid.SourceTypes, MODx.grid.Grid); +Ext.reg('modx-grid-source-types', MODx.grid.SourceTypes); diff --git a/manager/assets/modext/widgets/system/modx.grid.content.type.js b/manager/assets/modext/widgets/system/modx.grid.content.type.js index 16bda8b568a..289f1672ca9 100644 --- a/manager/assets/modext/widgets/system/modx.grid.content.type.js +++ b/manager/assets/modext/widgets/system/modx.grid.content.type.js @@ -4,35 +4,37 @@ * @param {Object} config An object of options. * @xtype modx-panel-content-type */ -MODx.panel.ContentType = function(config) { - config = config || {}; - Ext.applyIf(config,{ - id: 'modx-panel-content-type' - ,cls: 'container' - ,url: MODx.config.connector_url - ,defaults: { collapsible: false ,autoHeight: true } - ,items: [{ - html: _('content_types') - ,xtype: 'modx-header' - },MODx.getPageStructure([{ - title: _('content_types') - ,layout: 'form' - ,itemId: 'form' - ,items: [{ - html: '

    '+_('content_type_desc')+'

    ' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-content-type' - ,itemId: 'grid' - ,cls:'main-wrapper' - ,preventRender: true +MODx.panel.ContentType = function(config = {}) { + Ext.applyIf(config, { + id: 'modx-panel-content-type', + cls: 'container', + url: MODx.config.connector_url, + defaults: { + collapsible: false, + autoHeight: true + }, + items: [{ + html: _('content_types'), + xtype: 'modx-header' + }, MODx.getPageStructure([{ + title: _('content_types'), + layout: 'form', + itemId: 'form', + items: [{ + html: `

    ${_('content_type_desc')}

    `, + xtype: 'modx-description' + }, { + xtype: 'modx-grid-content-type', + itemId: 'grid', + cls: 'main-wrapper', + preventRender: true }] }])] }); - MODx.panel.ContentType.superclass.constructor.call(this,config); + MODx.panel.ContentType.superclass.constructor.call(this, config); }; -Ext.extend(MODx.panel.ContentType,MODx.FormPanel,{}); -Ext.reg('modx-panel-content-type',MODx.panel.ContentType); +Ext.extend(MODx.panel.ContentType, MODx.FormPanel, {}); +Ext.reg('modx-panel-content-type', MODx.panel.ContentType); /** * Loads a grid of content types @@ -42,115 +44,158 @@ Ext.reg('modx-panel-content-type',MODx.panel.ContentType); * @param {Object} config An object of options. * @xtype modx-grid-contenttype */ -MODx.grid.ContentType = function(config) { - config = config || {}; - var binaryColumn = new Ext.ux.grid.CheckColumn({ - header: _('binary') - ,dataIndex: 'binary' - ,width: 40 - ,sortable: true +MODx.grid.ContentType = function(config = {}) { + const binaryColumn = new Ext.ux.grid.CheckColumn({ + header: _('binary'), + dataIndex: 'binary', + width: 40, + sortable: true }); - - Ext.applyIf(config,{ - url: MODx.config.connector_url - ,baseParams: { + Ext.applyIf(config, { + url: MODx.config.connector_url, + baseParams: { action: 'System/ContentType/GetList' + }, + autosave: true, + save_action: 'System/ContentType/UpdateFromGrid', + fields: [ + 'id', + 'name', + 'mime_type', + 'file_extensions', + 'icon', + 'headers', + 'binary', + 'description', + 'creator' + ], + paging: true, + remoteSort: true, + plugins: binaryColumn, + columns: [ + { + header: _('id'), + dataIndex: 'id', + width: 50, + sortable: true + }, { + header: _('name'), + dataIndex: 'name', + sortable: true, + editor: { xtype: 'textfield' }, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record, [record.json.isProtected]); + return value; + }, + scope: this + } + }, { + header: _('description'), + dataIndex: 'description', + width: 200, + editor: { xtype: 'textfield' }, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record, [record.json.isProtected]); + return value; + }, + scope: this + } + }, { + header: _('mime_type'), + dataIndex: 'mime_type', + width: 80, + sortable: true, + editor: { xtype: 'textfield' }, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record, [record.json.isProtected]); + return value; + }, + scope: this + } + }, { + header: _('file_extensions'), + dataIndex: 'file_extensions', + sortable: true, + editor: { xtype: 'textfield' } + }, { + header: _('icon'), + dataIndex: 'icon', + sortable: false, + editor: { xtype: 'textfield' }, + renderer: this.renderIconField.createDelegate(this, [this], true) + }, + binaryColumn, + { + dataIndex: 'headers', + hidden: true + }, + this.getCreatorColumnConfig('content_types') + ], + tbar: [ + this.getCreateButton('content_types', 'newContentType') + ] + }); + MODx.grid.ContentType.superclass.constructor.call(this, config); + + this.gridMenuActions = ['edit', 'delete']; + + // Note there are currently no action-specific permissions for Content Types + this.setUserCanEdit(['content_types']); + this.setUserCanCreate(['content_types']); + this.setUserCanDelete(['content_types']); + this.setShowActionsMenu(); + + this.on({ + beforerender: function(grid) { + grid.view = new Ext.grid.GridView(grid.getViewConfig(false)); + }, + beforeedit: function(e) { + const skipProtectionFieldList = ['file_extensions', 'icon']; + if ((e.record.json.isProtected && !skipProtectionFieldList.includes(e.field)) || !this.userCanEditRecord(e.record)) { + return false; + } } - ,autosave: true - ,save_action: 'System/ContentType/UpdateFromGrid' - ,fields: ['id','name','mime_type','file_extensions','icon','headers','binary','description'] - ,paging: true - ,remoteSort: true - ,plugins: binaryColumn - ,columns: [{ - header: _('id') - ,dataIndex: 'id' - ,width: 50 - ,sortable: true - },{ - header: _('name') - ,dataIndex: 'name' - ,sortable: true - ,editor: { xtype: 'textfield' } - },{ - header: _('description') - ,dataIndex: 'description' - ,editor: { xtype: 'textfield' } - ,width: 200 - },{ - header: _('mime_type') - ,dataIndex: 'mime_type' - ,sortable: true - ,editor: { xtype: 'textfield' } - ,width: 80 - },{ - header: _('file_extensions') - ,dataIndex: 'file_extensions' - ,sortable: true - ,editor: { xtype: 'textfield' } - },{ - header: _('icon') - ,dataIndex: 'icon' - ,sortable: false - ,editor: { xtype: 'textfield' } - ,renderer: this.renderIconField.createDelegate(this,[this],true) - }, binaryColumn, { - dataIndex: 'headers' - ,hidden: true - }] - ,tbar: [{ - text: _('create') - ,cls: 'primary-button' - ,handler: this.newContentType - ,scope: this - }] }); - MODx.grid.ContentType.superclass.constructor.call(this,config); }; -Ext.extend(MODx.grid.ContentType,MODx.grid.Grid,{ +Ext.extend(MODx.grid.ContentType, MODx.grid.Grid, { getMenu: function() { - var m = []; - m.push({ - text: _('edit') - ,handler: function(btn, e) { - var window = new MODx.window.CreateContentType({ - record: this.menu.record - ,title: _('edit') - ,action: 'System/ContentType/Update' - ,listeners: { - success: { - fn: this.refresh - ,scope: this - } - } - }); - window.setRecord(this.menu.record); - window.show(e.target); - } - ,scope: this - }); - m.push({ - text: _('delete') - ,handler: this.confirm.createDelegate(this,['System/ContentType/Remove',_('content_type_remove_confirm')]) - }); + const + record = this.getSelectionModel().getSelected(), + menu = [] + ; + if (this.userCanEdit && this.userCanEditRecord(record)) { + menu.push({ + text: _('edit'), + handler: this.updateContentType.createDelegate(this, [record], true) + }); + } + if (this.userCanDelete && this.userCanDeleteRecord(record)) { + menu.push({ + text: _('delete'), + handler: this.confirm.createDelegate(this, ['System/ContentType/Remove', _('content_type_remove_confirm')]) + }); + } + return menu; + }, - return m; - } + newContentType: function(btn, e) { + const window = new MODx.window.CreateContentType({ grid: this }); + window.show(e.target); + }, - ,newContentType: function(btn, e) { - var window = new MODx.window.CreateContentType({ - listeners: { - success: { - fn: this.refresh - ,scope: this - } - } - }); + updateContentType: function(btn, e, record) { + const window = new MODx.window.UpdateContentType({ record: record, grid: this }); window.show(e.target); - } + }, - ,renderIconField: function (v, md, rec) { - return new Ext.XTemplate('   {icon:htmlEncode}').apply(rec.data); + renderIconField: function(value, metaData, record) { + return new Ext.XTemplate('   {icon:htmlEncode}').apply(record.data); } }); Ext.reg('modx-grid-content-type', MODx.grid.ContentType); @@ -163,134 +208,139 @@ Ext.reg('modx-grid-content-type', MODx.grid.ContentType); * @param {Object} config An object of options. * @xtype modx-window-content-type-create */ -MODx.window.CreateContentType = function(config) { - config = config || {}; - this.ident = config.ident || 'modx-cct'+Ext.id(); - Ext.applyIf(config,{ - title: _('create') - ,width: 600 - ,url: MODx.config.connector_url - ,action: 'System/ContentType/Create' - ,bwrapCssClass: 'x-window-with-tabs' - ,fields: [{ - xtype: 'modx-tabs' - ,items: [{ - title: _('content_type_main_tab') - ,layout: 'form' - ,items: [{ - layout: 'column' - ,border: false - ,defaults: { - layout: 'form' - ,labelAlign: 'top' - ,anchor: '100%' - ,border: false - } - ,items: [{ - columnWidth: .6 - ,defaults: { - msgTarget: 'under' - } - ,items: [{ - xtype: 'hidden' - ,name: 'id' - },{ - fieldLabel: _('name') - ,name: 'name' - ,id: this.ident+'-name' - ,xtype: 'textfield' - ,anchor: '100%' - ,allowBlank: false - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: this.ident+'-name' - ,html: _('name_desc') - ,cls: 'desc-under' - },{ - fieldLabel: _('mime_type') - ,description: MODx.expandHelp ? '' : _('mime_type_desc') - ,name: 'mime_type' - ,id: this.ident+'-mime-type' - ,xtype: 'textfield' - ,anchor: '100%' - ,allowBlank: false - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: this.ident+'-mime-type' - ,html: _('mime_type_desc') - ,cls: 'desc-under' +MODx.window.CreateContentType = function(config = {}) { + Ext.applyIf(config, { + title: _('create'), + width: 600, + url: MODx.config.connector_url, + action: 'System/ContentType/Create', + bwrapCssClass: 'x-window-with-tabs', + fields: [{ + xtype: 'modx-tabs', + items: [{ + title: _('content_type_main_tab'), + layout: 'form', + items: [{ + xtype: 'modx-description', + id: 'modx-content-type-general-desc', + hidden: !config.isUpdate || !config.record?.json?.isProtected, + html: _('content_type_reserved_general_desc') + }, { + layout: 'column', + border: false, + defaults: { + layout: 'form', + labelSeparator: '' + }, + items: [{ + columnWidth: 0.6, + defaults: { + msgTarget: 'under', + anchor: '100%', + validationEvent: 'change', + validateOnBlur: false + }, + items: [{ + xtype: 'hidden', + name: 'id' + }, { + fieldLabel: _('name'), + name: 'name', + xtype: 'textfield', + allowBlank: false, + readOnly: (config.isUpdate && config.record.json?.isProtected) || false + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('name_desc'), + cls: 'desc-under' + }, { + fieldLabel: _('mime_type'), + description: MODx.expandHelp ? '' : _('mime_type_desc'), + name: 'mime_type', + xtype: 'textfield', + allowBlank: false, + readOnly: (config.isUpdate && config.record.json?.isProtected) || false + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('mime_type_desc'), + cls: 'desc-under' }] - },{ - columnWidth: .4 - ,defaults: { - msgTarget: 'under' - } - ,items: [{ - fieldLabel: _('icon') - ,description: MODx.expandHelp ? '' : _('icon_desc') - ,name: 'icon' - ,id: this.ident+'-icon' - ,xtype: 'textfield' - ,anchor: '100%' - ,allowBlank: true - },{ - fieldLabel: _('file_extensions') - ,description: MODx.expandHelp ? '' : _('file_extensions_desc') - ,name: 'file_extensions' - ,id: this.ident+'-file-extensions' - ,xtype: 'textfield' - ,anchor: '100%' - ,allowBlank: true - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: this.ident+'-file-extensions' - ,html: _('file_extensions_desc') - ,cls: 'desc-under' + }, { + columnWidth: 0.4, + defaults: { + msgTarget: 'under', + anchor: '100%', + validationEvent: 'change', + validateOnBlur: false + }, + items: [{ + fieldLabel: _('icon'), + description: MODx.expandHelp ? '' : _('icon_desc'), + name: 'icon', + xtype: 'textfield' + }, { + fieldLabel: _('file_extensions'), + description: MODx.expandHelp ? '' : _('file_extensions_desc'), + name: 'file_extensions', + xtype: 'textfield' + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('file_extensions_desc'), + cls: 'desc-under' }] }] - },{ - xtype: 'xcheckbox' - ,hideLabel: true - ,boxLabel: _('binary_desc') - ,name: 'binary' - ,hiddenName: 'binary' - ,id: this.ident+'-binary' - ,anchor: '100%' - },{ - fieldLabel: _('description') - ,name: 'description' - ,id: 'modx-'+this.ident+'-description' - ,xtype: 'textarea' - ,anchor: '100%' - ,grow: true - },{ - xtype: 'hidden' - ,name: 'headers' + }, { + xtype: 'xcheckbox', + hideLabel: true, + boxLabel: _('binary_desc'), + name: 'binary', + hiddenName: 'binary' + }, { + fieldLabel: _('description'), + labelSeparator: '', + name: 'description', + xtype: 'textarea', + anchor: '100%', + grow: true, + readOnly: (config.isUpdate && config.record.json?.isProtected) || false + }, { + xtype: 'hidden', + name: 'headers' }] - },{ - title: _('content_type_header_tab') - ,layout: 'anchor' - ,anchor: '100%' - ,items: [{ - xtype: 'modx-content-type-headers-grid' - ,id: 'headers' + }, { + title: _('content_type_header_tab'), + layout: 'anchor', + anchor: '100%', + items: [{ + xtype: 'modx-content-type-headers-grid', + id: 'headers' }] }] - }] - ,keys: [] + }], + keys: [] }); MODx.window.CreateContentType.superclass.constructor.call(this, config); - this.on('beforeSubmit', this.beforeSubmit, this); + this.on({ + beforeSubmit: this.beforeSubmit, + success: { + fn: function() { + this.grid.refresh(); + } + } + }); }; -Ext.extend(MODx.window.CreateContentType,MODx.Window, { +Ext.extend(MODx.window.CreateContentType, MODx.Window, { setRecord: function(record) { this.setValues(record); - - var grid = Ext.getCmp('headers') - ,store = grid.getStore(); - + const + grid = Ext.getCmp('headers'), + store = grid.getStore() + ; store.removeAll(); if (record.headers && record.headers.length > 0) { Ext.each(record.headers, function(header) { @@ -299,15 +349,16 @@ Ext.extend(MODx.window.CreateContentType,MODx.Window, { })); }, this); } - } + }, - ,beforeSubmit: function(o) { - var grid = Ext.getCmp('headers'), - store = grid.getStore() - ,records = store.getRange() - ,form = this.fp.getForm(); - - var results = []; + beforeSubmit: function(o) { + const + grid = Ext.getCmp('headers'), + store = grid.getStore(), + records = store.getRange(), + form = this.fp.getForm(), + results = [] + ; Ext.each(records, function(rec) { results.push(rec.get('header')); }, this); @@ -317,78 +368,84 @@ Ext.extend(MODx.window.CreateContentType,MODx.Window, { return true; } }); -Ext.reg('modx-window-content-type-create',MODx.window.CreateContentType); +Ext.reg('modx-window-content-type-create', MODx.window.CreateContentType); + +MODx.window.UpdateContentType = function(config = {}) { + Ext.applyIf(config, { + title: _('edit'), + action: 'System/ContentType/Update', + isUpdate: true + }); + MODx.window.UpdateContentType.superclass.constructor.call(this, config); + this.setRecord(config.record.data); +}; +Ext.extend(MODx.window.UpdateContentType, MODx.window.CreateContentType, {}); /** * * @param config * @constructor */ -MODx.ContentTypeHeaderGrid = function(config) { - config = config || {}; - +MODx.ContentTypeHeaderGrid = function(config = {}) { Ext.apply(config, { - fields: ['id', 'header'] - ,columns: [{ - header: _('content_type_header') - ,dataIndex: 'header' - }] - ,deferredRender: true - ,autoHeight: true - ,tbar: [{ - text: _('create') - ,cls: 'primary-button' - ,handler: this.add - ,scope: this - }] + fields: ['id', 'header'], + columns: [{ + header: _('content_type_header'), + dataIndex: 'header' + }], + deferredRender: true, + autoHeight: true, + tbar: [this.getCreateButton('content_types', 'add', true)] }); MODx.ContentTypeHeaderGrid.superclass.constructor.call(this, config); }; Ext.extend(MODx.ContentTypeHeaderGrid, MODx.grid.LocalGrid, { - add: function(btn,e) { - var window = this.loadWindow(); + add: function(btn, e) { + const window = this.loadWindow(); window.show(e.target); - } - - ,edit: function(btn, e) { - var record = this.menu.record - ,window = this.loadWindow(record); + }, + edit: function(btn, e) { + const + { record } = this.menu, + window = this.loadWindow(record) + ; window.setValues(record); window.show(e.target); - } - - ,remove: function() { - var record = this.menu.record - ,store = this.getStore() - ,idx = store.find('header', record['header']); + }, + remove: function() { + const + { record } = this.menu, + store = this.getStore(), + idx = store.find('header', record.header) + ; store.removeAt(idx); - } + }, - ,loadWindow: function(record) { + loadWindow: function(record) { return MODx.load({ - xtype: 'modx-window-content-header' - ,grid: this - ,record: record + xtype: 'modx-window-content-header', + grid: this, + record: record }); - } + }, - ,getMenu: function() { - var m = []; - m.push({ - text: _('edit') - ,handler: this.edit - ,scope: this + getMenu: function() { + const menu = []; + menu.push({ + text: _('edit'), + handler: this.edit, + scope: this }); - m.push({ - text: _('delete') - ,handler: this.remove - ,scope: this + menu.push({ + text: _('delete'), + handler: this.remove, + scope: this }); - return m; + return menu; } }); Ext.reg('modx-content-type-headers-grid', MODx.ContentTypeHeaderGrid); @@ -398,39 +455,38 @@ Ext.reg('modx-content-type-headers-grid', MODx.ContentTypeHeaderGrid); * @param config * @constructor */ -MODx.window.ContentHeader = function(config) { - config = config || {}; - +MODx.window.ContentHeader = function(config = {}) { Ext.apply(config, { - title: _('content_type_header_title') - ,fields: [{ - xtype: 'textfield' - ,name: 'header' - ,fieldLabel: _('content_type_header') - ,anchor: '100%' - ,allowBlank: false - }] - ,closeAction: 'close' + title: _('content_type_header_title'), + fields: [{ + xtype: 'textfield', + name: 'header', + fieldLabel: _('content_type_header'), + anchor: '100%', + allowBlank: false + }], + closeAction: 'close' }); MODx.window.ContentHeader.superclass.constructor.call(this, config); }; Ext.extend(MODx.window.ContentHeader, MODx.Window, { submit: function(close) { - var values = this.fp.getForm().getValues() - ,store = this.grid.getStore(); - + const + values = this.fp.getForm().getValues(), + store = this.grid.getStore() + ; if (this.config.record && this.config.record.header) { // Existing record, let's update it - var idx = store.find('header', this.config.record.header); + const idx = store.find('header', this.config.record.header); store.removeAt(idx); store.insert(idx, new Ext.data.Record({ - header: values['header'] + header: values.header })); } else { // New record let's add it to the store store.add(new Ext.data.Record({ - header: values['header'] + header: values.header })); } diff --git a/manager/assets/modext/widgets/system/modx.grid.context.js b/manager/assets/modext/widgets/system/modx.grid.context.js index 2532e5bfd78..eaf658e8315 100644 --- a/manager/assets/modext/widgets/system/modx.grid.context.js +++ b/manager/assets/modext/widgets/system/modx.grid.context.js @@ -6,34 +6,37 @@ * @param {Object} config An object of configuration options * @xtype modx-panel-contexts */ -MODx.panel.Contexts = function(config) { - config = config || {}; - Ext.applyIf(config,{ - id: 'modx-panel-contexts' - ,cls: 'container' - ,bodyStyle: '' - ,defaults: { collapsible: false ,autoHeight: true } - ,items: [{ - html: _('contexts') - ,id: 'modx-contexts-header' - ,xtype: 'modx-header' - },MODx.getPageStructure([{ - title: _('contexts') - ,layout: 'form' - ,items: [{ - html: '

    '+_('context_management_message')+'

    ' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-contexts' - ,cls:'main-wrapper' - ,preventRender: true +MODx.panel.Contexts = function(config = {}) { + Ext.applyIf(config, { + id: 'modx-panel-contexts', + cls: 'container', + bodyStyle: '', + defaults: { + collapsible: false, + autoHeight: true + }, + items: [{ + html: _('contexts'), + id: 'modx-contexts-header', + xtype: 'modx-header' + }, MODx.getPageStructure([{ + title: _('contexts'), + layout: 'form', + items: [{ + html: `

    ${_('context_management_message')}

    `, + xtype: 'modx-description' + }, { + xtype: 'modx-grid-contexts', + urlFilters: ['search'], + cls: 'main-wrapper', + preventRender: true }] }])] }); - MODx.panel.Contexts.superclass.constructor.call(this,config); + MODx.panel.Contexts.superclass.constructor.call(this, config); }; -Ext.extend(MODx.panel.Contexts,MODx.FormPanel); -Ext.reg('modx-panel-contexts',MODx.panel.Contexts); +Ext.extend(MODx.panel.Contexts, MODx.FormPanel); +Ext.reg('modx-panel-contexts', MODx.panel.Contexts); /** * Loads a grid of modContexts. @@ -43,110 +46,175 @@ Ext.reg('modx-panel-contexts',MODx.panel.Contexts); * @param {Object} config An object of configuration properties * @xtype modx-grid-contexts */ -MODx.grid.Context = function(config) { - config = config || {}; - Ext.applyIf(config,{ - title: _('contexts') - ,id: 'modx-grid-context' - ,url: MODx.config.connector_url - ,baseParams: { +MODx.grid.Context = function(config = {}) { + Ext.applyIf(config, { + title: _('contexts'), + id: 'modx-grid-context', + url: MODx.config.connector_url, + baseParams: { action: 'Context/GetList' - } - ,fields: [ + }, + fields: [ 'key', 'name', 'description', - 'perm', - 'rank' - ] - ,paging: true - ,autosave: true - ,save_action: 'Context/UpdateFromGrid' - ,remoteSort: true - ,primaryKey: 'key' - ,columns: [{ - header: _('key') - ,dataIndex: 'key' - ,width: 100 - ,sortable: true - },{ - header: _('name') - ,dataIndex: 'name' - ,width: 150 - ,sortable: true - ,editor: { xtype: 'textfield' } - ,renderer: { fn: function(v,md,record) { - return this.renderLink(v, { - href: '?a=context/update&key=' + record.data.key - }); - }, scope: this } - },{ - header: _('description') - ,dataIndex: 'description' - ,width: 575 - ,sortable: false - ,editor: { xtype: 'textarea' } - },{ - header: _('rank') - ,dataIndex: 'rank' - ,width: 100 - ,sortable: true - ,editor: { xtype: 'numberfield' } - }] - ,tbar: [ - { - text: _('create') - ,cls:'primary-button' - ,handler: this.create - ,scope: this + 'rank', + 'creator' + ], + paging: true, + autosave: true, + save_action: 'Context/UpdateFromGrid', + remoteSort: true, + primaryKey: 'key', + stateful: true, + stateId: 'modx-grid-context-state', + columns: [{ + header: _('key'), + dataIndex: 'key', + width: 100, + sortable: true + }, { + header: _('name'), + dataIndex: 'name', + width: 150, + sortable: true, + editor: { + xtype: 'textfield', + allowBlank: false, + blankText: _('context_err_ns_name'), + validationEvent: 'change', + validator: function(value) { + const + grid = Ext.getCmp('modx-grid-context'), + reserved = this.gridEditor.record.json.reserved.name + ; + if (grid.valueIsReserved(reserved, value)) { + const msg = _('context_err_name_reserved', { + reservedName: value + }); + Ext.Msg.alert(_('error'), msg); + return false; + } + return true; + } + }, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record, [record.json.isProtected, !(record.json.key === 'web')]); + return this.userCanEditRecord(record) + ? this.renderLink(value, { + href: `?a=context/update&key=${record.data.key}`, + title: _('context_edit') + }) + : value + ; + }, + scope: this + } + }, { + header: _('description'), + dataIndex: 'description', + width: 575, + sortable: false, + editor: { + xtype: 'textarea' + }, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record, [record.json.isProtected, !(record.json.key === 'web')]); + return value; + }, + scope: this + } + }, + this.getCreatorColumnConfig('context'), + { + header: _('rank'), + dataIndex: 'rank', + width: 100, + align: 'center', + sortable: true, + editor: { + xtype: 'numberfield' }, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record, [record.json.isProtected, !(record.json.key === 'web')]); + return value; + }, + scope: this + } + }], + tbar: [ + this.getCreateButton('context'), '->', this.getQueryFilterField(), this.getClearFiltersButton() - ] + ], + viewConfig: this.getViewConfig(false) + }); + MODx.grid.Context.superclass.constructor.call(this, config); + + this.gridMenuActions = ['edit', 'delete', 'duplicate']; + + this.setUserCanEdit(['save_context', 'edit_context']); + this.setUserCanCreate(['save_context', 'new_context']); + this.setUserCanDelete(['delete_context']); + this.setShowActionsMenu(); + + this.on({ + beforeedit: function(e) { + if (!this.userCanEdit || e.record.json.key === 'mgr' || !this.userCanEditRecord(e.record)) { + return false; + } + } }); - MODx.grid.Context.superclass.constructor.call(this,config); }; -Ext.extend(MODx.grid.Context,MODx.grid.Grid,{ +Ext.extend(MODx.grid.Context, MODx.grid.Grid, { + getMenu: function() { - var r = this.getSelectionModel().getSelected(); - var p = r.data.perm; - var m = []; - if (p.indexOf('pnew') != -1) { - m.push({ - text: _('duplicate') - ,handler: this.duplicateContext - ,scope: this + const + record = this.getSelectionModel().getSelected(), + menu = [] + ; + if (this.userCanCreate && this.userCanDuplicateRecord(record)) { + menu.push({ + text: _('duplicate'), + handler: this.duplicateContext, + scope: this }); } - - if (p.indexOf('pedit') != -1) { - m.push({ - text: _('edit') - ,handler: this.updateContext + if (this.userCanEdit && this.userCanEditRecord(record)) { + menu.push({ + text: _('edit'), + handler: this.updateContext }); } - - if (p.indexOf('premove') != -1) { - m.push('-'); - m.push({ - text: _('delete') - ,handler: this.remove - ,scope: this + if (this.userCanDelete && this.userCanDeleteRecord(record)) { + if (menu.length > 0) { + menu.push('-'); + } + menu.push({ + text: _('delete'), + handler: this.remove, + scope: this }); } - return m; - } + return menu; + }, - ,create: function(btn, e) { + create: function(btn, e) { if (this.createWindow) { this.createWindow.destroy(); } this.createWindow = MODx.load({ xtype: 'modx-window-context-create', - closeAction:'close', + closeAction: 'close', listeners: { - 'success': { + success: { fn: function() { this.afterAction(); }, @@ -155,34 +223,39 @@ Ext.extend(MODx.grid.Context,MODx.grid.Grid,{ } }); this.createWindow.show(e.target); - } + }, - ,updateContext: function(itm,e) { - MODx.loadPage('context/update', 'key='+this.menu.record.key); - } + updateContext: function(itm, e) { + MODx.loadPage('context/update', `key=${this.menu.record.key}`); + }, - ,duplicateContext: function() { - var r = { - key: this.menu.record.key - ,newkey: '' - }; - var w = MODx.load({ - xtype: 'modx-window-context-duplicate' - ,record: r - ,listeners: { - 'success': {fn:function() { - this.refresh(); - var tree = Ext.getCmp('modx-resource-tree'); - if (tree) { - tree.refresh(); + duplicateContext: function() { + const + record = { + key: this.menu.record.key, + newkey: '' + }, + window = MODx.load({ + xtype: 'modx-window-context-duplicate', + record: record, + listeners: { + success: { + fn: function() { + this.refresh(); + const tree = Ext.getCmp('modx-resource-tree'); + if (tree) { + tree.refresh(); + } + }, + scope: this } - },scope:this} - } - }); - w.show(); - } + } + }) + ; + window.show(); + }, - ,remove: function(btn, e) { + remove: function(btn, e) { MODx.msg.confirm({ title: _('warning'), text: _('context_remove_confirm'), @@ -192,7 +265,7 @@ Ext.extend(MODx.grid.Context,MODx.grid.Grid,{ key: this.menu.record.key }, listeners: { - 'success': { + success: { fn: function() { this.afterAction(); }, @@ -200,10 +273,10 @@ Ext.extend(MODx.grid.Context,MODx.grid.Grid,{ } } }); - } + }, - ,afterAction: function() { - var cmp = Ext.getCmp('modx-resource-tree'); + afterAction: function() { + const cmp = Ext.getCmp('modx-resource-tree'); if (cmp) { cmp.refresh(); } @@ -211,7 +284,7 @@ Ext.extend(MODx.grid.Context,MODx.grid.Grid,{ this.refresh(); } }); -Ext.reg('modx-grid-contexts',MODx.grid.Context); +Ext.reg('modx-grid-contexts', MODx.grid.Context); /** * Generates the create context window. @@ -221,40 +294,41 @@ Ext.reg('modx-grid-contexts',MODx.grid.Context); * @param {Object} config An object of options. * @xtype modx-window-context-create */ -MODx.window.CreateContext = function(config) { - config = config || {}; - Ext.applyIf(config,{ - title: _('create') - ,url: MODx.config.connector_url - ,action: 'Context/Create' - ,fields: [{ - xtype: 'textfield' - ,fieldLabel: _('context_key') - ,name: 'key' - ,anchor: '100%' - ,maxLength: 100 - },{ - xtype: 'textfield' - ,fieldLabel: _('name') - ,name: 'name' - ,anchor: '100%' - ,maxLength: 100 - },{ - xtype: 'textarea' - ,fieldLabel: _('description') - ,name: 'description' - ,anchor: '100%' - ,grow: true - },{ - xtype: 'numberfield' - ,fieldLabel: _('rank') - ,name: 'rank' - ,allowBlank: true - ,anchor: '100%' - }] - ,keys: [] +MODx.window.CreateContext = function(config = {}) { + Ext.applyIf(config, { + title: _('create'), + url: MODx.config.connector_url, + action: 'Context/Create', + formDefaults: { + anchor: '100%' + }, + fields: [{ + xtype: 'textfield', + fieldLabel: _('context_key'), + name: 'key', + maxLength: 100, + allowBlank: false, + blankText: _('context_err_ns_key') + }, { + xtype: 'textfield', + fieldLabel: _('name'), + name: 'name', + maxLength: 100, + allowBlank: false, + blankText: _('context_err_ns_name') + }, { + xtype: 'textarea', + fieldLabel: _('description'), + name: 'description', + grow: true + }, { + xtype: 'numberfield', + fieldLabel: _('rank'), + name: 'rank' + }], + keys: [] }); - MODx.window.CreateContext.superclass.constructor.call(this,config); + MODx.window.CreateContext.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.CreateContext,MODx.Window); -Ext.reg('modx-window-context-create',MODx.window.CreateContext); +Ext.extend(MODx.window.CreateContext, MODx.Window); +Ext.reg('modx-window-context-create', MODx.window.CreateContext); diff --git a/manager/assets/modext/widgets/system/modx.grid.dashboard.widgets.js b/manager/assets/modext/widgets/system/modx.grid.dashboard.widgets.js index aaea2ab9710..a82b719fa48 100644 --- a/manager/assets/modext/widgets/system/modx.grid.dashboard.widgets.js +++ b/manager/assets/modext/widgets/system/modx.grid.dashboard.widgets.js @@ -11,14 +11,14 @@ MODx.grid.DashboardWidgets = function(config = {}) { '

    {description_trans}

    ' ) }); - this.sm = new Ext.grid.CheckboxSelectionModel(); - Ext.applyIf(config,{ - url: MODx.config.connector_url - ,baseParams: { + Ext.applyIf(config, { + id: 'modx-grid-dashboard-widgets', + url: MODx.config.connector_url, + baseParams: { action: 'System/Dashboard/Widget/GetList' - } - ,fields: [ + }, + fields: [ 'id', 'name', 'name_trans', @@ -28,136 +28,123 @@ MODx.grid.DashboardWidgets = function(config = {}) { 'content', 'namespace', 'lexicon', - 'size', - 'cls' - ] - ,paging: true - ,remoteSort: true - ,sm: this.sm - ,plugins: [this.exp] - ,columns: [this.exp,this.sm,{ - header: _('id') - ,dataIndex: 'id' - ,width: 50 - ,sortable: true - },{ - header: _('name') - ,dataIndex: 'name_trans' - ,width: 150 - ,sortable: true - ,editable: false - ,renderer: { fn: function(v,md,record) { - return this.renderLink(v, { - href: '?a=system/dashboards/widget/update&id=' + record.data.id - }); - }, scope: this } - },{ - header: _('widget_type') - ,dataIndex: 'type' - ,width: 80 - ,sortable: true - },{ - header: _('widget_namespace') - ,dataIndex: 'namespace' - ,width: 120 - ,sortable: true - }] - ,tbar: [ + 'size' + ], + paging: true, + remoteSort: true, + sm: this.sm, + plugins: [this.exp], + columns: [ + this.exp, + this.sm, { - text: _('create') - ,cls:'primary-button' - ,handler: this.createDashboard - ,scope: this - },{ - text: _('bulk_actions') - ,menu: [{ - text: _('selected_remove') - ,handler: this.removeSelected - ,scope: this - }] - }, + header: _('id'), + dataIndex: 'id', + width: 50, + sortable: true + }, { + header: _('name'), + dataIndex: 'name_trans', + width: 150, + sortable: true, + editable: false, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record, [record.json.isProtected]); + return this.userCanEditRecord(record) + ? this.renderLink(value, { + href: `?a=system/dashboards/widget/update&id=${record.data.id}`, + title: _('dashboard_edit') + }) + : value + ; + }, + scope: this + } + }, { + header: _('widget_type'), + dataIndex: 'type', + width: 80, + sortable: true + }, { + header: _('widget_namespace'), + dataIndex: 'namespace', + width: 120, + sortable: true, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record, [record.json.isProtected]); + return value; + }, + scope: this + } + } + ], + tbar: [ + this.getCreateButton('dashboard', 'createDashboard'), + this.getBulkActionsButton('widget', 'System/Dashboard/Widget/RemoveMultiple'), '->', this.getQueryFilterField(`filter-query-dashboardWidgets:${queryValue}`), this.getClearFiltersButton('filter-query-dashboardWidgets') ] }); - MODx.grid.DashboardWidgets.superclass.constructor.call(this,config); + MODx.grid.DashboardWidgets.superclass.constructor.call(this, config); + + this.gridMenuActions = ['edit', 'delete']; + + // Note there are currently no action-specific permissions for Dashboards + this.setUserCanEdit(['dashboards']); + this.setUserCanCreate(['dashboards']); + this.setUserCanDelete(['dashboards']); + this.setShowActionsMenu(); + + this.on({ + beforerender: function(grid) { + grid.view = new Ext.grid.GridView(grid.getViewConfig()); + } + }); }; -Ext.extend(MODx.grid.DashboardWidgets,MODx.grid.Grid,{ +Ext.extend(MODx.grid.DashboardWidgets, MODx.grid.Grid, { getMenu: function() { - var r = this.getSelectionModel().getSelected(); - var p = r.data.cls; - - var m = []; - if (this.getSelectionModel().getCount() > 1) { - m.push({ - text: _('selected_remove') - ,handler: this.removeSelected - ,scope: this + const + record = this.getSelectionModel().getSelected(), + menu = [], + canDelete = this.userCanDelete && this.userCanDeleteRecord(record) + ; + if (this.getSelectionModel().getCount() > 1 && canDelete) { + menu.push({ + text: _('selected_remove'), + handler: this.removeSelected, + scope: this }); } else { - if (p.indexOf('pupdate') != -1) { - m.push({ - text: _('edit') - ,handler: this.updateWidget + if (this.userCanEdit && this.userCanEditRecord(record)) { + menu.push({ + text: _('edit'), + handler: this.updateWidget }); } - if (p.indexOf('premove') != -1) { - if (m.length > 0) m.push('-'); - m.push({ - text: _('delete') - ,handler: this.removeWidget + if (canDelete) { + if (menu.length > 0) { + menu.push('-'); + } + menu.push({ + text: _('delete'), + handler: this.confirm.createDelegate(this, ['System/Dashboard/Widget/Remove', 'widget_remove_confirm']) }); } } - if (m.length > 0) { - this.addContextMenuItem(m); - } - } + return menu; + }, - ,createDashboard: function() { + createDashboard: function() { MODx.loadPage('system/dashboards/widget/create'); - } - - ,updateWidget: function() { - MODx.loadPage('system/dashboards/widget/update', 'id='+this.menu.record.id); - } + }, - ,removeWidget: function() { - MODx.msg.confirm({ - title: _('delete') - ,text: _('widget_remove_confirm') - ,url: this.config.url - ,params: { - action: 'System/Dashboard/Widget/Remove' - ,id: this.menu.record.id - } - ,listeners: { - 'success': {fn:this.refresh,scope:this} - } - }); - } - - ,removeSelected: function() { - var cs = this.getSelectedAsList(); - if (cs === false) return false; - - MODx.msg.confirm({ - title: _('selected_remove') - ,text: _('widget_remove_multiple_confirm') - ,url: this.config.url - ,params: { - action: 'System/Dashboard/Widget/RemoveMultiple' - ,widgets: cs - } - ,listeners: { - 'success': {fn:function(r) { - this.getSelectionModel().clearSelections(true); - this.refresh(); - },scope:this} - } - }); - return true; + updateWidget: function() { + MODx.loadPage('system/dashboards/widget/update', `id=${this.menu.record.id}`); } }); -Ext.reg('modx-grid-dashboard-widgets',MODx.grid.DashboardWidgets); +Ext.reg('modx-grid-dashboard-widgets', MODx.grid.DashboardWidgets); diff --git a/manager/assets/modext/widgets/system/modx.panel.context.js b/manager/assets/modext/widgets/system/modx.panel.context.js index 9a4270cab05..a838c59aaaf 100644 --- a/manager/assets/modext/widgets/system/modx.panel.context.js +++ b/manager/assets/modext/widgets/system/modx.panel.context.js @@ -4,152 +4,181 @@ * @param {Object} config An object of config properties * @xtype modx-panel-context */ -MODx.panel.Context = function(config) { - config = config || {}; - Ext.applyIf(config,{ - url: MODx.config.connector_url - ,baseParams: { +MODx.panel.Context = function(config = {}) { + Ext.applyIf(config, { + url: MODx.config.connector_url, + baseParams: { action: 'Context/Get' - } - ,id: 'modx-panel-context' - ,cls: 'container' - ,class_key: 'modContext' - ,plugin: '' - ,bodyStyle: '' - ,items: [this.getPageHeader(config), MODx.getPageStructure([{ - title: _('general_information') - ,autoHeight: true - ,layout: 'form' - ,defaults: { border: false ,msgTarget: 'side' } - ,items:[{ - xtype: 'panel' - ,border: false - ,cls:'main-wrapper' - ,layout: 'form' - ,items: [{ - xtype: 'statictextfield' - ,fieldLabel: _('key') - ,name: 'key' - ,width: 300 - ,maxLength: 100 - ,enableKeyEvents: true - ,allowBlank: true - ,value: config.context - ,submitValue: true - },{ - xtype: 'textfield' - ,fieldLabel: _('name') - ,name: 'name' - ,width: 300 - ,maxLength: 191 - },{ - xtype: 'textarea' - ,fieldLabel: _('description') - ,name: 'description' - ,width: 300 - ,grow: true - },{ - xtype: 'numberfield' - ,fieldLabel: _('rank') - ,name: 'rank' - ,allowBlank: true - ,width: 300 - },{ - html: MODx.onContextFormRender - ,border: false + }, + id: 'modx-panel-context', + cls: 'container', + class_key: 'modContext', + plugin: '', + bodyStyle: '', + items: [this.getPageHeader(config), MODx.getPageStructure([{ + title: _('general_information'), + autoHeight: true, + layout: 'form', + defaults: { border: false, msgTarget: 'side' }, + items: [{ + xtype: 'modx-description', + id: 'modx-context-general-desc', + hidden: true, + html: '' + }, { + xtype: 'panel', + border: false, + cls: 'main-wrapper', + layout: 'form', + items: [{ + xtype: 'statictextfield', + fieldLabel: _('key'), + name: 'key', + width: 300, + maxLength: 100, + enableKeyEvents: true, + value: config.context, + submitValue: true + }, { + xtype: config.context === 'mgr' ? 'statictextfield' : 'textfield', + fieldLabel: _('name'), + name: 'name', + width: 300, + maxLength: 191 + }, { + xtype: config.context === 'mgr' ? 'statictextarea' : 'textarea', + fieldLabel: _('description'), + name: 'description', + width: 300, + grow: true + }, { + xtype: config.context === 'mgr' ? 'statictextfield' : 'numberfield', + fieldLabel: _('rank'), + name: 'rank', + width: 300 + }, { + html: MODx.onContextFormRender, + border: false }] }] - },{ - title: _('context_settings') - ,autoHeight: true - ,layout: 'form' - ,items: [{ - html: '

    '+_('context_settings_desc')+'

    ' - ,id: 'modx-context-settings-desc' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-context-settings' - ,cls:'main-wrapper' - ,title: '' - ,preventRender: true - ,context_key: config.context - ,listeners: { - 'afteredit': {fn:function() { this.markDirty(); },scope:this} + }, { + title: _('context_settings'), + autoHeight: true, + layout: 'form', + items: [{ + html: `

    ${_('context_settings_desc')}

    `, + id: 'modx-context-settings-desc', + xtype: 'modx-description' + }, { + xtype: 'modx-grid-context-settings', + cls: 'main-wrapper', + title: '', + preventRender: true, + context_key: config.context, + listeners: { + afteredit: { + fn: function() { + this.markDirty(); + }, + scope: this + } } }] - },{ - title: _('access_permissions') - ,autoHeight: true - ,items:[{ - xtype: 'modx-grid-access-context' - ,cls:'main-wrapper' - ,title: '' - ,preventRender: true - ,context_key: config.context - ,listeners: { - 'afteredit': {fn:function() { this.markDirty(); },scope:this} + }, { + title: _('access_permissions'), + autoHeight: true, + items: [{ + xtype: 'modx-grid-access-context', + cls: 'main-wrapper', + title: '', + preventRender: true, + context_key: config.context, + listeners: { + afteredit: { + fn: function() { + this.markDirty(); + }, + scope: this + } } }] - }],{ + }], { id: 'modx-context-tabs' - })] - ,useLoadingMask: true - ,listeners: { - 'setup': {fn:this.setup,scope:this} - ,'success': {fn:this.success,scope:this} - ,'beforeSubmit': {fn:this.beforeSubmit,scope:this} + })], + useLoadingMask: true, + listeners: { + setup: { fn: this.setup, scope: this }, + success: { fn: this.success, scope: this }, + beforeSubmit: { fn: this.beforeSubmit, scope: this } } }); - MODx.panel.Context.superclass.constructor.call(this,config); + MODx.panel.Context.superclass.constructor.call(this, config); }; -Ext.extend(MODx.panel.Context,MODx.FormPanel,{ - initialized: false +Ext.extend(MODx.panel.Context, MODx.FormPanel, { + initialized: false, - ,setup: function() { + setup: function() { if (this.initialized || (this.config.context === '' || this.config.context === 0)) { this.fireEvent('ready'); return false; } MODx.Ajax.request({ - url: this.config.url - ,params: { - action: 'Context/Get' - ,key: this.config.context - } - ,listeners: { - 'success': {fn:function(r) { - this.getForm().setValues(r.object); - Ext.getCmp('modx-header-breadcrumbs').updateHeader(Ext.util.Format.htmlEncode(r.object.key)); - this.fireEvent('ready'); - MODx.fireEvent('ready'); - this.initialized = true; - },scope:this} + url: this.config.url, + params: { + action: 'Context/Get', + key: this.config.context + }, + listeners: { + success: { + fn: function(response) { + const record = response.object; + this.config.record = record; + if (record.isProtected && record.key !== 'web') { + const descriptionCmp = Ext.getCmp('modx-context-general-desc'); + descriptionCmp.update(_('context_reserved_general_desc')); + descriptionCmp.show(); + } + this.getForm().setValues(record); + Ext.getCmp('modx-header-breadcrumbs').updateHeader(Ext.util.Format.htmlEncode(record.key)); + this.fireEvent('ready'); + MODx.fireEvent('ready'); + this.initialized = true; + }, + scope: this + } } }); - } - - ,beforeSubmit: function(o) { - var r = {}; - - var g = Ext.getCmp('modx-grid-context-settings'); - if (g) { r.settings = g.encodeModified(); } + }, - Ext.apply(o.form.baseParams,r); - } - - ,success: function(o) { - var g = Ext.getCmp('modx-grid-context-settings'); - if (g) { g.getStore().commitChanges(); } + beforeSubmit: function(o) { + const + data = {}, + settingsCmp = Ext.getCmp('modx-grid-context-settings') + ; + if (settingsCmp) { + data.settings = settingsCmp.encodeModified(); + } + Ext.apply(o.form.baseParams, data); + }, - var t = parent.Ext.getCmp('modx-resource-tree'); - if (t) { t.refresh(); } - } + success: function(o) { + const + settingsCmp = Ext.getCmp('modx-grid-context-settings'), + tree = Ext.getCmp('modx-resource-tree') + ; + if (settingsCmp) { + settingsCmp.getStore().commitChanges(); + } + if (tree) { + tree.refresh(); + } + }, - ,getPageHeader: function(config) { + getPageHeader: function(config) { return MODx.util.getHeaderBreadCrumbs('modx-context-name', [{ text: _('contexts'), href: MODx.getPage('context') }]); } }); -Ext.reg('modx-panel-context',MODx.panel.Context); +Ext.reg('modx-panel-context', MODx.panel.Context); diff --git a/manager/assets/modext/widgets/system/modx.panel.dashboard.js b/manager/assets/modext/widgets/system/modx.panel.dashboard.js index 63e60af2815..bc0199d2a6f 100644 --- a/manager/assets/modext/widgets/system/modx.panel.dashboard.js +++ b/manager/assets/modext/widgets/system/modx.panel.dashboard.js @@ -4,148 +4,168 @@ * @param {Object} config An object of configuration properties * @xtype modx-panel-dashboard */ -MODx.panel.Dashboard = function(config) { - config = config || {}; - Ext.applyIf(config,{ - id: 'modx-panel-dashboard' - ,url: MODx.config.connector_url - ,baseParams: { +MODx.panel.Dashboard = function(config = {}) { + let generalIntro = {}; + if (config.record.reserved) { + generalIntro = { + xtype: 'box', + cls: 'panel-desc', + html: _('dashboard_reserved_general_desc') + }; + } + Ext.applyIf(config, { + id: 'modx-panel-dashboard', + url: MODx.config.connector_url, + baseParams: { action: 'System/Dashboard/Update' - } - ,cls: 'container' - ,defaults: { collapsible: false ,autoHeight: true } - ,items: [this.getPageHeader(config),{ - xtype: 'modx-tabs' - ,defaults: { - autoHeight: true - ,border: false - } - ,id: 'modx-dashboard-tabs' - ,forceLayout: true - ,deferredRender: false - ,stateful: true - ,stateId: 'modx-dashboard-tabpanel' - ,stateEvents: ['tabchange'] - ,getState:function() { - return {activeTab:this.items.indexOf(this.getActiveTab())}; - } + }, + cls: 'container', + defaults: { + collapsible: false, + autoHeight: true + }, + items: [this.getPageHeader(config), { + xtype: 'modx-tabs', + defaults: { + autoHeight: true, + border: false + }, + id: 'modx-dashboard-tabs', + forceLayout: true, + deferredRender: false, + stateful: true, + stateId: 'modx-dashboard-tabpanel', + stateEvents: ['tabchange'], + getState: function() { + return { activeTab: this.items.indexOf(this.getActiveTab()) }; + }, // todo: the layout is inconsistent with other panels, refactor the structure - ,items: [{ - title: _('general_information') - ,cls: 'form-with-labels' - ,defaults: { border: false, cls: 'main-wrapper' } - ,layout: 'form' - ,id: 'modx-dashboard-form' - ,labelAlign: 'top' - ,items: [{ - xtype: 'hidden' - ,name: 'id' - ,id: 'modx-dashboard-id' - ,value: config.record.id - },{ - layout: 'column' - ,border: false - ,defaults: { - layout: 'form' - ,labelAlign: 'top' - ,anchor: '100%' - ,border: false - } - ,items: [{ - columnWidth: .7 - ,cls: 'main-content' - ,items: [{ - name: 'name' - ,id: 'modx-dashboard-name' - ,xtype: 'textfield' - ,fieldLabel: _('name') - ,description: MODx.expandHelp ? '' : _('dashboard_desc_name') - ,allowBlank: false - ,enableKeyEvents: true - ,anchor: '100%' - ,listeners: { - 'keyup': {scope:this,fn:function(f,e) { - Ext.getCmp('modx-header-breadcrumbs').updateHeader(Ext.util.Format.htmlEncode(f.getValue())); - }} + items: [{ + title: _('general_information'), + cls: 'form-with-labels', + defaults: { + border: false, + cls: 'main-wrapper' + }, + layout: 'form', + id: 'modx-dashboard-form', + labelAlign: 'top', + items: [generalIntro, { + xtype: 'hidden', + name: 'id', + id: 'modx-dashboard-id', + value: config.record.id + }, { + layout: 'column', + border: false, + defaults: { + layout: 'form', + labelAlign: 'top', + labelSeparator: '', + border: false + }, + items: [{ + columnWidth: 0.7, + cls: 'main-content', + defaults: { + msgTarget: 'under', + anchor: '100%' + }, + items: [{ + xtype: config.record.reserved ? 'statictextfield' : 'textfield', + name: 'name', + fieldLabel: _('name'), + description: MODx.expandHelp ? '' : _('dashboard_name_desc'), + allowBlank: false, + enableKeyEvents: true, + listeners: { + keyup: { + fn: function(f, e) { + Ext.getCmp('modx-header-breadcrumbs').updateHeader(Ext.util.Format.htmlEncode(f.getValue())); + }, + scope: this + } } - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-dashboard-name' - ,html: _('dashboard_desc_name') - ,cls: 'desc-under' - },{ - name: 'description' - ,id: 'modx-dashboard-description' - ,xtype: 'textarea' - ,fieldLabel: _('description') - ,description: MODx.expandHelp ? '' : _('dashboard_desc_description') - ,anchor: '100%' - ,grow: true - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-dashboard-description' - ,html: _('dashboard_desc_description') - ,cls: 'desc-under' + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('dashboard_name_desc'), + cls: 'desc-under' + }, { + name: 'description', + xtype: 'textarea', + /** + * @todo - Change this xtype to the following once Lexicon-based name/desc is implemented for core dashboard + * xtype: config.record.reserved ? 'statictextfield' : 'textfield', + */ + fieldLabel: _('description'), + description: MODx.expandHelp ? '' : _('dashboard_description_desc'), + grow: true + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('dashboard_description_desc'), + cls: 'desc-under' }] - },{ - columnWidth: .3 - ,cls: 'main-content' - ,items: [{ - name: 'hide_trees' - ,id: 'modx-dashboard-hide-trees' - ,xtype: 'xcheckbox' - ,boxLabel: _('dashboard_hide_trees') - ,description: MODx.expandHelp ? '' : _('dashboard_desc_hide_trees') - ,inputValue: 1 - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-dashboard-hide-trees' - ,html: _('dashboard_desc_hide_trees') - ,cls: 'desc-under' - },{ - name: 'customizable' - ,id: 'modx-dashboard-customizable' - ,xtype: 'xcheckbox' - ,boxLabel: _('dashboard_customizable') - ,description: MODx.expandHelp ? '' : _('dashboard_desc_customizable') - ,inputValue: 1 - ,checked: true - },{ - xtype: MODx.expandHelp ? 'label' : 'hidden' - ,forId: 'modx-dashboard-customizable' - ,html: _('dashboard_desc_customizable') - ,cls: 'desc-under' + }, { + columnWidth: 0.3, + cls: 'main-content', + items: [{ + name: 'hide_trees', + xtype: 'xcheckbox', + ctCls: 'display-switch', + boxLabel: _('dashboard_hide_trees'), + description: MODx.expandHelp ? '' : _('dashboard_hide_trees_desc'), + inputValue: 1 + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('dashboard_hide_trees_desc'), + cls: 'desc-under' + }, { + name: 'customizable', + xtype: 'xcheckbox', + ctCls: 'display-switch', + boxLabel: _('dashboard_customizable'), + description: MODx.expandHelp ? '' : _('dashboard_customizable_desc'), + inputValue: 1, + checked: true + }, { + xtype: 'box', + hidden: !MODx.expandHelp, + html: _('dashboard_customizable_desc'), + cls: 'desc-under' }] }] - },{ - html: '

    '+_('dashboard_widgets.intro_msg')+'

    ' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-dashboard-widget-placements' - ,preventRender: true - ,dashboard: config.record.id - ,autoHeight: true - ,anchor: '100%' - ,listeners: { - 'afterRemoveRow': {fn:this.markDirty,scope:this} - ,'updateRole': {fn:this.markDirty,scope:this} - ,'addMember': {fn:this.markDirty,scope:this} + }, { + html: `

    ${_('dashboard_widgets.intro_msg')}

    `, + xtype: 'modx-description' + }, { + xtype: 'modx-grid-dashboard-widget-placements', + preventRender: true, + dashboard: config.record.id, + autoHeight: true, + anchor: '100%', + listeners: { + afterRemoveRow: { fn: this.markDirty, scope: this }, + updateRole: { fn: this.markDirty, scope: this }, + addMember: { fn: this.markDirty, scope: this } } }] }] - }] - ,listeners: { - 'setup': {fn:this.setup,scope:this} - ,'success': {fn:this.success,scope:this} - ,'beforeSubmit': {fn:this.beforeSubmit,scope:this} + }], + listeners: { + setup: { fn: this.setup, scope: this }, + success: { fn: this.success, scope: this }, + beforeSubmit: { fn: this.beforeSubmit, scope: this } } }); - MODx.panel.Dashboard.superclass.constructor.call(this,config); + MODx.panel.Dashboard.superclass.constructor.call(this, config); }; -Ext.extend(MODx.panel.Dashboard,MODx.FormPanel,{ - initialized: false +Ext.extend(MODx.panel.Dashboard, MODx.FormPanel, { + initialized: false, - ,setup: function() { + setup: function() { if (this.initialized) { return false; } if (Ext.isEmpty(this.config.record.id)) { this.fireEvent('ready'); @@ -154,45 +174,48 @@ Ext.extend(MODx.panel.Dashboard,MODx.FormPanel,{ this.getForm().setValues(this.config.record); Ext.getCmp('modx-header-breadcrumbs').updateHeader(Ext.util.Format.htmlEncode(this.config.record.name)); - var d = this.config.record.widgets; - var g = Ext.getCmp('modx-grid-dashboard-widget-placements'); - if (d && g) { - g.getStore().loadData(d); + const + { widgets } = this.config.record, + placementsGrid = Ext.getCmp('modx-grid-dashboard-widget-placements') + ; + if (widgets && placementsGrid) { + placementsGrid.getStore().loadData(widgets); } - this.fireEvent('ready',this.config.record); + this.fireEvent('ready', this.config.record); MODx.fireEvent('ready'); this.initialized = true; - } + }, - ,beforeSubmit: function(o) { - var bp = {}; - var wg = Ext.getCmp('modx-grid-dashboard-widget-placements'); - if (wg) { - bp['widgets'] = wg.encode(); + beforeSubmit: function(o) { + const + params = {}, + placementsGrid = Ext.getCmp('modx-grid-dashboard-widget-placements') + ; + if (placementsGrid) { + params.widgets = placementsGrid.encode(); } - Ext.apply(o.form.baseParams,bp); - } + Ext.apply(o.form.baseParams, params); + }, - ,success: function(o) { + success: function(o) { if (Ext.isEmpty(this.config.record) || Ext.isEmpty(this.config.record.id)) { - MODx.loadPage('system/dashboards/update', 'id='+o.result.object.id); + MODx.loadPage('system/dashboards/update', `id=${o.result.object.id}`); } else { Ext.getCmp('modx-abtn-save').setDisabled(false); - var wg = Ext.getCmp('modx-grid-dashboard-widget-placements'); + const wg = Ext.getCmp('modx-grid-dashboard-widget-placements'); if (wg) { wg.getStore().commitChanges(); } - } - } + }, - ,getPageHeader: function(config) { + getPageHeader: function(config) { return MODx.util.getHeaderBreadCrumbs('modx-dashboard-header', [{ text: _('dashboards'), href: MODx.getPage('system/dashboards') }]); } }); -Ext.reg('modx-panel-dashboard',MODx.panel.Dashboard); +Ext.reg('modx-panel-dashboard', MODx.panel.Dashboard); /** * @class MODx.grid.DashboardWidgetPlacements @@ -200,109 +223,139 @@ Ext.reg('modx-panel-dashboard',MODx.panel.Dashboard); * @param {Object} config An object of configuration properties * @xtype modx-grid-dashboard-widget-placements */ -MODx.grid.DashboardWidgetPlacements = function(config) { - config = config || {}; +MODx.grid.DashboardWidgetPlacements = function(config = {}) { this.exp = new Ext.grid.RowExpander({ - tpl : new Ext.Template( + tpl: new Ext.Template( '

    {description_trans}

    ' ) }); - Ext.applyIf(config,{ - id: 'modx-grid-dashboard-widget-placements' - ,url: MODx.config.connector_url - ,action: 'system/dashboard/widget/placement/getList' - ,fields: ['dashboard','widget','rank','name','name_trans','description','description_trans'] - ,autoHeight: true - ,primaryKey: 'widget' - ,cls: 'modx-grid modx-grid-draggable' - ,plugins: [this.exp,new Ext.ux.dd.GridDragDropRowOrder({ - copy: false // false by default - ,scrollable: true // enable scrolling support (default is false) - ,targetCfg: {} - ,listeners: { - 'afterrowmove': {fn:this.onAfterRowMove,scope:this} + Ext.applyIf(config, { + id: 'modx-grid-dashboard-widget-placements', + url: MODx.config.connector_url, + fields: [ + 'dashboard', + 'widget', + 'rank', + 'name', + 'name_trans', + 'description', + 'description_trans', + 'permissions' + ], + autoHeight: true, + primaryKey: 'widget', + cls: 'modx-grid modx-grid-draggable', + plugins: [this.exp, new Ext.ux.dd.GridDragDropRowOrder({ + scrollable: true, + targetCfg: {}, + listeners: { + afterrowmove: { + fn: this.onAfterRowMove, + scope: this + } } - })] - ,columns: [this.exp,{ - header: _('widget') - ,dataIndex: 'name_trans' - ,width: 600 - ,renderer: { fn: function(v,md,record) { - return this.renderLink(v, { - href: '?a=system/dashboards/widget/update&id=' + record.data.widget - ,target: '_blank' - }); - }, scope: this } - },{ - header: _('rank') - ,dataIndex: 'rank' - ,width: 80 - ,editor: { xtype: 'numberfield', allowBlank: false, allowNegative: false } - }] - ,tbar: [{ - text: _('widget_place') - ,cls:'primary-button' - ,handler: this.placeWidget - ,scope: this + })], + columns: [this.exp, { + header: _('widget'), + dataIndex: 'name_trans', + width: 150, + renderer: { + fn: function(value, metaData, record) { + return this.renderLink(value, { + href: `?a=system/dashboards/widget/update&id=${record.data.widget}`, + target: '_blank' + }); + }, + scope: this + } + }, { + header: _('rank'), + dataIndex: 'rank', + width: 80, + align: 'center', + editor: { + xtype: 'numberfield', + allowBlank: false, + allowNegative: false + } + }], + tbar: [{ + text: _('widget_place'), + cls: 'primary-button', + handler: this.placeWidget, + scope: this }] }); - MODx.grid.DashboardWidgetPlacements.superclass.constructor.call(this,config); - this.propRecord = Ext.data.Record.create(['dashboard','widget','rank','name','name_trans','description','description_trans']); + MODx.grid.DashboardWidgetPlacements.superclass.constructor.call(this, config); + this.propRecord = Ext.data.Record.create([ + 'dashboard', + 'widget', + 'rank', + 'name', + 'name_trans', + 'description', + 'description_trans', + 'permissions' + ]); }; -Ext.extend(MODx.grid.DashboardWidgetPlacements,MODx.grid.LocalGrid,{ +Ext.extend(MODx.grid.DashboardWidgetPlacements, MODx.grid.LocalGrid, { getMenu: function() { return [{ - text: _('widget_unplace') - ,handler: this.unplaceWidget - ,scope: this + text: _('widget_unplace'), + handler: this.unplaceWidget, + scope: this }]; - } - - ,onAfterRowMove: function(dt,sri,ri,sels) { - var s = this.getStore(); - var sourceRec = s.data.items[sri]; - var total = s.data.length; + }, - sourceRec.set('rank',sri); - sourceRec.commit(); + onAfterRowMove: function(dropTarget, fromRowIndex, toRowIndex, selections) { + const + store = this.getStore(), + firstDraggedRecord = store.data.items[fromRowIndex], + total = store.data.length + ; + firstDraggedRecord.set('rank', fromRowIndex); + firstDraggedRecord.commit(); - /* get all rows below ri, and up their rank by 1 */ - var brec; - for (var x=(ri-1);x 0 - // Get the rank of the last record - ? s.data.items[s.data.length - 1].get('rank') + 1 - // Or set it to '0' if no record found - : 0; - - var fldStore = fld.getStore(); - var fldRi = fldStore.find('id',fld.getValue()); - var rec = fldStore.getAt(fldRi); - - if (id != '' && this.fp.getForm().isValid()) { - - if (this.fireEvent('success',{ - widget: fld.getValue() - ,dashboard: g.config.dashboard - ,name: rec.data.name - ,name_trans: rec.data.name_trans - ,description: rec.data.description - ,description_trans: rec.data.description_trans - ,rank: rank - })) { - this.fp.getForm().reset(); - this.hide(); - return true; - } - } else { - MODx.msg.alert(_('error'),_('widget_err_ns')); - } - return true; - } -}); -Ext.reg('modx-window-dashboard-widget-place',MODx.window.DashboardWidgetPlace); - -/* -MODx.grid.DashboardUserGroups = function(config) { - config = config || {}; - Ext.applyIf(config,{ - id: 'modx-grid-dashboard-usergroups' - ,url: MODx.config.connector_url - ,action: 'system/dashboard/group/getList' - ,fields: ['id','name'] - ,autoHeight: true - ,primaryKey: 'user' - ,columns: [{ - header: _('user_group') - ,dataIndex: 'name' - ,width: 600 - }] - ,tbar: [{ - text: _('dashboard_usergroup_add') - ,handler: this.addUserGroup - ,scope: this - }] - }); - MODx.grid.DashboardUserGroups.superclass.constructor.call(this,config); - this.propRecord = Ext.data.Record.create(['id','name']); -}; -Ext.extend(MODx.grid.DashboardUserGroups,MODx.grid.LocalGrid,{ - getMenu: function() { - return [{ - text: _('dashboard_usergroup_remove') - ,handler: this.remove.createDelegate(this,[{ - title: _('dashboard_usergroup_remove') - ,text: _('dashboard_usergroup_remove_confirm') - }]) - ,scope: this - }]; - } - - ,addUserGroup: function(btn,e) { - this.loadWindow(btn,e,{ - xtype: 'modx-window-dashboard-usergroup-add' - ,listeners: { - 'success': {fn:function(vs) { - var rec = new this.propRecord(vs); - this.getStore().add(rec); - },scope:this} - } - }); - var w = Ext.getCmp('modx-window-dashboard-usergroup-add'); - w.reset(); - w.setValues({ - dashboard: this.config.dashboard - }); - - } -}); -Ext.reg('modx-grid-dashboard-usergroups',MODx.grid.DashboardUserGroups); - -MODx.window.DashboardUserGroupAdd = function(config) { - config = config || {}; - this.ident = config.ident || 'dbugadd'+Ext.id(); - Ext.applyIf(config,{ - title: _('dashboard_usergroup_add') - ,frame: true - ,id: 'modx-window-dashboard-usergroup-add' - ,fields: [{ - xtype: 'modx-combo-usergroup' - ,fieldLabel: _('user_group') - ,name: 'usergroup' - ,hiddenName: 'usergroup' - ,id: 'modx-'+this.ident+'-usergroup' - ,allowBlank: false - }] - }); - MODx.window.DashboardUserGroupAdd.superclass.constructor.call(this,config); -}; -Ext.extend(MODx.window.DashboardUserGroupAdd,MODx.Window,{ - submit: function() { - var f = this.fp.getForm(); - var fld = f.findField('usergroup'); - - if (id != '' && this.fp.getForm().isValid()) { - if (this.fireEvent('success',{ - id: fld.getValue() - ,name: fld.getRawValue() + const + // Get the rank of the last record or set it to '0' if no record found + rank = store.data.length > 0 + ? store.data.items[store.data.length - 1].get('rank') + 1 + : 0, + widgetStore = widgetField.getStore(), + widgetRowIndex = widgetStore.find('id', selectedWidget), + record = widgetStore.getAt(widgetRowIndex) + ; + if (this.fp.getForm().isValid()) { + if (this.fireEvent('success', { + widget: widgetField.getValue(), + dashboard: widgetsGrid.config.dashboard, + name: record.data.name, + name_trans: record.data.name_trans, + description: record.data.description, + description_trans: record.data.description_trans, + rank: rank })) { this.fp.getForm().reset(); this.hide(); return true; } } else { - MODx.msg.alert(_('error'),_('user_group_err_ns')); + MODx.msg.alert(_('error'), _('widget_err_ns')); } return true; } }); -Ext.reg('modx-window-dashboard-usergroup-add',MODx.window.DashboardUserGroupAdd); -*/ +Ext.reg('modx-window-dashboard-widget-place', MODx.window.DashboardWidgetPlace); /** * @class MODx.combo.DashboardWidgets @@ -486,28 +442,36 @@ Ext.reg('modx-window-dashboard-usergroup-add',MODx.window.DashboardUserGroupAdd) * @param {Object} config An object of options. * @xtype modx-combo-dashboard-widgets */ -MODx.combo.DashboardWidgets = function(config) { - config = config || {}; - Ext.applyIf(config,{ - name: 'widget' - ,hiddenName: 'widget' - ,displayField: 'name_trans' - ,editable: true - ,valueField: 'id' - ,fields: ['id','name','name_trans','description','description_trans'] - ,pageSize: 20 - ,url: MODx.config.connector_url - ,baseParams: { - action: 'System/Dashboard/Widget/GetList' - ,combo: true - } - ,tpl: new Ext.XTemplate('' - ,'
    ' - ,'

    {name_trans:htmlEncode}

    ' - ,'

    {description_trans:htmlEncode}

    ' - ,'
    ') +MODx.combo.DashboardWidgets = function(config = {}) { + Ext.applyIf(config, { + name: 'widget', + hiddenName: 'widget', + displayField: 'name_trans', + editable: true, + valueField: 'id', + fields: [ + 'id', + 'name', + 'name_trans', + 'description', + 'description_trans' + ], + pageSize: 20, + url: MODx.config.connector_url, + baseParams: { + action: 'System/Dashboard/Widget/GetList', + combo: true + }, + tpl: new Ext.XTemplate(` + +
    +

    {name_trans:htmlEncode}

    +

    {description_trans:htmlEncode}

    +
    +
    + `) }); - MODx.combo.DashboardWidgets.superclass.constructor.call(this,config); + MODx.combo.DashboardWidgets.superclass.constructor.call(this, config); }; -Ext.extend(MODx.combo.DashboardWidgets,MODx.combo.ComboBox); -Ext.reg('modx-combo-dashboard-widgets',MODx.combo.DashboardWidgets); +Ext.extend(MODx.combo.DashboardWidgets, MODx.combo.ComboBox); +Ext.reg('modx-combo-dashboard-widgets', MODx.combo.DashboardWidgets); diff --git a/manager/assets/modext/widgets/system/modx.panel.dashboards.js b/manager/assets/modext/widgets/system/modx.panel.dashboards.js index 1be48b36c5d..99b5f47c06f 100644 --- a/manager/assets/modext/widgets/system/modx.panel.dashboards.js +++ b/manager/assets/modext/widgets/system/modx.panel.dashboards.js @@ -4,44 +4,46 @@ * @param {Object} config An object of configuration properties * @xtype modx-panel-dashboards */ -MODx.panel.Dashboards = function(config) { - config = config || {}; - Ext.applyIf(config,{ - id: 'modx-panel-dashboards' - ,cls: 'container' - ,defaults: { collapsible: false ,autoHeight: true } - ,items: [{ - html: _('dashboards') - ,id: 'modx-dashboards-header' - ,xtype: 'modx-header' - },MODx.getPageStructure([{ - layout: 'form' - ,title: _('dashboards') - ,items: [{ - html: '

    '+_('dashboards.intro_msg')+'

    ' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-dashboards' - ,cls: 'main-wrapper' - ,preventRender: true +MODx.panel.Dashboards = function(config = {}) { + Ext.applyIf(config, { + id: 'modx-panel-dashboards', + cls: 'container', + defaults: { + collapsible: false, + autoHeight: true + }, + items: [{ + html: _('dashboards'), + id: 'modx-dashboards-header', + xtype: 'modx-header' + }, MODx.getPageStructure([{ + layout: 'form', + title: _('dashboards'), + items: [{ + html: `

    ${_('dashboards.intro_msg')}

    `, + xtype: 'modx-description' + }, { + xtype: 'modx-grid-dashboards', + cls: 'main-wrapper', + preventRender: true }] - },{ - layout: 'form' - ,title: _('widgets') - ,items: [{ - html: '

    '+_('widgets.intro_msg')+'

    ' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-dashboard-widgets' - ,cls: 'main-wrapper' - ,preventRender: true + }, { + layout: 'form', + title: _('widgets'), + items: [{ + html: `

    ${_('widgets.intro_msg')}

    `, + xtype: 'modx-description' + }, { + xtype: 'modx-grid-dashboard-widgets', + cls: 'main-wrapper', + preventRender: true }] }])] }); - MODx.panel.Dashboards.superclass.constructor.call(this,config); + MODx.panel.Dashboards.superclass.constructor.call(this, config); }; -Ext.extend(MODx.panel.Dashboards,MODx.FormPanel); -Ext.reg('modx-panel-dashboards',MODx.panel.Dashboards); +Ext.extend(MODx.panel.Dashboards, MODx.FormPanel); +Ext.reg('modx-panel-dashboards', MODx.panel.Dashboards); /** * @class MODx.grid.Dashboards @@ -52,72 +54,101 @@ Ext.reg('modx-panel-dashboards',MODx.panel.Dashboards); MODx.grid.Dashboards = function(config = {}) { const queryValue = this.applyRequestFilter(0, 'query', 'tab', true); this.sm = new Ext.grid.CheckboxSelectionModel(); - Ext.applyIf(config,{ - url: MODx.config.connector_url - ,baseParams: { + Ext.applyIf(config, { + id: 'modx-grid-dashboards', + url: MODx.config.connector_url, + baseParams: { action: 'System/Dashboard/GetList', usergroup: MODx.request.usergroup || null - } - ,fields: [ + }, + fields: [ 'id', 'name', 'description', - 'cls' - ] - ,paging: true - ,autosave: true - ,save_action: 'System/Dashboard/UpdateFromGrid' - ,remoteSort: true - ,sm: this.sm - ,columns: [this.sm,{ - header: _('id') - ,dataIndex: 'id' - ,width: 50 - ,sortable: true - },{ - header: _('name') - ,dataIndex: 'name' - ,width: 150 - ,sortable: true - ,editor: { xtype: 'textfield' ,allowBlank: false } - ,renderer: { fn: function(v,md,record) { - return this.renderLink(v, { - href: '?a=system/dashboards/update&id=' + record.data.id - }); - }, scope: this } - },{ - header: _('description') - ,dataIndex: 'description' - ,width: 300 - ,sortable: false - ,editor: { xtype: 'textarea' } - }] - ,tbar: [ - { - text: _('create') - ,cls:'primary-button' - ,handler: this.createDashboard - ,scope: this - },{ - text: _('bulk_actions') - ,menu: [{ - text: _('selected_remove') - ,handler: this.removeSelected - ,scope: this - }] - },'->',{ - xtype: 'modx-combo-usergroup' - ,itemId: 'filter-usergroup' - ,emptyText: _('user_group_filter') - ,baseParams: { - action: 'Security/Group/GetList' - ,addAll: true + 'creator' + ], + paging: true, + autosave: true, + save_action: 'System/Dashboard/UpdateFromGrid', + remoteSort: true, + sm: this.sm, + columns: [this.sm, { + header: _('id'), + dataIndex: 'id', + width: 50, + sortable: true + }, { + header: _('name'), + dataIndex: 'name', + width: 150, + sortable: true, + editor: { + xtype: 'textfield', + allowBlank: false, + blankText: _('dashboard_err_ns_name'), + validationEvent: 'change', + validator: function(value) { + const grid = Ext.getCmp('modx-grid-dashboards'), + reserved = this.gridEditor.record.json.reserved.name + ; + if (grid.valueIsReserved(reserved, value)) { + const msg = _('dashboard_err_name_reserved', { reservedName: value }); + Ext.Msg.alert(_('error'), msg); + return false; + } + return true; } - ,value: MODx.request.usergroup || null - ,width: 200 - ,listeners: { + }, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record, [record.json.isProtected]); + return this.userCanEditRecord(record) + ? this.renderLink(value, { + href: `?a=system/dashboards/update&id=${record.data.id}`, + title: _('dashboard_edit') + }) + : value + ; + }, + scope: this + } + }, { + header: _('description'), + dataIndex: 'description', + width: 300, + sortable: false, + editor: { + xtype: 'textarea' + }, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses(record, [record.json.isProtected]); + return value; + }, + scope: this + } + }, + this.getCreatorColumnConfig('dashboard') + ], + tbar: [ + this.getCreateButton('dashboard', 'createDashboard'), + this.getBulkActionsButton('dashboard', 'System/Dashboard/RemoveMultiple'), + '->', + { + xtype: 'modx-combo-usergroup', + itemId: 'filter-usergroup', + emptyText: _('user_group_filter'), + baseParams: { + action: 'Security/Group/GetList', + addAll: true + }, + value: MODx.request.usergroup || null, + width: 200, + listeners: { select: { - fn: function (cmp, record, selectedIndex) { + fn: function(cmp, record, selectedIndex) { this.applyGridFilter(cmp, 'usergroup'); }, scope: this @@ -128,103 +159,74 @@ MODx.grid.Dashboards = function(config = {}) { this.getClearFiltersButton('filter-usergroup, filter-query') ] }); - MODx.grid.Dashboards.superclass.constructor.call(this,config); + MODx.grid.Dashboards.superclass.constructor.call(this, config); + + this.gridMenuActions = ['edit', 'delete', 'duplicate']; + + // Note there are currently no action-specific permissions for Dashboards + this.setUserCanEdit(['dashboards']); + this.setUserCanCreate(['dashboards']); + this.setUserCanDelete(['dashboards']); + this.setShowActionsMenu(); + + this.on({ + beforerender: function(grid) { + grid.view = new Ext.grid.GridView(grid.getViewConfig()); + } + }); }; -Ext.extend(MODx.grid.Dashboards,MODx.grid.Grid,{ +Ext.extend(MODx.grid.Dashboards, MODx.grid.Grid, { getMenu: function() { - var r = this.getSelectionModel().getSelected(); - var p = r.data.cls; - - var m = []; - if (this.getSelectionModel().getCount() > 1) { - m.push({ - text: _('selected_remove') - ,handler: this.removeSelected - ,scope: this + const + record = this.getSelectionModel().getSelected(), + menu = [] + ; + if (this.userCanEdit && this.userCanEditRecord(record)) { + menu.push({ + text: _('edit'), + handler: this.updateDashboard }); - } else { - if (p.indexOf('pupdate') != -1) { - m.push({ - text: _('edit') - ,handler: this.updateDashboard - }); - } - if (p.indexOf('pduplicate') != -1) { - m.push({ - text: _('duplicate') - ,handler: this.duplicateDashboard - }); - } - if (p.indexOf('premove') != -1 && r.data.id != 1 && r.data.name != 'Default') { - if (m.length > 0) m.push('-'); - m.push({ - text: _('delete') - ,handler: this.removeDashboard - }); - } } - if (m.length > 0) { - this.addContextMenuItem(m); + if (this.userCanCreate && this.userCanDuplicateRecord(record)) { + menu.push({ + text: _('duplicate'), + handler: this.duplicateDashboard + }); } - } + if (this.userCanDelete && this.userCanDeleteRecord(record)) { + if (menu.length > 0) { + menu.push('-'); + } + menu.push({ + text: _('delete'), + handler: this.confirm.createDelegate(this, ['System/Dashboard/Remove', 'dashboard_remove_confirm']) + }); + } + return menu; + }, - ,createDashboard: function() { + createDashboard: function() { MODx.loadPage('system/dashboards/create'); - } + }, - ,updateDashboard: function() { - MODx.loadPage('system/dashboards/update', 'id='+this.menu.record.id); - } + updateDashboard: function() { + MODx.loadPage('system/dashboards/update', `id=${this.menu.record.id}`); + }, - ,duplicateDashboard: function(btn,e) { + duplicateDashboard: function(btn, e) { MODx.Ajax.request({ - url: this.config.url - ,params: { - action: 'System/Dashboard/Duplicate' - ,id: this.menu.record.id - } - ,listeners: { - 'success': {fn:this.refresh,scope:this} - } - }); - } - - ,removeDashboard: function() { - MODx.msg.confirm({ - title: _('delete') - ,text: _('dashboard_remove_confirm') - ,url: this.config.url - ,params: { - action: 'System/Dashboard/Remove' - ,id: this.menu.record.id - } - ,listeners: { - 'success': {fn:this.refresh,scope:this} - } - }); - } - - ,removeSelected: function() { - var cs = this.getSelectedAsList(); - if (cs === false) return false; - - MODx.msg.confirm({ - title: _('selected_remove') - ,text: _('dashboard_remove_multiple_confirm') - ,url: this.config.url - ,params: { - action: 'System/Dashboard/RemoveMultiple' - ,dashboards: cs - } - ,listeners: { - 'success': {fn:function(r) { - this.getSelectionModel().clearSelections(true); - this.refresh(); - },scope:this} + url: this.config.url, + params: { + action: 'System/Dashboard/Duplicate', + id: this.menu.record.id + }, + listeners: { + success: { + fn: this.refresh, + scope: this + } } }); - return true; } - }); -Ext.reg('modx-grid-dashboards',MODx.grid.Dashboards); +Ext.reg('modx-grid-dashboards', MODx.grid.Dashboards); diff --git a/manager/assets/modext/workspace/lexicon/lexicon.grid.js b/manager/assets/modext/workspace/lexicon/lexicon.grid.js index 6b074fa3c78..8eaa1053c54 100644 --- a/manager/assets/modext/workspace/lexicon/lexicon.grid.js +++ b/manager/assets/modext/workspace/lexicon/lexicon.grid.js @@ -11,10 +11,10 @@ MODx.grid.Lexicon = function(config = {}) { this.topicFilterValue = MODx.util.url.getParamValue('topic') || 'default'; this.namespaceFilterValue = MODx.util.url.getParamValue('ns') || 'core'; - Ext.applyIf(config,{ - id: 'modx-grid-lexicon' - ,url: MODx.config.connector_url - ,fields: [ + Ext.applyIf(config, { + id: 'modx-grid-lexicon', + url: MODx.config.connector_url, + fields: [ 'name', 'value', 'namespace', @@ -22,47 +22,56 @@ MODx.grid.Lexicon = function(config = {}) { 'language', 'editedon', 'overridden' - ] - ,baseParams: { + ], + baseParams: { action: 'Workspace/Lexicon/GetList', namespace: this.namespaceFilterValue, topic: this.topicFilterValue, language: this.languageFilterValue - } - ,paging: true - ,autosave: true - ,save_action: 'Workspace/Lexicon/UpdateFromGrid' - ,columns: [{ - header: _('name') - ,dataIndex: 'name' - ,width: 200 - ,sortable: true - ,renderer: this._renderStatus - },{ - header: _('value') - ,dataIndex: 'value' - ,width: 500 - ,sortable: false - ,editor: {xtype: 'textarea'} - ,renderer: this._renderStatus - },{ - header: _('last_modified') - ,dataIndex: 'editedon' - ,width: 125 - }] - ,tbar: { + }, + paging: true, + autosave: true, + preventSaveRefresh: false, + save_action: 'Workspace/Lexicon/UpdateFromGrid', + columns: [{ + header: _('name'), + dataIndex: 'name', + width: 200, + sortable: true, + renderer: this._renderStatus + }, { + header: _('value'), + dataIndex: 'value', + width: 500, + sortable: false, + editor: { + xtype: 'textarea' + }, + renderer: this._renderStatus + }, { + header: _('last_modified'), + dataIndex: 'editedon', + width: 125, + renderer: this._renderLastModDate + }], + tbar: { cls: 'has-nested-filters', items: [ + this.getCreateButton('lexicon', 'createEntry'), { - xtype: 'button' - ,text: _('create') - ,cls: 'primary-button' - ,handler: this.createEntry - ,scope: this - },{ - text: _('lexicon_revert') - ,handler: this.reloadFromBase - ,scope: this + text: _('lexicon_revert'), + handler: this.reloadFromBase, + scope: this, + listeners: { + render: { + fn: function(btn) { + if (!this.userCanEdit) { + btn.hide(); + } + }, + scope: this + } + } }, '->', { @@ -78,8 +87,7 @@ MODx.grid.Lexicon = function(config = {}) { { xtype: 'label', html: _('namespace') - }, - { + }, { xtype: 'modx-combo-namespace', itemId: 'filter-namespace', hideLabel: true, @@ -127,8 +135,7 @@ MODx.grid.Lexicon = function(config = {}) { { xtype: 'label', html: _('language') - }, - { + }, { xtype: 'modx-combo-language', itemId: 'filter-language', hideLabel: true, @@ -177,8 +184,7 @@ MODx.grid.Lexicon = function(config = {}) { { xtype: 'label', html: _('topic') - }, - { + }, { xtype: 'modx-combo-lexicon-topic', itemId: 'filter-topic', hideLabel: true, @@ -219,110 +225,125 @@ MODx.grid.Lexicon = function(config = {}) { ] } }); - MODx.grid.Lexicon.superclass.constructor.call(this,config); + MODx.grid.Lexicon.superclass.constructor.call(this, config); + + this.gridMenuActions = ['edit']; + + // Note there are currently no action-specific permissions for Lexicons + this.setUserCanCreate(['lexicons']); + this.setUserCanEdit(['lexicons']); + this.setUserCanDelete(['lexicons']); + this.setShowActionsMenu(); }; -Ext.extend(MODx.grid.Lexicon,MODx.grid.Grid,{ - console: null +Ext.extend(MODx.grid.Lexicon, MODx.grid.Grid, { + console: null, - ,_renderStatus: function(v,md,rec,ri) { - switch (rec.data.overridden) { + _renderStatus: function(value, metaData, record, rowIndex) { + switch (record.data.overridden) { case 1: - return ''+v+'';break; + return `${value}`; case 2: - return ''+v+''; + return `${value}`; default: - return ''+v+''; + return `${value}`; } - } + }, /** * @deprecated since 3.0.5. To be removed in future release. Datetime formatting * now handled in back end processors to provide uniform display across components. */ - ,_renderLastModDate: function(value) { + _renderLastModDate: function(value) { return value; - } + }, - ,loadWindow2: function(btn,e,o) { + loadWindow2: function(btn, e, o) { this.menu.record = { namespace: this.getFilterComponent('filter-namespace').getValue(), language: this.getFilterComponent('filter-language').getValue() }; - if (o.xtype != 'modx-window-lexicon-import') { + if (o.xtype !== 'modx-window-lexicon-import') { this.menu.record.topic = this.getFilterComponent('filter-topic').getValue(); } this.loadWindow(btn, e, o); - } + }, - ,reloadFromBase: function() { - namespace = this.getFilterComponent('filter-namespace').getValue(), - topic = this.getFilterComponent('filter-topic').getValue(), - language = this.getFilterComponent('filter-language').getValue(), - registryTopic = '/workspace/lexicon/reload/'; + reloadFromBase: function() { + const + namespace = this.getFilterComponent('filter-namespace').getValue(), + topic = this.getFilterComponent('filter-topic').getValue(), + language = this.getFilterComponent('filter-language').getValue(), + registryTopic = '/workspace/lexicon/reload/' + ; MODx.msg.confirm({ text: _('lexicon_revert_confirm', { - namespace: namespace - ,topic: topic - ,language: language - }) - ,url: this.config.url - ,params: { - action: 'Workspace/Lexicon/ReloadFromBase' - ,register: 'mgr' - ,topic: registryTopic - ,namespace: namespace - ,lexiconTopic: topic - ,language: language - } - ,listeners: { - 'success': { - fn:function() { + namespace: namespace, + topic: topic, + language: language + }), + url: this.config.url, + params: { + action: 'Workspace/Lexicon/ReloadFromBase', + register: 'mgr', + topic: registryTopic, + namespace: namespace, + lexiconTopic: topic, + language: language + }, + listeners: { + success: { + fn: function() { this.console = MODx.load({ - xtype: 'modx-console' - ,register: 'mgr' - ,topic: registryTopic + xtype: 'modx-console', + register: 'mgr', + topic: registryTopic }); - this.console.on('complete',function(){ + this.console.on('complete', function() { this.refresh(); - },this); + }, this); this.console.show(Ext.getBody()); - } - ,scope:this + }, + scope: this } } }); - } + }, - ,revertEntry: function() { - var p = this.menu.record; - p.action = 'Workspace/Lexicon/Revert'; + revertEntry: function() { + const { record } = this.menu; + record.action = 'Workspace/Lexicon/Revert'; MODx.Ajax.request({ - url: this.config.url - ,params: p - ,listeners: { - 'success': {fn:function(r) { - this.refresh(); - },scope:this} + url: this.config.url, + params: record, + listeners: { + success: { + fn: function(r) { + this.refresh(); + }, + scope: this + } } }); - } + }, - ,getMenu: function() { - var r = this.getSelectionModel().getSelected(); - var m = []; - if (r.data.overridden) { - m.push({ - text: _('entry_revert') - ,handler: this.revertEntry + getMenu: function() { + const + record = this.getSelectionModel().getSelected(), + menu = [] + ; + if (record.data.overridden) { + menu.push({ + text: _('entry_revert'), + handler: this.revertEntry }); } - return m; - } + return menu; + }, - ,createEntry: function(btn, e) { + createEntry: function(btn, e) { const record = this.menu.record || {}; record.namespace = this.getFilterComponent('filter-namespace').getValue(); @@ -348,64 +369,49 @@ Ext.extend(MODx.grid.Lexicon,MODx.grid.Grid,{ this.createEntryWindow.show(e.target); } }); -Ext.reg('modx-grid-lexicon',MODx.grid.Lexicon); +Ext.reg('modx-grid-lexicon', MODx.grid.Lexicon); -MODx.window.LexiconEntryCreate = function(config) { - config = config || {}; - this.ident = config.ident || 'lexentc'+Ext.id(); - var r = config.record; - Ext.applyIf(config,{ - title: _('create') - ,url: MODx.config.connector_url - ,action: 'Workspace/Lexicon/Create' - ,fileUpload: true - ,fields: [{ - xtype: 'textfield' - ,fieldLabel: _('name') - ,id: 'modx-'+this.ident+'-name' - ,itemId: 'name' - ,name: 'name' - ,anchor: '100%' - ,msgTarget: 'under' - ,allowBlank: false - },{ - xtype: 'modx-combo-namespace' - ,fieldLabel: _('namespace') - ,name: 'namespace' - ,id: 'modx-'+this.ident+'-namespace' - ,itemId: 'namespace' - ,anchor: '100%' - ,msgTarget: 'under' - ,allowBlank: false - },{ - xtype: 'modx-combo-lexicon-topic' - ,fieldLabel: _('topic') - ,name: 'topic' - ,id: 'modx-'+this.ident+'-topic' - ,itemId: 'topic' - ,anchor: '100%' - ,msgTarget: 'under' - ,allowBlank: false - },{ - xtype: 'modx-combo-language' - ,fieldLabel: _('language') - ,name: 'language' - ,id: 'modx-'+this.ident+'-language' - ,itemId: 'language' - ,anchor: '100%' - ,msgTarget: 'under' - ,allowBlank: false - },{ - xtype: 'textarea' - ,fieldLabel: _('value') - ,id: 'modx-'+this.ident+'-value' - ,itemId: 'value' - ,name: 'value' - ,anchor: '100%' - ,msgTarget: 'under' +MODx.window.LexiconEntryCreate = function(config = {}) { + this.ident = config.ident || `lexentc${Ext.id()}`; + Ext.applyIf(config, { + title: _('create'), + url: MODx.config.connector_url, + action: 'Workspace/Lexicon/Create', + fileUpload: true, + formDefaults: { + anchor: '100%', + msgTarget: 'under', + allowBlank: false + }, + fields: [{ + xtype: 'textfield', + fieldLabel: _('name'), + itemId: 'name', + name: 'name' + }, { + xtype: 'modx-combo-namespace', + fieldLabel: _('namespace'), + name: 'namespace', + itemId: 'namespace' + }, { + xtype: 'modx-combo-lexicon-topic', + fieldLabel: _('topic'), + name: 'topic', + itemId: 'topic' + }, { + xtype: 'modx-combo-language', + fieldLabel: _('language'), + name: 'language', + itemId: 'language' + }, { + xtype: 'textarea', + fieldLabel: _('value'), + itemId: 'value', + name: 'value', + allowBlank: true }] }); - MODx.window.LexiconEntryCreate.superclass.constructor.call(this,config); + MODx.window.LexiconEntryCreate.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.LexiconEntryCreate,MODx.Window); -Ext.reg('modx-window-lexicon-entry-create',MODx.window.LexiconEntryCreate); +Ext.extend(MODx.window.LexiconEntryCreate, MODx.Window); +Ext.reg('modx-window-lexicon-entry-create', MODx.window.LexiconEntryCreate); diff --git a/manager/assets/modext/workspace/namespace/modx.namespace.panel.js b/manager/assets/modext/workspace/namespace/modx.namespace.panel.js index 90aaaba74e7..82cfed4cca5 100644 --- a/manager/assets/modext/workspace/namespace/modx.namespace.panel.js +++ b/manager/assets/modext/workspace/namespace/modx.namespace.panel.js @@ -6,34 +6,41 @@ * @param {Object} config An object of configuration properties * @xtype modx-panel-namespaces */ -MODx.panel.Namespaces = function(config) { - config = config || {}; - Ext.applyIf(config,{ - id: 'modx-panel-namespaces' - ,cls: 'container' - ,bodyStyle: '' - ,defaults: { collapsible: false ,autoHeight: true } - ,items: [{ - html: _('namespaces') - ,id: 'modx-namespaces-header' - ,xtype: 'modx-header' - },MODx.getPageStructure([{ - title: _('namespaces') - ,layout: 'form' - ,items: [{ - html: '

    '+_('namespaces_desc')+'

    ' - ,xtype: 'modx-description' - },{ - xtype: 'modx-grid-namespace' - ,cls:'main-wrapper' - ,preventRender: true - }] - }])] +MODx.panel.Namespaces = function(config = {}) { + Ext.applyIf(config, { + id: 'modx-panel-namespaces', + cls: 'container', + bodyStyle: '', + defaults: { + collapsible: false, + autoHeight: true + }, + items: [ + { + html: _('namespaces'), + id: 'modx-namespaces-header', + xtype: 'modx-header' + }, + MODx.getPageStructure([{ + title: _('namespaces'), + layout: 'form', + items: [ + { + html: `

    ${_('namespaces_desc')}

    `, + xtype: 'modx-description' + }, { + xtype: 'modx-grid-namespace', + cls: 'main-wrapper', + preventRender: true + } + ] + }]) + ] }); - MODx.panel.Namespaces.superclass.constructor.call(this,config); + MODx.panel.Namespaces.superclass.constructor.call(this, config); }; -Ext.extend(MODx.panel.Namespaces,MODx.FormPanel); -Ext.reg('modx-panel-namespaces',MODx.panel.Namespaces); +Ext.extend(MODx.panel.Namespaces, MODx.FormPanel); +Ext.reg('modx-panel-namespaces', MODx.panel.Namespaces); /** * Loads a grid for managing namespaces. @@ -43,121 +50,157 @@ Ext.reg('modx-panel-namespaces',MODx.panel.Namespaces); * @param {Object} config An object of configuration properties * @xtype modx-grid-namespace */ -MODx.grid.Namespace = function(config) { - config = config || {}; +MODx.grid.Namespace = function(config = {}) { this.sm = new Ext.grid.CheckboxSelectionModel(); - Ext.applyIf(config,{ - url: MODx.config.connector_url - ,baseParams: { + Ext.applyIf(config, { + id: 'modx-grid-namespaces', + url: MODx.config.connector_url, + baseParams: { action: 'Workspace/PackageNamespace/GetList' - } - ,fields: [ - 'id', + }, + fields: [ 'name', 'path', 'assets_path', 'perm' - ] - ,anchor: '100%' - ,paging: true - ,autosave: true - ,save_action: 'Workspace/PackageNamespace/UpdateFromGrid' - ,primaryKey: 'name' - ,remoteSort: true - ,sm: this.sm - ,columns: [this.sm,{ - header: _('name') - ,dataIndex: 'name' - ,width: 200 - ,sortable: true - },{ - header: _('namespace_path') - ,dataIndex: 'path' - ,width: 500 - ,sortable: false - ,editor: { xtype: 'textfield' } - },{ - header: _('namespace_assets_path') - ,dataIndex: 'assets_path' - ,width: 500 - ,sortable: false - ,editor: { xtype: 'textfield' } - }] - ,tbar: [ - { - text: _('create') - ,handler: { xtype: 'modx-window-namespace-create' ,blankValues: true } - ,cls:'primary-button' - ,scope: this + ], + anchor: '100%', + paging: true, + autosave: true, + save_action: 'Workspace/PackageNamespace/UpdateFromGrid', + primaryKey: 'name', + remoteSort: true, + sm: this.sm, + columns: [this.sm, { + header: _('name'), + dataIndex: 'name', + width: 200, + sortable: true, + // because PK is name, allowing edit is tricky as implemented; leave for now + listeners: { + click: { + fn: function(column, grid, rowIndex, e) { + if (e.target.classList.contains('simulated-link')) { + this.updateNamespace(e); + } + }, + scope: this + } + } + }, { + header: _('namespace_path'), + dataIndex: 'path', + width: 500, + sortable: false, + editor: { + xtype: 'textfield' }, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses( + record, + [record.json.isProtected], + '', + false + ); + return value; + }, + scope: this + } + }, { + header: _('namespace_assets_path'), + dataIndex: 'assets_path', + width: 500, + sortable: false, + editor: { + xtype: 'textfield' + }, + renderer: { + fn: function(value, metaData, record) { + // eslint-disable-next-line no-param-reassign + metaData.css = this.setEditableCellClasses( + record, + [record.json.isProtected], + '', + false + ); + return value; + }, + scope: this + } + } + ], + tbar: [ + this.getCreateButton('namespace', { + xtype: 'modx-window-namespace-create', + blankValues: true + }), + this.getBulkActionsButton('namespace', 'Workspace/PackageNamespace/RemoveMultiple', 'string'), '->', this.getQueryFilterField(), this.getClearFiltersButton() - ] + ], + viewConfig: this.getViewConfig() + }); + MODx.grid.Namespace.superclass.constructor.call(this, config); + + this.gridMenuActions = ['edit', 'delete']; + + // Note there are currently no action-specific permissions for Namespaces + this.setUserCanEdit(['namespaces']); + this.setUserCanCreate(['namespaces']); + this.setUserCanDelete(['namespaces']); + this.setShowActionsMenu(); + + this.on({ + beforeedit: function(e) { + if (!this.userCanEditRecord(e.record) || e.record.json.isProtected) { + return false; + } + } }); - MODx.grid.Namespace.superclass.constructor.call(this,config); }; -Ext.extend(MODx.grid.Namespace,MODx.grid.Grid,{ +Ext.extend(MODx.grid.Namespace, MODx.grid.Grid, { + getMenu: function() { - var r = this.getSelectionModel().getSelected(); - var p = r.data.perm; - var m = []; - if (this.getSelectionModel().getCount() > 1) { - m.push({ - text: _('selected_remove') - ,handler: this.removeSelected - ,scope: this - }); - } else { - m.push({ - text: _('edit') - ,handler: this.namespaceUpdate + const record = this.getSelectionModel().getSelected(), + menu = [] + ; + if (this.userCanEdit && this.userCanEditRecord(record)) { + menu.push({ + text: _('edit'), + handler: this.updateNamespace }); - if (p.indexOf('premove') != -1 && this.menu.record.name != 'core') { - m.push({ - text: _('delete') - ,handler: this.remove.createDelegate(this,['namespace_remove_confirm','Workspace/PackageNamespace/Remove']) - }); + } + if (this.userCanDelete && this.userCanEditRecord(record)) { + if (menu.length > 0) { + menu.push('-'); } + menu.push({ + text: _('delete'), + handler: this.remove.createDelegate(this, ['namespace_remove_confirm', 'Workspace/PackageNamespace/Remove']) + }); } - return m; - } + return menu; + }, - ,namespaceUpdate: function(elem, vent) { - var win = MODx.load({ - xtype: 'modx-window-namespace-update' - ,record: this.menu.record - ,listeners: { - success: { - fn: this.refresh - ,scope: this + updateNamespace: function(e) { + const + record = this.getSelectionModel().getSelected().data, + window = MODx.load({ + xtype: 'modx-window-namespace-update', + record: record, + listeners: { + success: { + fn: this.refresh, + scope: this + } } - } - }); - win.setValues(this.menu.record); - win.show(vent.target); - } - - ,removeSelected: function() { - var cs = this.getSelectedAsList(); - if (cs === false) return false; - - MODx.msg.confirm({ - title: _('selected_remove') - ,text: _('namespace_remove_multiple_confirm') - ,url: this.config.url - ,params: { - action: 'Workspace/PackageNamespace/RemoveMultiple' - ,namespaces: cs - } - ,listeners: { - 'success': {fn:function(r) { - this.getSelectionModel().clearSelections(true); - this.refresh(); - },scope:this} - } - }); - return true; + }) + ; + window.setValues(record); + window.show(e.target); } }); -Ext.reg('modx-grid-namespace',MODx.grid.Namespace); +Ext.reg('modx-grid-namespace', MODx.grid.Namespace); diff --git a/manager/assets/modext/workspace/package/package.versions.grid.js b/manager/assets/modext/workspace/package/package.versions.grid.js index eac7118d076..3a4287ce4f5 100644 --- a/manager/assets/modext/workspace/package/package.versions.grid.js +++ b/manager/assets/modext/workspace/package/package.versions.grid.js @@ -1,107 +1,150 @@ -MODx.grid.PackageVersions = function(config) { - config = config || {}; +MODx.grid.PackageVersions = function(config = {}) { this.exp = new Ext.grid.RowExpander({ - tpl : new Ext.Template( + tpl: new Ext.Template( '

    {readme}

    ' ) }); - Ext.applyIf(config,{ - title: _('packages') - ,id: 'modx-grid-package-versions' - ,url: MODx.config.connector_url - ,baseParams: { - action: 'Workspace/Packages/Version/GetList' - ,signature: config.signature - ,package_name: MODx.request.package_name - } - ,fields: ['signature','name','version','release','created','updated','installed','state' - ,'workspace','provider','provider_name','disabled','source' - ,'readme','menu'] - ,plugins: [this.exp] - ,pageSize: 20 - ,columns: [this.exp,{ - header: _('name') ,dataIndex: 'name' } - ,{ header: _('version') ,dataIndex: 'version' } - ,{ header: _('release') ,dataIndex: 'release' } - ,{ header: _('installed') ,dataIndex: 'installed' ,renderer: this._rins } - ,{ - header: _('provider') - ,dataIndex: 'provider_name' - ,editable: false - }] - ,primaryKey: 'signature' - ,paging: true - ,autosave: true - ,tbar: [{ - text: _('package_versions_purge') - ,handler: this.purgePackageVersions + Ext.applyIf(config, { + title: _('packages'), + id: 'modx-grid-package-versions', + url: MODx.config.connector_url, + baseParams: { + action: 'Workspace/Packages/Version/GetList', + signature: config.signature, + package_name: MODx.request.package_name + }, + fields: [ + 'signature', + 'name', + 'version', + 'release', + 'created', + 'updated', + 'installed', + 'state', + 'workspace', + 'provider', + 'provider_name', + 'disabled', + 'source', + 'readme', + 'menu' + ], + plugins: [this.exp], + pageSize: 20, + columns: [this.exp, + { + header: _('name'), + dataIndex: 'name' + }, { + header: _('version'), + dataIndex: 'version' + }, { + header: _('release'), + dataIndex: 'release' + }, { + header: _('installed'), + dataIndex: 'installed', + renderer: this._rins + }, { + header: _('provider'), + dataIndex: 'provider_name', + editable: false + }], + primaryKey: 'signature', + paging: true, + autosave: true, + tbar: [{ + text: _('package_versions_purge'), + handler: this.purgePackageVersions, + listeners: { + render: { + fn: function(btn) { + if (!this.userCanDelete) { + btn.hide(); + } + }, + scope: this + } + } }] }); - MODx.grid.PackageVersions.superclass.constructor.call(this,config); + MODx.grid.PackageVersions.superclass.constructor.call(this, config); + + this.gridMenuActions = ['delete']; + + this.setUserCanDelete(['packages']); + this.setShowActionsMenu(); }; -Ext.extend(MODx.grid.PackageVersions,MODx.grid.Grid,{ +Ext.extend(MODx.grid.PackageVersions, MODx.grid.Grid, { _rins: function(value, metaData) { if (Ext.isEmpty(value) || value.includes(_('not_installed'))) { metaData.css = 'not-installed'; } return value; - } + }, - ,removePriorVersion: function(btn,e) { - var r = this.menu.record; + removePriorVersion: function(btn, e) { + const { record } = this.menu; MODx.msg.confirm({ - title: _('package_version_remove') - ,text: _('package_version_remove_confirm') - ,url: this.config.url - ,params: { - action: 'Workspace/Packages/Version/Remove' - ,signature: r.signature - } - ,listeners: { - 'success': {fn:function() { - if (this.fireEvent('afterRemoveRow',r)) { - this.removeActiveRow(r); - } - },scope:this} + title: _('package_version_remove'), + text: _('package_version_remove_confirm'), + url: this.config.url, + params: { + action: 'Workspace/Packages/Version/Remove', + signature: record.signature + }, + listeners: { + success: { + fn: function() { + if (this.fireEvent('afterRemoveRow', record)) { + this.removeActiveRow(record); + } + }, + scope: this + } } }); - } + }, /* Purge old package versions */ - ,purgePackageVersions: function(btn,e) { - var topic = '/Workspace/Packages/Purge/'; + purgePackageVersions: function(btn, e) { + const topic = '/Workspace/Packages/Purge/'; - this.loadWindow(btn,e,{ - xtype: 'modx-window-package-versions-purge' - ,record: { - packagename: this.config.package_name - ,topic: topic - ,register: 'mgr' - } - ,listeners: { - success: {fn: function(o) { - this.refresh(); - },scope:this} + this.loadWindow(btn, e, { + xtype: 'modx-window-package-versions-purge', + record: { + packagename: this.config.package_name, + topic: topic, + register: 'mgr' + }, + listeners: { + success: { + fn: function(o) { + this.refresh(); + }, + scope: this + } } }); - } + }, /* Load the console */ - ,loadConsole: function(btn,topic) { + loadConsole: function(btn, topic) { this.console = MODx.load({ - xtype: 'modx-console' - ,register: 'mgr' - ,topic: topic + xtype: 'modx-console', + register: 'mgr', + topic: topic }); this.console.show(btn); - } + }, - ,getConsole: function() { + getConsole: function() { return this.console; } }); -Ext.reg('modx-grid-package-versions',MODx.grid.PackageVersions); +Ext.reg('modx-grid-package-versions', MODx.grid.PackageVersions); /** * @class MODx.window.PurgePackageVersions @@ -109,53 +152,55 @@ Ext.reg('modx-grid-package-versions',MODx.grid.PackageVersions); * @param {Object} config An object of configuration parameters * @xtype modx-window-package-versions-purge */ -MODx.window.PurgePackageVersions = function(config) { - config = config || {}; - Ext.applyIf(config,{ - title: _('package_versions_purge') - ,url: MODx.config.connector_url - ,baseParams: { +MODx.window.PurgePackageVersions = function(config = {}) { + Ext.applyIf(config, { + title: _('package_versions_purge'), + url: MODx.config.connector_url, + baseParams: { action: 'Workspace/Packages/Purge' - } - ,cls: 'modx-confirm' - ,defaults: { border: false } - ,fields: [{ - xtype: 'hidden' - ,name: 'packagename' - ,id: 'modx-ppack-package_name' - ,value: config.packagename - },{ + }, + cls: 'modx-confirm', + defaults: { border: false }, + fields: [{ + xtype: 'hidden', + name: 'packagename', + id: 'modx-ppack-package_name', + value: config.packagename + }, { html: _('package_versions_purge_confirm') - }] - ,saveBtnText: _('package_versions_purge') + }], + saveBtnText: _('package_versions_purge') }); - MODx.window.PurgePackageVersions.superclass.constructor.call(this,config); + MODx.window.PurgePackageVersions.superclass.constructor.call(this, config); }; -Ext.extend(MODx.window.PurgePackageVersions,MODx.Window,{ +Ext.extend(MODx.window.PurgePackageVersions, MODx.Window, { submit: function() { - var r = this.config.record; + const { record } = this.config; if (this.fp.getForm().isValid()) { - Ext.getCmp('modx-grid-package-versions').loadConsole(Ext.getBody(),r.topic); + Ext.getCmp('modx-grid-package-versions').loadConsole(Ext.getBody(), record.topic); this.fp.getForm().baseParams = { - action: 'Workspace/Packages/Purge' - ,register: 'mgr' - ,topic: r.topic + action: 'Workspace/Packages/Purge', + register: 'mgr', + topic: record.topic }; this.fp.getForm().submit({ - waitMsg: _('saving') - ,scope: this - ,failure: function(frm,a) { - this.fireEvent('failure',frm,a); - var g = Ext.getCmp('modx-grid-package-versions'); + waitMsg: _('saving'), + scope: this, + failure: function(frm, a) { + this.fireEvent('failure', frm, a); + const g = Ext.getCmp('modx-grid-package-versions'); g.getConsole().fireEvent('complete'); g.refresh(); Ext.Msg.hide(); this.hide(); - } - ,success: function(frm,a) { - this.fireEvent('success',{f:frm,a:a}); - var g = Ext.getCmp('modx-grid-package-versions'); + }, + success: function(frm, a) { + this.fireEvent('success', { + f: frm, + a: a + }); + const g = Ext.getCmp('modx-grid-package-versions'); g.getConsole().fireEvent('complete'); g.refresh(); Ext.Msg.hide(); @@ -165,4 +210,4 @@ Ext.extend(MODx.window.PurgePackageVersions,MODx.Window,{ } } }); -Ext.reg('modx-window-package-versions-purge',MODx.window.PurgePackageVersions); +Ext.reg('modx-window-package-versions-purge', MODx.window.PurgePackageVersions); diff --git a/manager/controllers/default/security/user/index.class.php b/manager/controllers/default/security/user/index.class.php index ed940141a0d..cbe0fd24972 100644 --- a/manager/controllers/default/security/user/index.class.php +++ b/manager/controllers/default/security/user/index.class.php @@ -1,4 +1,5 @@ modx->hasPermission('edit_user'); + return $this->modx->hasPermission('view_user'); } /** diff --git a/manager/controllers/default/source/update.class.php b/manager/controllers/default/source/update.class.php index cb31f33b31e..d5ceaaaf6b5 100644 --- a/manager/controllers/default/source/update.class.php +++ b/manager/controllers/default/source/update.class.php @@ -1,4 +1,5 @@ modx->hasPermission('source_edit'); } @@ -40,18 +43,28 @@ public function checkPermissions() { * Register custom CSS/JS for the page * @return void */ - public function loadCustomCssJs() { - $mgrUrl = $this->modx->getOption('manager_url',null,MODX_MANAGER_URL); - $this->addJavascript($mgrUrl.'assets/modext/widgets/core/modx.grid.local.property.js'); - $this->addJavascript($mgrUrl.'assets/modext/widgets/source/modx.grid.source.properties.js'); - $this->addJavascript($mgrUrl.'assets/modext/widgets/source/modx.grid.source.access.js'); - $this->addJavascript($mgrUrl.'assets/modext/widgets/source/modx.panel.source.js'); - $this->addJavascript($mgrUrl.'assets/modext/sections/source/update.js'); - $this->addHtml(''); + public function loadCustomCssJs() + { + $mgrUrl = $this->modx->getOption('manager_url', null, MODX_MANAGER_URL); + $this->addJavascript($mgrUrl . 'assets/modext/widgets/core/modx.grid.local.property.js'); + $this->addJavascript($mgrUrl . 'assets/modext/widgets/source/modx.grid.source.properties.js'); + $this->addJavascript($mgrUrl . 'assets/modext/widgets/source/modx.grid.source.access.js'); + $this->addJavascript($mgrUrl . 'assets/modext/widgets/source/modx.panel.source.js'); + $this->addJavascript($mgrUrl . 'assets/modext/sections/source/update.js'); + $record = $this->modx->toJSON($this->sourceArray); + $defaultProps = $this->modx->toJSON($this->sourceDefaultProperties); + $pageCmp = << + Ext.onReady(function() { + MODx.load({ + xtype: 'modx-page-source-update', + record: {$record}, + defaultProperties: {$defaultProps} + }); + }); + +CMP; + $this->addHtml($pageCmp); } /** @@ -59,14 +72,24 @@ public function loadCustomCssJs() { * @param array $scriptProperties * @return mixed */ - public function process(array $scriptProperties = []) { + public function process(array $scriptProperties = []) + { if (empty($this->scriptProperties['id']) || strlen($this->scriptProperties['id']) !== strlen((int)$this->scriptProperties['id'])) { return $this->failure($this->modx->lexicon('source_err_ns')); } $this->source = $this->modx->getObject(modMediaSource::class, ['id' => $this->scriptProperties['id']]); - if (empty($this->source)) return $this->failure($this->modx->lexicon('source_err_nf')); + if (empty($this->source)) { + return $this->failure($this->modx->lexicon('source_err_nf')); + } $this->sourceArray = $this->source->toArray(); + + $coreSources = modMediaSource::getCoreSources(); + $sourceKey = $this->sourceArray['name']; + if (in_array($sourceKey, $coreSources)) { + $this->sourceArray['isProtected'] = true; + $this->sourceArray['reserved'] = true; + } $this->getProperties(); $this->getAccess(); @@ -75,7 +98,8 @@ public function process(array $scriptProperties = []) { return []; } - public function getProperties() { + public function getProperties() + { $properties = $this->source->getProperties(); $data = []; foreach ($properties as $property) { @@ -94,7 +118,8 @@ public function getProperties() { $this->sourceArray['properties'] = $data; } - public function getDefaultProperties() { + public function getDefaultProperties() + { $default = $this->source->getDefaultProperties(); $default = $this->source->prepareProperties($default); $data = []; @@ -115,7 +140,8 @@ public function getDefaultProperties() { return $data; } - public function getAccess() { + public function getAccess() + { $c = $this->modx->newQuery(modAccessMediaSource::class); $c->innerJoin(modMediaSource::class, 'Target'); $c->innerJoin(modAccessPolicy::class, 'Policy'); @@ -131,7 +157,7 @@ public function getAccess() { 'policy_name' => 'Policy.name', 'authority_name' => 'MinimumRole.name', ]); - $acls = $this->modx->getCollection(modAccessMediaSource::class,$c); + $acls = $this->modx->getCollection(modAccessMediaSource::class, $c); $access = []; /** @var modAccessMediaSource $acl */ foreach ($acls as $acl) { @@ -158,15 +184,17 @@ public function getAccess() { * * @return string */ - public function getPageTitle() { - return $this->modx->lexicon('source').': '.$this->sourceArray['name']; + public function getPageTitle() + { + return $this->modx->lexicon('source') . ': ' . $this->sourceArray['name']; } /** * Return the location of the template file * @return string */ - public function getTemplateFile() { + public function getTemplateFile() + { return ''; } @@ -174,7 +202,8 @@ public function getTemplateFile() { * Specify the language topics to load * @return array */ - public function getLanguageTopics() { + public function getLanguageTopics() + { return ['source','namespace','propertyset']; } @@ -182,7 +211,8 @@ public function getLanguageTopics() { * Get the Help URL * @return string */ - public function getHelpUrl() { + public function getHelpUrl() + { return 'Media+Sources'; } } diff --git a/manager/controllers/default/system/dashboards/update.class.php b/manager/controllers/default/system/dashboards/update.class.php index f5aaaaeecda..88daf5c8c95 100644 --- a/manager/controllers/default/system/dashboards/update.class.php +++ b/manager/controllers/default/system/dashboards/update.class.php @@ -1,4 +1,5 @@ modx->hasPermission('dashboards'); } @@ -40,7 +43,8 @@ public function checkPermissions() { * * @return array */ - public function process(array $scriptProperties = []) { + public function process(array $scriptProperties = []) + { if (empty($this->scriptProperties['id']) || strlen($this->scriptProperties['id']) !== strlen((int)$this->scriptProperties['id'])) { $this->failure($this->modx->lexicon('dashboard_err_ns')); return []; @@ -52,37 +56,49 @@ public function process(array $scriptProperties = []) { } $this->dashboardArray = $this->dashboard->toArray(); + + $coreDashboards = modDashboard::getCoreDashboards(); + $dashboardKey = $this->dashboardArray['name']; + if (in_array($dashboardKey, $coreDashboards)) { + $this->dashboardArray['isProtected'] = true; + $this->dashboardArray['reserved'] = true; + } + $this->dashboardArray['widgets'] = $this->getWidgets(); return $this->dashboardArray; - } /** * Get all the Widgets placed on this Dashboard * @return array */ - public function getWidgets() { + public function getWidgets() + { $c = $this->modx->newQuery(modDashboardWidgetPlacement::class); $c->where([ 'dashboard' => $this->dashboard->get('id'), 'user' => 0, ]); - $c->sortby('modDashboardWidgetPlacement.rank','ASC'); + $c->sortby('modDashboardWidgetPlacement.rank', 'ASC'); $placements = $this->modx->getCollection(modDashboardWidgetPlacement::class, $c); $list = []; /** @var modDashboardWidgetPlacement $placement */ foreach ($placements as $placement) { $placement->getOne('Widget'); - if (!($placement->Widget instanceof modDashboardWidget)) { continue; } - if ($placement->Widget->get('lexicon') != 'core:dashboards') { $this->modx->lexicon->load($placement->Widget->get('lexicon')); } $widgetArray = $placement->Widget->toArray(); + // Currently Dashboards do not have action-specific permissions, so hard code them + // here to true since view permission is needed to get to this point + $widgetArray['permissions'] = [ + 'edit' => true, + 'delete' => true + ]; $list[] = [ $placement->get('dashboard'), $placement->get('widget'), @@ -91,6 +107,7 @@ public function getWidgets() { $widgetArray['name_trans'], $widgetArray['description'], $widgetArray['description_trans'], + $widgetArray['permissions'] ]; } return $list; @@ -100,7 +117,8 @@ public function getWidgets() { * Get all the User Groups assigned to this Dashboard * @return array */ - public function getUserGroups() { + public function getUserGroups() + { $list = []; $c = $this->modx->newQuery(modUserGroup::class); $c->where([ @@ -121,9 +139,10 @@ public function getUserGroups() { * Register custom CSS/JS for the page * @return void */ - public function loadCustomCssJs() { - $this->addJavascript($this->modx->getOption('manager_url')."assets/modext/widgets/system/modx.panel.dashboard.js"); - $this->addJavascript($this->modx->getOption('manager_url').'assets/modext/sections/system/dashboards/update.js'); + public function loadCustomCssJs() + { + $this->addJavascript($this->modx->getOption('manager_url') . "assets/modext/widgets/system/modx.panel.dashboard.js"); + $this->addJavascript($this->modx->getOption('manager_url') . 'assets/modext/sections/system/dashboards/update.js'); $data = json_encode([ 'xtype' => 'modx-page-dashboard-update', 'record' => $this->dashboardArray, @@ -136,15 +155,17 @@ public function loadCustomCssJs() { * * @return string */ - public function getPageTitle() { - return $this->modx->lexicon('dashboards').': '.$this->dashboardArray['name']; + public function getPageTitle() + { + return $this->modx->lexicon('dashboards') . ': ' . $this->dashboardArray['name']; } /** * Return the location of the template file * @return string */ - public function getTemplateFile() { + public function getTemplateFile() + { return ''; } @@ -152,7 +173,8 @@ public function getTemplateFile() { * Specify the language topics to load * @return array */ - public function getLanguageTopics() { + public function getLanguageTopics() + { return ['dashboards','user']; } @@ -160,7 +182,8 @@ public function getLanguageTopics() { * Get the Help URL * @return string */ - public function getHelpUrl() { + public function getHelpUrl() + { return 'Dashboards'; } } diff --git a/manager/templates/default/css/index-min.css b/manager/templates/default/css/index-min.css index 4e8cc24145e..7cb7d9d02dc 100644 --- a/manager/templates/default/css/index-min.css +++ b/manager/templates/default/css/index-min.css @@ -56,6 +56,6 @@ * Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) */@font-face{font-display:block;font-family:Font Awesome\ 5 Brands;font-style:normal;font-weight:400;src:url(../fonts/fa-brands-400.eot);src:url(../fonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../fonts/fa-brands-400.woff2) format("woff2"),url(../fonts/fa-brands-400.woff) format("woff"),url(../fonts/fa-brands-400.ttf) format("truetype"),url(../fonts/fa-brands-400.svg#fontawesome) format("svg")}.fab,.far{font-weight:400}.fab{font-family:Font Awesome\ 5 Brands}.icon.icon-glass:before{content:"\f000"}.icon.icon-meetup{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-star-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-star-o:before{content:"\f005"}.icon.icon-close:before,.icon.icon-remove:before{content:"\f00d"}.icon.icon-gear:before{content:"\f013"}.icon.icon-trash-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-trash-o:before{content:"\f2ed"}.icon.icon-file-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-file-o:before{content:"\f15b"}.icon.icon-clock-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-clock-o:before{content:"\f017"}.icon.icon-arrow-circle-o-down{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-arrow-circle-o-down:before{content:"\f358"}.icon.icon-arrow-circle-o-up{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-arrow-circle-o-up:before{content:"\f35b"}.icon.icon-play-circle-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-play-circle-o:before{content:"\f144"}.icon.icon-repeat:before,.icon.icon-rotate-right:before{content:"\f01e"}.icon.icon-refresh:before{content:"\f021"}.icon.icon-list-alt{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-dedent:before{content:"\f03b"}.icon.icon-video-camera:before{content:"\f03d"}.icon.icon-picture-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-picture-o:before{content:"\f03e"}.icon.icon-photo{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-photo:before{content:"\f03e"}.icon.icon-image{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-image:before{content:"\f03e"}.icon.icon-pencil:before{content:"\f303"}.icon.icon-map-marker:before{content:"\f3c5"}.icon.icon-pencil-square-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-pencil-square-o:before{content:"\f044"}.icon.icon-share-square-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-share-square-o:before{content:"\f14d"}.icon.icon-check-square-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-check-square-o:before{content:"\f14a"}.icon.icon-arrows:before{content:"\f0b2"}.icon.icon-times-circle-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-times-circle-o:before{content:"\f057"}.icon.icon-check-circle-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-check-circle-o:before{content:"\f058"}.icon.icon-mail-forward:before{content:"\f064"}.icon.icon-expand:before{content:"\f424"}.icon.icon-compress:before{content:"\f422"}.icon.icon-eye,.icon.icon-eye-slash{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-warning:before{content:"\f071"}.icon.icon-calendar:before{content:"\f073"}.icon.icon-arrows-v:before{content:"\f338"}.icon.icon-arrows-h:before{content:"\f337"}.icon.icon-bar-chart{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-bar-chart:before{content:"\f080"}.icon.icon-bar-chart-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-bar-chart-o:before{content:"\f080"}.icon.icon-facebook-square,.icon.icon-twitter-square{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-gears:before{content:"\f085"}.icon.icon-thumbs-o-up{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-thumbs-o-up:before{content:"\f164"}.icon.icon-thumbs-o-down{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-thumbs-o-down:before{content:"\f165"}.icon.icon-heart-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-heart-o:before{content:"\f004"}.icon.icon-sign-out:before{content:"\f2f5"}.icon.icon-linkedin-square{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-linkedin-square:before{content:"\f08c"}.icon.icon-thumb-tack:before{content:"\f08d"}.icon.icon-external-link:before{content:"\f35d"}.icon.icon-sign-in:before{content:"\f2f6"}.icon.icon-github-square{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-lemon-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-lemon-o:before{content:"\f094"}.icon.icon-square-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-square-o:before{content:"\f0c8"}.icon.icon-bookmark-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-bookmark-o:before{content:"\f02e"}.icon.icon-facebook,.icon.icon-twitter{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-facebook:before{content:"\f39e"}.icon.icon-facebook-f{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-facebook-f:before{content:"\f39e"}.icon.icon-github{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-credit-card{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-feed:before{content:"\f09e"}.icon.icon-hdd-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-hdd-o:before{content:"\f0a0"}.icon.icon-hand-o-right{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-hand-o-right:before{content:"\f0a4"}.icon.icon-hand-o-left{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-hand-o-left:before{content:"\f0a5"}.icon.icon-hand-o-up{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-hand-o-up:before{content:"\f0a6"}.icon.icon-hand-o-down{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-hand-o-down:before{content:"\f0a7"}.icon.icon-arrows-alt:before{content:"\f31e"}.icon.icon-group:before{content:"\f0c0"}.icon.icon-chain:before{content:"\f0c1"}.icon.icon-scissors:before{content:"\f0c4"}.icon.icon-files-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-files-o:before{content:"\f0c5"}.icon.icon-floppy-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-floppy-o:before{content:"\f0c7"}.icon.icon-navicon:before,.icon.icon-reorder:before{content:"\f0c9"}.icon.icon-google-plus,.icon.icon-google-plus-square,.icon.icon-pinterest,.icon.icon-pinterest-square{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-google-plus:before{content:"\f0d5"}.icon.icon-money{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-money:before{content:"\f3d1"}.icon.icon-unsorted:before{content:"\f0dc"}.icon.icon-sort-desc:before{content:"\f0dd"}.icon.icon-sort-asc:before{content:"\f0de"}.icon.icon-linkedin{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-linkedin:before{content:"\f0e1"}.icon.icon-rotate-left:before{content:"\f0e2"}.icon.icon-legal:before{content:"\f0e3"}.icon.icon-dashboard:before,.icon.icon-tachometer:before{content:"\f3fd"}.icon.icon-comment-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-comment-o:before{content:"\f075"}.icon.icon-comments-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-comments-o:before{content:"\f086"}.icon.icon-flash:before{content:"\f0e7"}.icon.icon-clipboard,.icon.icon-paste{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-paste:before{content:"\f328"}.icon.icon-lightbulb-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-lightbulb-o:before{content:"\f0eb"}.icon.icon-exchange:before{content:"\f362"}.icon.icon-cloud-download:before{content:"\f381"}.icon.icon-cloud-upload:before{content:"\f382"}.icon.icon-bell-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-bell-o:before{content:"\f0f3"}.icon.icon-cutlery:before{content:"\f2e7"}.icon.icon-file-text-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-file-text-o:before{content:"\f15c"}.icon.icon-building-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-building-o:before{content:"\f1ad"}.icon.icon-hospital-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-hospital-o:before{content:"\f0f8"}.icon.icon-tablet:before{content:"\f3fa"}.icon.icon-mobile-phone:before,.icon.icon-mobile:before{content:"\f3cd"}.icon.icon-circle-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-circle-o:before{content:"\f111"}.icon.icon-mail-reply:before{content:"\f3e5"}.icon.icon-github-alt{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-folder-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-folder-o:before{content:"\f07b"}.icon.icon-folder-open-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-folder-open-o:before{content:"\f07c"}.icon.icon-smile-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-smile-o:before{content:"\f118"}.icon.icon-frown-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-frown-o:before{content:"\f119"}.icon.icon-meh-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-meh-o:before{content:"\f11a"}.icon.icon-keyboard-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-keyboard-o:before{content:"\f11c"}.icon.icon-flag-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-flag-o:before{content:"\f024"}.icon.icon-mail-reply-all:before{content:"\f122"}.icon.icon-star-half-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-star-half-o:before{content:"\f089"}.icon.icon-star-half-empty{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-star-half-empty:before{content:"\f089"}.icon.icon-star-half-full{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-star-half-full:before{content:"\f089"}.icon.icon-code-fork:before{content:"\f126"}.icon.icon-chain-broken:before{content:"\f127"}.icon.icon-shield:before{content:"\f3ed"}.icon.icon-calendar-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-calendar-o:before{content:"\f133"}.icon.icon-css3,.icon.icon-html5,.icon.icon-maxcdn{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-ticket:before{content:"\f3ff"}.icon.icon-minus-square-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-minus-square-o:before{content:"\f146"}.icon.icon-level-up:before{content:"\f3bf"}.icon.icon-level-down:before{content:"\f3be"}.icon.icon-pencil-square:before{content:"\f14b"}.icon.icon-external-link-square:before{content:"\f360"}.icon.icon-compass{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-caret-square-o-down{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-caret-square-o-down:before{content:"\f150"}.icon.icon-toggle-down{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-toggle-down:before{content:"\f150"}.icon.icon-caret-square-o-up{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-caret-square-o-up:before{content:"\f151"}.icon.icon-toggle-up{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-toggle-up:before{content:"\f151"}.icon.icon-caret-square-o-right{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-caret-square-o-right:before{content:"\f152"}.icon.icon-toggle-right{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-toggle-right:before{content:"\f152"}.icon.icon-eur:before,.icon.icon-euro:before{content:"\f153"}.icon.icon-gbp:before{content:"\f154"}.icon.icon-dollar:before,.icon.icon-usd:before{content:"\f155"}.icon.icon-inr:before,.icon.icon-rupee:before{content:"\f156"}.icon.icon-cny:before,.icon.icon-jpy:before,.icon.icon-rmb:before,.icon.icon-yen:before{content:"\f157"}.icon.icon-rouble:before,.icon.icon-rub:before,.icon.icon-ruble:before{content:"\f158"}.icon.icon-krw:before,.icon.icon-won:before{content:"\f159"}.icon.icon-bitcoin,.icon.icon-btc{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-bitcoin:before{content:"\f15a"}.icon.icon-file-text:before{content:"\f15c"}.icon.icon-sort-alpha-asc:before{content:"\f15d"}.icon.icon-sort-alpha-desc:before{content:"\f881"}.icon.icon-sort-amount-asc:before{content:"\f160"}.icon.icon-sort-amount-desc:before{content:"\f884"}.icon.icon-sort-numeric-asc:before{content:"\f162"}.icon.icon-sort-numeric-desc:before{content:"\f886"}.icon.icon-xing,.icon.icon-xing-square,.icon.icon-youtube,.icon.icon-youtube-play,.icon.icon-youtube-square{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-youtube-play:before{content:"\f167"}.icon.icon-adn,.icon.icon-bitbucket,.icon.icon-bitbucket-square,.icon.icon-dropbox,.icon.icon-flickr,.icon.icon-instagram,.icon.icon-stack-overflow{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-bitbucket-square:before{content:"\f171"}.icon.icon-tumblr,.icon.icon-tumblr-square{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-long-arrow-down:before{content:"\f309"}.icon.icon-long-arrow-up:before{content:"\f30c"}.icon.icon-long-arrow-left:before{content:"\f30a"}.icon.icon-long-arrow-right:before{content:"\f30b"}.icon.icon-android,.icon.icon-apple,.icon.icon-dribbble,.icon.icon-foursquare,.icon.icon-gittip,.icon.icon-gratipay,.icon.icon-linux,.icon.icon-skype,.icon.icon-trello,.icon.icon-windows{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-gittip:before{content:"\f184"}.icon.icon-sun-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-sun-o:before{content:"\f185"}.icon.icon-moon-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-moon-o:before{content:"\f186"}.icon.icon-pagelines,.icon.icon-renren,.icon.icon-stack-exchange,.icon.icon-vk,.icon.icon-weibo{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-arrow-circle-o-right{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-arrow-circle-o-right:before{content:"\f35a"}.icon.icon-arrow-circle-o-left{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-arrow-circle-o-left:before{content:"\f359"}.icon.icon-caret-square-o-left{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-caret-square-o-left:before{content:"\f191"}.icon.icon-toggle-left{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-toggle-left:before{content:"\f191"}.icon.icon-dot-circle-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-dot-circle-o:before{content:"\f192"}.icon.icon-vimeo-square{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-try:before,.icon.icon-turkish-lira:before{content:"\f195"}.icon.icon-plus-square-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-plus-square-o:before{content:"\f0fe"}.icon.icon-openid,.icon.icon-slack,.icon.icon-wordpress{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-bank:before,.icon.icon-institution:before{content:"\f19c"}.icon.icon-mortar-board:before{content:"\f19d"}.icon.icon-delicious,.icon.icon-digg,.icon.icon-drupal,.icon.icon-google,.icon.icon-joomla,.icon.icon-pied-piper-alt,.icon.icon-pied-piper-pp,.icon.icon-reddit,.icon.icon-reddit-square,.icon.icon-stumbleupon,.icon.icon-stumbleupon-circle,.icon.icon-yahoo{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-spoon:before{content:"\f2e5"}.icon.icon-behance,.icon.icon-behance-square,.icon.icon-steam,.icon.icon-steam-square{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-automobile:before{content:"\f1b9"}.icon.icon-envelope-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-envelope-o:before{content:"\f0e0"}.icon.icon-deviantart,.icon.icon-soundcloud,.icon.icon-spotify{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-file-pdf-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-file-pdf-o:before{content:"\f1c1"}.icon.icon-file-word-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-file-word-o:before{content:"\f1c2"}.icon.icon-file-excel-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-file-excel-o:before{content:"\f1c3"}.icon.icon-file-powerpoint-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-file-powerpoint-o:before{content:"\f1c4"}.icon.icon-file-image-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-file-image-o:before{content:"\f1c5"}.icon.icon-file-photo-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-file-photo-o:before{content:"\f1c5"}.icon.icon-file-picture-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-file-picture-o:before{content:"\f1c5"}.icon.icon-file-archive-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-file-archive-o:before{content:"\f1c6"}.icon.icon-file-zip-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-file-zip-o:before{content:"\f1c6"}.icon.icon-file-audio-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-file-audio-o:before{content:"\f1c7"}.icon.icon-file-sound-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-file-sound-o:before{content:"\f1c7"}.icon.icon-file-video-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-file-video-o:before{content:"\f1c8"}.icon.icon-file-movie-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-file-movie-o:before{content:"\f1c8"}.icon.icon-file-code-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-file-code-o:before{content:"\f1c9"}.icon.icon-codepen,.icon.icon-jsfiddle,.icon.icon-vine{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-life-bouy,.icon.icon-life-ring{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-life-bouy:before{content:"\f1cd"}.icon.icon-life-buoy{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-life-buoy:before{content:"\f1cd"}.icon.icon-life-saver{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-life-saver:before{content:"\f1cd"}.icon.icon-support{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-support:before{content:"\f1cd"}.icon.icon-circle-o-notch:before{content:"\f1ce"}.icon.icon-ra,.icon.icon-rebel{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-ra:before{content:"\f1d0"}.icon.icon-resistance{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-resistance:before{content:"\f1d0"}.icon.icon-empire,.icon.icon-ge{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-ge:before{content:"\f1d1"}.icon.icon-git,.icon.icon-git-square,.icon.icon-hacker-news,.icon.icon-y-combinator-square{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-y-combinator-square:before{content:"\f1d4"}.icon.icon-yc-square{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-yc-square:before{content:"\f1d4"}.icon.icon-qq,.icon.icon-tencent-weibo,.icon.icon-wechat,.icon.icon-weixin{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-wechat:before{content:"\f1d7"}.icon.icon-send:before{content:"\f1d8"}.icon.icon-paper-plane-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-paper-plane-o:before{content:"\f1d8"}.icon.icon-send-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-send-o:before{content:"\f1d8"}.icon.icon-circle-thin{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-circle-thin:before{content:"\f111"}.icon.icon-header:before{content:"\f1dc"}.icon.icon-sliders:before{content:"\f1de"}.icon.icon-futbol-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-futbol-o:before{content:"\f1e3"}.icon.icon-soccer-ball-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-soccer-ball-o:before{content:"\f1e3"}.icon.icon-slideshare,.icon.icon-twitch,.icon.icon-yelp{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-newspaper-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-newspaper-o:before{content:"\f1ea"}.icon.icon-cc-amex,.icon.icon-cc-discover,.icon.icon-cc-mastercard,.icon.icon-cc-paypal,.icon.icon-cc-stripe,.icon.icon-cc-visa,.icon.icon-google-wallet,.icon.icon-paypal{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-bell-slash-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-bell-slash-o:before{content:"\f1f6"}.icon.icon-trash:before{content:"\f2ed"}.icon.icon-copyright{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-eyedropper:before{content:"\f1fb"}.icon.icon-area-chart:before{content:"\f1fe"}.icon.icon-pie-chart:before{content:"\f200"}.icon.icon-line-chart:before{content:"\f201"}.icon.icon-angellist,.icon.icon-ioxhost,.icon.icon-lastfm,.icon.icon-lastfm-square{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-cc{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-cc:before{content:"\f20a"}.icon.icon-ils:before,.icon.icon-shekel:before,.icon.icon-sheqel:before{content:"\f20b"}.icon.icon-meanpath{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-meanpath:before{content:"\f2b4"}.icon.icon-buysellads,.icon.icon-connectdevelop,.icon.icon-dashcube,.icon.icon-forumbee,.icon.icon-leanpub,.icon.icon-sellsy,.icon.icon-shirtsinbulk,.icon.icon-simplybuilt,.icon.icon-skyatlas{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-diamond{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-diamond:before{content:"\f3a5"}.icon.icon-intersex:before{content:"\f224"}.icon.icon-facebook-official{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-facebook-official:before{content:"\f09a"}.icon.icon-pinterest-p,.icon.icon-whatsapp{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-hotel:before{content:"\f236"}.icon.icon-medium,.icon.icon-viacoin,.icon.icon-y-combinator,.icon.icon-yc{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-yc:before{content:"\f23b"}.icon.icon-expeditedssl,.icon.icon-opencart,.icon.icon-optin-monster{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-battery-4:before,.icon.icon-battery:before{content:"\f240"}.icon.icon-battery-3:before{content:"\f241"}.icon.icon-battery-2:before{content:"\f242"}.icon.icon-battery-1:before{content:"\f243"}.icon.icon-battery-0:before{content:"\f244"}.icon.icon-object-group,.icon.icon-object-ungroup,.icon.icon-sticky-note-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-sticky-note-o:before{content:"\f249"}.icon.icon-cc-diners-club,.icon.icon-cc-jcb{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-clone,.icon.icon-hourglass-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-hourglass-o:before{content:"\f254"}.icon.icon-hourglass-1:before{content:"\f251"}.icon.icon-hourglass-2:before{content:"\f252"}.icon.icon-hourglass-3:before{content:"\f253"}.icon.icon-hand-rock-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-hand-rock-o:before{content:"\f255"}.icon.icon-hand-grab-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-hand-grab-o:before{content:"\f255"}.icon.icon-hand-paper-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-hand-paper-o:before{content:"\f256"}.icon.icon-hand-stop-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-hand-stop-o:before{content:"\f256"}.icon.icon-hand-scissors-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-hand-scissors-o:before{content:"\f257"}.icon.icon-hand-lizard-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-hand-lizard-o:before{content:"\f258"}.icon.icon-hand-spock-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-hand-spock-o:before{content:"\f259"}.icon.icon-hand-pointer-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-hand-pointer-o:before{content:"\f25a"}.icon.icon-hand-peace-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-hand-peace-o:before{content:"\f25b"}.icon.icon-registered{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-chrome,.icon.icon-creative-commons,.icon.icon-firefox,.icon.icon-get-pocket,.icon.icon-gg,.icon.icon-gg-circle,.icon.icon-internet-explorer,.icon.icon-odnoklassniki,.icon.icon-odnoklassniki-square,.icon.icon-opera,.icon.icon-safari,.icon.icon-tripadvisor,.icon.icon-wikipedia-w{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-television:before{content:"\f26c"}.icon.icon-500px,.icon.icon-amazon,.icon.icon-contao{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-calendar-plus-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-calendar-plus-o:before{content:"\f271"}.icon.icon-calendar-minus-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-calendar-minus-o:before{content:"\f272"}.icon.icon-calendar-times-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-calendar-times-o:before{content:"\f273"}.icon.icon-calendar-check-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-calendar-check-o:before{content:"\f274"}.icon.icon-map-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-map-o:before{content:"\f279"}.icon.icon-commenting:before{content:"\f4ad"}.icon.icon-commenting-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-commenting-o:before{content:"\f4ad"}.icon.icon-houzz,.icon.icon-vimeo{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-vimeo:before{content:"\f27d"}.icon.icon-black-tie,.icon.icon-edge,.icon.icon-fonticons,.icon.icon-reddit-alien{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-credit-card-alt:before{content:"\f09d"}.icon.icon-codiepie,.icon.icon-fort-awesome,.icon.icon-mixcloud,.icon.icon-modx,.icon.icon-product-hunt,.icon.icon-scribd,.icon.icon-usb{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-pause-circle-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-pause-circle-o:before{content:"\f28b"}.icon.icon-stop-circle-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-stop-circle-o:before{content:"\f28d"}.icon.icon-bluetooth,.icon.icon-bluetooth-b,.icon.icon-envira,.icon.icon-gitlab,.icon.icon-wheelchair-alt,.icon.icon-wpbeginner,.icon.icon-wpforms{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-wheelchair-alt:before{content:"\f368"}.icon.icon-question-circle-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-question-circle-o:before{content:"\f059"}.icon.icon-volume-control-phone:before{content:"\f2a0"}.icon.icon-asl-interpreting:before{content:"\f2a3"}.icon.icon-deafness:before,.icon.icon-hard-of-hearing:before{content:"\f2a4"}.icon.icon-glide,.icon.icon-glide-g{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-signing:before{content:"\f2a7"}.icon.icon-first-order,.icon.icon-google-plus-official,.icon.icon-pied-piper,.icon.icon-snapchat,.icon.icon-snapchat-ghost,.icon.icon-snapchat-square,.icon.icon-themeisle,.icon.icon-viadeo,.icon.icon-viadeo-square,.icon.icon-yoast{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-google-plus-official:before{content:"\f2b3"}.icon.icon-google-plus-circle{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-google-plus-circle:before{content:"\f2b3"}.icon.icon-fa,.icon.icon-font-awesome{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-fa:before{content:"\f2b4"}.icon.icon-handshake-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-handshake-o:before{content:"\f2b5"}.icon.icon-envelope-open-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-envelope-open-o:before{content:"\f2b6"}.icon.icon-linode{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-address-book-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-address-book-o:before{content:"\f2b9"}.icon.icon-vcard:before{content:"\f2bb"}.icon.icon-address-card-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-address-card-o:before{content:"\f2bb"}.icon.icon-vcard-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-vcard-o:before{content:"\f2bb"}.icon.icon-user-circle-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-user-circle-o:before{content:"\f2bd"}.icon.icon-user-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-user-o:before{content:"\f007"}.icon.icon-id-badge{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-drivers-license:before{content:"\f2c2"}.icon.icon-id-card-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-id-card-o:before{content:"\f2c2"}.icon.icon-drivers-license-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-drivers-license-o:before{content:"\f2c2"}.icon.icon-free-code-camp,.icon.icon-quora,.icon.icon-telegram{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-thermometer-4:before,.icon.icon-thermometer:before{content:"\f2c7"}.icon.icon-thermometer-3:before{content:"\f2c8"}.icon.icon-thermometer-2:before{content:"\f2c9"}.icon.icon-thermometer-1:before{content:"\f2ca"}.icon.icon-thermometer-0:before{content:"\f2cb"}.icon.icon-bathtub:before,.icon.icon-s15:before{content:"\f2cd"}.icon.icon-window-maximize,.icon.icon-window-restore{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-times-rectangle:before{content:"\f410"}.icon.icon-window-close-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-window-close-o:before{content:"\f410"}.icon.icon-times-rectangle-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-times-rectangle-o:before{content:"\f410"}.icon.icon-bandcamp,.icon.icon-eercast,.icon.icon-etsy,.icon.icon-grav,.icon.icon-imdb,.icon.icon-ravelry{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-eercast:before{content:"\f2da"}.icon.icon-snowflake-o{font-family:Font Awesome\ 5 Free;font-weight:400}.icon.icon-snowflake-o:before{content:"\f2dc"}.icon.icon-superpowers,.icon.icon-wpexplorer{font-family:Font Awesome\ 5 Brands;font-weight:400}.icon.icon-cab:before{content:"\f1ba"}#modx-navbar #modx-topnav{margin-left:auto;margin-right:auto;max-width:1200px}#modx-navbar #modx-topnav:after{clear:both;content:"";display:block}#modx-footer .modx-subnav li.sub:after,#modx-header .modx-subnav li.sub:after,#modx-leftbar-header a:after,.actions button .x-btn-arrow:before,.actions button .x-btn-split:before,.crumb_wrapper .crumbs li.first:before,.desc-under .copy-this:hover:after,.desc-under .example-list ul li:before,.ext-mb-icon:before,.home-panel ol li:hover button:before,.icon,.icon-3gp:before,.icon-7z:before,.icon-aac:before,.icon-access:before,.icon-aif:before,.icon-aiff:before,.icon-as:before,.icon-avi:before,.icon-backup:before,.icon-bak:before,.icon-bat:before,.icon-bk:before,.icon-bmp:before,.icon-bz2:before,.icon-cal:before,.icon-cfm:before,.icon-coffeescript:before,.icon-css:before,.icon-csv:before,.icon-db:before,.icon-dmg:before,.icon-doc:before,.icon-docx:before,.icon-fla:before,.icon-flac:before,.icon-flv:before,.icon-gif:before,.icon-gz:before,.icon-htaccess:before,.icon-htm:before,.icon-html:before,.icon-ical:before,.icon-ics:before,.icon-iso:before,.icon-jar:before,.icon-java:before,.icon-jpeg:before,.icon-jpg:before,.icon-js:before,.icon-json:before,.icon-less:before,.icon-lock,.icon-log:before,.icon-m4a:before,.icon-m4v:before,.icon-mov:before,.icon-mp3:before,.icon-mp4:before,.icon-mpeg:before,.icon-mpg:before,.icon-ogg:before,.icon-pdf:before,.icon-php:before,.icon-png:before,.icon-ppt:before,.icon-pptx:before,.icon-rar:before,.icon-rb:before,.icon-rss:before,.icon-scr:before,.icon-scss:before,.icon-sh:before,.icon-sql:before,.icon-styl:before,.icon-svg:before,.icon-swf:before,.icon-tar:before,.icon-tgz:before,.icon-tiff:before,.icon-txt:before,.icon-vcs:before,.icon-wav:before,.icon-wma:before,.icon-wmv:before,.icon-xls:before,.icon-xlsx:before,.icon-xml:before,.icon-zip:before,.inline-button .x-btn-arrow:before,.inline-button .x-btn-split:before,.modx-browser-detail-thumb.preview:before,.modx-browser-pathbbar .x-toolbar-left .x-toolbar-left-row td.x-toolbar-cell:before,.modx-header-breadcrumbs ul li:after,.modx-manager-search-results .loading-indicator:before,.modx-status-msg:before,.modx-tv .resizable:after,.modx-tv .resizable:before,.tree-context:before,.tree-new-category>em>button:before,.tree-new-chunk>em>button:before,.tree-new-plugin>em>button:before,.tree-new-resource>em>button:before,.tree-new-snippet>em>button:before,.tree-new-static-resource>em>button:before,.tree-new-symlink>em>button:before,.tree-new-template>em>button:before,.tree-new-tv>em>button:before,.tree-new-weblink>em>button:before,.tree-resource:before,.x-btn-icon.arrow_down button:before,.x-btn-icon.arrow_up button:before,.x-btn-icon.icon-file_manager button:before,.x-btn-icon.icon-file_upload button:before,.x-btn-icon.icon-folder button:before,.x-btn-icon.icon-page_white button:before,.x-btn-icon.refresh button:before,.x-btn .x-btn-arrow:before,.x-btn .x-btn-split:before,.x-date-left a:before,.x-date-mp-cancel .x-btn-arrow:before,.x-date-mp-cancel .x-btn-split:before,.x-date-mp-ok .x-btn-arrow:before,.x-date-mp-ok .x-btn-split:before,.x-date-mp-ybtn a.x-date-mp-next:before,.x-date-mp-ybtn a.x-date-mp-prev:before,.x-date-right a:before,.x-fieldset-checkbox-toggle legend .x-fieldset-header-text:before,.x-fieldset-checkbox-toggle legend .x-form-cb-label:before,.x-form-check-wrap .x-fieldset-header-text:before,.x-form-check-wrap .x-form-cb-label:before,.x-form-field-wrap .x-form-trigger:before,.x-form-invalid-msg:before,.x-form-item .x-form-element .x-form-invalid-icon:before,.x-form-item label.x-form-item-label .modx-field-utils:before,.x-form-item label.x-form-item-label .modx-tv-reset:before,.x-form-trigger .x-btn-arrow:before,.x-form-trigger .x-btn-split:before,.x-grid3-check-col-on:before,.x-grid3-check-col:before,.x-grid3-hd-btn:before,.x-grid3-hd-checker:not(.x-grid3-hd-inner):before,.x-grid3-row-checker:before,.x-grid3-row-collapsed .x-grid3-row-expander:before,.x-grid3-row-expanded .x-grid3-row-expander:before,.x-grid-group-collapsed .x-grid-group-hd div.x-grid-group-title:before,.x-grid-group-hd div.x-grid-group-title:before,.x-superboxselect-item .x-btn-arrow:before,.x-superboxselect-item .x-btn-split:before,.x-superboxselect .x-superboxselect-btns .x-superboxselect-btn-clear:before,.x-superboxselect ul li.x-superboxselect-item .x-superboxselect-item-close:before,.x-tab-scroller-left:before,.x-tab-scroller-right:before,.x-tbar-loading:before,.x-tbar-page-first:before,.x-tbar-page-last:before,.x-tbar-page-next:before,.x-tbar-page-prev:before,.x-tool:after,.x-tree-arrows .x-tree-elbow-end-minus:before,.x-tree-arrows .x-tree-elbow-end-plus:before,.x-tree-arrows .x-tree-elbow-minus:before,.x-tree-arrows .x-tree-elbow-plus:before{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:auto;display:inline-block;font-family:Font Awesome\ 5 Free,Font Awesome\ 5 Brands;font-style:normal;font-variant:normal;font-weight:900}.crumb_wrapper .crumbs li.first:before,.x-btn-icon.arrow_down button:before,.x-btn-icon.arrow_up button:before,.x-btn-icon.refresh button:before,.x-tbar-loading:before,.x-tbar-page-first:before,.x-tbar-page-last:before,.x-tbar-page-next:before,.x-tbar-page-prev:before{bottom:0;color:inherit;font-size:14px;height:100%;left:0;line-height:100%;position:absolute;right:0;text-align:center;top:0;width:100%}#modx-tv-tabs .lt-ie8{*zoom:1}#modx-tv-tabs:after,#modx-tv-tabs:before{content:" ";display:table}#modx-tv-tabs:after{clear:both}.x-splitbar-proxy{background-color:#aaa}.x-color-palette a{border-color:#fff}.x-color-palette a.x-color-palette-sel,.x-color-palette a:hover{background-color:#ebebeb;border-color:#b4b4b4}.x-color-palette em{border-color:#aca899}.loading-indicator{background-image:url(../images/modx-theme/grid/loading.gif);font-size:11px}.x-spotlight{background-color:#ccc}.ext-ie7 .x-plain-body{position:relative}.x-statusbar .x-status-busy{background-image:url(../images/modx-theme/grid/loading.gif)}.x-statusbar .x-status-text-panel{border-color:#dfdfdf #fff #fff #dfdfdf}.x-resizable-handle-southeast{bottom:1px;right:1px}.x-resizable-over .x-resizable-handle-east,.x-resizable-over .x-resizable-handle-west,.x-resizable-pinned .x-resizable-handle-east,.x-resizable-pinned .x-resizable-handle-west{background-image:url(../images/modx-theme/sizer/e-handle.gif)}.x-resizable-over .x-resizable-handle-north,.x-resizable-over .x-resizable-handle-south,.x-resizable-pinned .x-resizable-handle-north,.x-resizable-pinned .x-resizable-handle-south{background-image:url(../images/modx-theme/sizer/s-handle.gif)}.x-resizable-over .x-resizable-handle-southeast,.x-resizable-pinned .x-resizable-handle-southeast{background-image:url(../images/modx-theme/sizer/se-handle.gif)}.x-resizable-over .x-resizable-handle-northwest,.x-resizable-pinned .x-resizable-handle-northwest{background-image:url(../images/modx-theme/sizer/nw-handle.gif)}.x-resizable-over .x-resizable-handle-northeast,.x-resizable-pinned .x-resizable-handle-northeast{background-image:url(../images/modx-theme/sizer/ne-handle.gif)}.x-resizable-over .x-resizable-handle-southwest,.x-resizable-pinned .x-resizable-handle-southwest{background-image:url(../images/modx-theme/sizer/sw-handle.gif)}.x-resizable-proxy{border-color:#575757}.x-resizable-overlay{background-color:#fff}.x-grid3{background-color:initial;background-image:none;border:1px solid #e4e9ee;border-radius:3px;overflow:hidden;padding:0}.x-grid-panel .x-panel-mc .x-panel-body{border:0}.x-grid3-hd-row td,.x-grid3-row td,.x-grid3-summary-row td{font:normal 12px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.x-grid3-row td,.x-grid3-summary-row td{border-left:1px solid #0000;padding-left:0}.x-grid3-hd-row td{border-left:1px solid #fff;border-right:none;text-align:initial}.x-grid3-hd-row td.x-grid3-cell-first,.x-grid3-row td.x-grid3-cell-first,.x-grid3-row td.x-grid3-summary-first{border-left:0}.x-grid3-hd-row td.x-grid3-cell-last,.x-grid3-row td.x-grid3-cell-last,.x-grid3-row td.x-grid3-summary-last{border-right:0}.x-grid-row-loading{background-color:#fff;background-image:url(../images/modx-theme/shared/loading-balls.gif)}.x-grid3-row{border-color:#fff #fff #efefef}.x-grid3-row.highlight-inserted{background-color:#dce0ea}.x-grid3-row-expanded .x-grid3-row-body{word-wrap:break-word;color:#888;margin:0 2px 0 -20px;padding:0 25px 15px}.x-grid3-row-expanded .x-grid3-row-body .desc{word-wrap:break-word}.x-grid3-row-alt{background-color:#f5f6f9}.x-panel-body-noheader .x-grid3-row{border-color:#0000}.x-panel-body-noheader .x-grid3-row-alt{border-bottom:1px solid #eaeaea;border-top:1px solid #eaeaea}.x-panel-body-noheader .x-grid3-row-alt .x-grid3-row-table{border-top:1px solid #0000}.x-grid3-row-over{background-color:#e0e8ef;background-image:none;border-bottom:1px solid #d1d9df}.x-grid3-resize-marker,.x-grid3-resize-proxy{background-color:#777}.x-grid3-header{background:#fff;border-bottom:1px solid #e4e9ee!important;padding:0}.x-panel-body-noheader .x-grid3-header{border:none}.x-grid3-header-offset{padding-left:0}.x-grid3-header .x-grid3-hd-row td{color:dimgray;font-weight:700;text-align:initial}.x-grid3-header-pop{border-left-color:#dfdfdf}.x-grid3-header-pop-inner{background-image:url(../images/modx-theme/grid/hd-pop.gif);border-left-color:#eee}td.sort-asc,td.sort-desc,td.x-grid3-hd-menu-open,td.x-grid3-hd-over{background:#fff;border-left-color:#fff}td.sort-asc .x-grid3-hd-inner,td.sort-desc .x-grid3-hd-inner,td.x-grid3-hd-menu-open .x-grid3-hd-inner,td.x-grid3-hd-over .x-grid3-hd-inner{color:#696969}.sort-asc .x-grid3-sort-icon{background-image:url(../images/modx-theme/grid/sort_asc.gif)}.sort-desc .x-grid3-sort-icon{background-image:url(../images/modx-theme/grid/sort_desc.gif)}.x-panel-body-noheader .x-grid3-body{background-color:#fff}.x-grid3-cell-text,.x-grid3-hd-text{color:#515151}.x-grid3-split{background-image:url(../images/modx-theme/grid/grid-split.gif)}.x-grid3-hd-text{color:#464646}.x-dd-drag-proxy .x-grid3-hd-inner{background-color:#f2f2f2;background-image:url(../images/modx-theme/grid/grid3-hrow-over.gif);border-color:#c8c8c8}.col-move-top{background-image:url(../images/modx-theme/grid/col-move-top.gif)}.col-move-bottom{background-image:url(../images/modx-theme/grid/col-move-bottom.gif)}.x-grid3-row-selected{background-color:#f0f0f0;background-image:none;border-bottom:1px solid #e4e4e4!important;border-top:1px solid #e4e4e4!important;color:#565550}.x-grid3-row-last,.x-grid3-row-last .x-grid3-row-selected{border-bottom-color:#0000!important}.x-grid3-cell-selected{background-color:#e0eaef!important;color:#515151}.x-grid3-cell-selected span{color:#515151!important}.x-grid3-cell-selected .x-grid3-cell-text{color:#515151}.x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker,.x-grid3-locked td.x-grid3-row-marker{background-color:#d7d9df!important;background-image:url(../images/modx-theme/grid/grid-hrow.gif)!important;border-right-color:#9c9c9c!important;border-top-color:#fff;color:#515151}.x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker div,.x-grid3-locked td.x-grid3-row-marker div{color:#464646!important}.x-grid3-dirty-cell{background-image:url(../images/modx-theme/grid/dirty.gif)}.x-grid3-bottombar,.x-grid3-topbar{font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.x-grid3-bottombar .x-toolbar{border-top-color:#bcbcbc}.x-props-grid .x-grid3-td-name .x-grid3-cell-inner{background-image:url(../images/modx-theme/grid/grid3-special-col-bg.gif)!important;color:#515151!important}.x-grid3-hd-inner{font-weight:700;padding:10px}.ext-ie .x-grid3-hd-inner{width:auto}.x-grid3-cell-inner,.x-grid3-hd-inner{padding:10px}.x-props-grid .x-grid3-body .x-grid3-td-name{background-color:#fff!important;border-right-color:#eee}.xg-hmenu-sort-asc .x-menu-item-icon{background-image:url(../images/modx-theme/grid/hmenu-asc.gif)}.xg-hmenu-sort-desc .x-menu-item-icon{background-image:url(../images/modx-theme/grid/hmenu-desc.gif)}.xg-hmenu-lock .x-menu-item-icon{background-image:url(../images/modx-theme/grid/hmenu-lock.gif)}.xg-hmenu-unlock .x-menu-item-icon{background-image:url(../images/modx-theme/grid/hmenu-unlock.gif)}.x-grid3-hd-btn{background-color:#fff}.x-grid3-hd-btn:before{color:#77899f;content:"\f0d7";font-size:14px;font-style:normal;font-weight:900;left:0;position:absolute;right:0;text-align:center;top:14px}.x-grid3-hd-btn:hover{background-color:#fff}.x-grid3-body .x-grid3-td-expander{background-image:none;text-align:right}.x-grid3-row-collapsed .x-grid3-row-expander{height:27px;margin-top:10px}.x-grid3-row-collapsed .x-grid3-row-expander:before{color:#53595f;content:"\f0fe";font-size:14px;font-weight:400}.x-grid3-row-expanded .x-grid3-row-expander{height:27px;margin-top:10px}.x-grid3-row-expanded .x-grid3-row-expander:before{color:#53595f;content:"\f146";font-size:14px;font-weight:400}.x-grid3-body .x-grid3-td-checker{background-image:none;padding:10px 0 0}.x-grid3-hd-checker:not(.x-grid3-hd-inner),.x-grid3-row-checker{cursor:pointer}.x-grid3-hd-checker:not(.x-grid3-hd-inner):before,.x-grid3-row-checker:before{color:#53595f;content:"\f0c8";display:inline-block;font-size:14px;font-weight:400;padding:3px 5px}.x-grid3-hd-checker-on .x-grid3-hd-checker:not(.x-grid3-hd-inner):before,.x-grid3-hd-checker-on .x-grid3-row-checker:before,.x-grid3-row-selected .x-grid3-hd-checker:not(.x-grid3-hd-inner):before,.x-grid3-row-selected .x-grid3-row-checker:before{content:"\f14a";font-weight:400}.x-grid3-body .x-grid3-td-numberer{background-color:#e5e5e5;border-bottom:1px solid #dadada;border-right:1px solid #dadada!important}.x-grid3-body .x-grid3-td-numberer .x-grid3-cell-inner{color:#444;padding-left:10px;padding-top:10px!important}.x-grid3-body .x-grid3-td-row-icon{background-image:url(../images/modx-theme/grid/grid3-special-col-bg.gif)}.x-grid3-body .x-grid3-row-selected .x-grid3-td-checker,.x-grid3-body .x-grid3-row-selected .x-grid3-td-expander,.x-grid3-body .x-grid3-row-selected .x-grid3-td-numberer{background-image:none}.x-grid3-check-col{cursor:pointer;margin-top:10px}.x-grid3-check-col:before{color:#53595f;content:"\f0c8";display:block;font-size:14px;font-weight:400;margin:0 auto;padding:3px 5px;text-align:left;width:14px}.x-grid3-check-col-on{cursor:pointer;margin-top:10px}.x-grid3-check-col-on:before{color:#53595f;content:"\f14a";display:block;font-size:14px;font-weight:400;margin:0 auto;padding:3px 5px;text-align:left;width:14px}.x-grid-group,.x-grid-group-body,.x-grid-group-hd{zoom:1}.x-grid-group-hd{border-bottom-color:#53595f}.x-grid-group-hd div.x-grid-group-title{color:#53595f;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:12px;font-weight:700;padding:10px 0}.x-grid-group-hd div.x-grid-group-title:before{content:"\f146";font-size:14px;font-style:normal;font-weight:400;padding:0 5px}.x-grid-group-collapsed .x-grid-group-hd div.x-grid-group-title:before{content:"\f0fe";font-style:normal;font-weight:400;padding:0 5px}.x-group-by-icon{background-image:url(../images/modx-theme/grid/group-by.gif)}.x-cols-icon{background-image:url(../images/modx-theme/grid/columns.gif)}.x-show-groups-icon{background-image:url(../images/modx-theme/grid/group-by.gif)}.x-grid-empty{color:#515151;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;text-align:center}.x-grid-with-col-lines .x-grid3-row td.x-grid3-cell{border-right-color:#ededed}.x-grid-with-col-lines .x-grid3-row{border-left:0;border-top:0}.x-grid-with-col-lines .x-grid3-row-selected{border-top-color:#e4e4e4}.x-dd-drag-ghost{background-color:#fff;border-color:#ddd #bbb #bbb #dfdfdf;color:#515151;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.x-dd-drop-nodrop .x-dd-drop-icon{background-image:url(../images/modx-theme/dd/drop-no.gif)}.x-dd-drop-ok .x-dd-drop-icon{background-image:url(../images/modx-theme/dd/drop-yes.gif)}.x-dd-drop-ok-add .x-dd-drop-icon{background-image:url(../images/modx-theme/dd/drop-add.gif)}.x-view-selector{background-color:#d8d8d8;border-color:#8d8d8d}.x-tip{background:#575757;border-radius:3px;max-width:400px;min-width:200px;padding:5px;width:auto!important}.x-tip .x-tip-close{background-image:url(../images/modx-theme/qtip/close.gif)}.x-tip .x-tip-bc,.x-tip .x-tip-bl,.x-tip .x-tip-br,.x-tip .x-tip-ml,.x-tip .x-tip-mr,.x-tip .x-tip-tc,.x-tip .x-tip-tl,.x-tip .x-tip-tr{background-image:none}.x-tip .x-tip-mc{font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.x-tip .x-tip-ml{background-color:initial}.x-tip .x-tip-header-text{color:#f0f0f0;font:normal 13px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.x-tip .x-tip-body{color:#f0f0f0;font:normal 12px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;width:auto!important}.x-tip img{background-color:#ccc;background-image:url(../images/modx-theme/transparency-pattern.png);display:block;height:auto;max-width:100%;width:100%}.x-form-invalid-tip .x-tip-bc,.x-form-invalid-tip .x-tip-bl,.x-form-invalid-tip .x-tip-br,.x-form-invalid-tip .x-tip-ml,.x-form-invalid-tip .x-tip-mr,.x-form-invalid-tip .x-tip-tc,.x-form-invalid-tip .x-tip-tl,.x-form-invalid-tip .x-tip-tr{background-image:url(../images/modx-theme/form/error-tip-corners.gif)}.x-form-invalid-tip .x-tip-body{background-image:url(../images/modx-theme/form/exclamation.gif)}.x-tip-anchor{background-image:url(../images/modx-theme/qtip/tip-anchor-sprite.gif)}.x-menu{background-color:#fff;border:1px solid #e4e4e4;border-radius:3px;box-shadow:0 4px 6px #00000026}.x-menu-list{padding:0}.x-menu-list li{border:0;margin:0;padding:0}.x-menu-list li:first-child{margin-top:3px}.x-menu-list li:last-child{margin-bottom:3px}.x-menu-list li.x-menu-date-item{margin:0}.x-menu-list li a.x-menu-item{color:#515151;font-size:13px;padding:3px 21px 3px 27px}.x-menu-list li a.x-menu-item:hover{color:#515151}.x-menu-list li.x-menu-item-active{background-color:#f0f0f0}.x-menu-list li.x-menu-item-active a{color:#515151}.x-menu-floating{border-color:#c7c7c7}html[dir=rtl] .x-menu-floating{left:unset!important;right:0}.x-menu-nosep{background-image:none}.x-menu-list-item{font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.x-menu-item-arrow{background-image:url(../images/modx-theme/menu/menu-parent.gif)}.x-menu-sep{background-color:#e4e4e4;border-bottom:none;margin:2px 0}.x-menu-item-active a.x-menu-item{border:0;margin:0}.x-menu-check-item .x-menu-item-icon{background-image:url(../images/modx-theme/menu/unchecked.gif)}.x-menu-item-checked .x-menu-item-icon{background-image:url(../images/modx-theme/menu/checked.gif)}.x-menu-item-checked .x-menu-group-item .x-menu-item-icon{background-image:url(../images/modx-theme/menu/group-checked.gif)}.x-menu-group-item .x-menu-item-icon{background-image:none}.x-menu-plain{background-color:#fff!important}.x-cycle-menu .x-menu-item-checked{background-color:#dfdfdf;border-color:#b9b9b9!important}.x-menu-scroller-top{background-image:url(../images/modx-theme/layout/mini-top.gif)}.x-menu-scroller-bottom{background-image:url(../images/modx-theme/layout/mini-bottom.gif)}.x-box-ml,.x-box-tl{background-color:#fafafa;background-image:none;color:#393939;font:normal 13px/1.4 -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-weight:700}.x-box-mc p{font-weight:400;margin-bottom:5px}.x-box-tl{border-top:1px solid #dedede}.x-box-ml,.x-box-tl{background-color:#fafafacc}.x-box-bl,.x-box-ml,.x-box-tl{border-left:1px solid #dedede;border-right:1px solid #dedede}.x-box-bl{background-color:#e6e6e6cc;border-bottom:1px solid #dedede}.x-box-mc h3{font-size:14px;font-weight:700}.x-box-bc,.x-box-bl,.x-box-blue .x-box-bl,.x-box-blue .x-box-br,.x-box-blue .x-box-tl,.x-box-blue .x-box-tr,.x-box-br,.x-box-mr{background-image:none}.x-box-blue .x-box-bc,.x-box-blue .x-box-mc,.x-box-blue .x-box-tc{background-image:url(../images/modx-theme/box/tb-gray.gif)}.x-box-blue .x-box-mc{background-color:#d8d8d8}.x-box-blue .x-box-mc h3{color:#363636}.x-box-blue .x-box-ml{background-image:url(../images/modx-theme/box/l-gray.gif)}.x-box-blue .x-box-mr{background-image:url(../images/modx-theme/box/r-gray.gif)}#x-debug-browser .x-tree .x-tree-node a span{color:#333;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:11px}#x-debug-browser .x-tree a i{color:#cf1124;font-style:normal}#x-debug-browser .x-tree a em{color:#999}#x-debug-browser .x-tree .x-tree-node .x-tree-selected a span{background-color:#d8d8d8}.x-panel-body,.x-panel-bwrap{overflow:visible}.x-panel-body{border:0;border-radius:3px}#modx-panel-packages-browser .x-panel-body{border-radius:0}.x-grid-panel .x-panel-body{background-color:#f5f5f5;border:0}.x-grid-panel .x-panel-body-noheader{background-color:initial;border:0;padding:0!important}.x-panel-tl .x-panel-header{color:#6a6a6a;font:normal 12px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-weight:700}.x-panel-tl .x-panel-icon{background-position:0 8px}.x-panel-tc{background-image:none}.x-panel-bl,.x-panel-br,.x-panel-tl,.x-panel-tr{background-image:none;border-bottom-color:#dfdfdf}.x-panel-bc{background-image:none}.x-panel-tc{background-color:#f5f5f5}.x-panel-tl{border:1px solid #e3e3e3;border-bottom:0 #e3e3e3}.x-panel-tl .x-panel-header{border-bottom:1px solid #e4e4e4;padding:10px 0}.x-panel-bc .x-panel-footer{padding-bottom:0}.x-panel-btns{background-color:initial;padding:15px 0 1px}.x-panel-btns td.x-toolbar-cell{padding:0}.x-panel-mc{background-color:#f5f5f5;border-bottom:1px solid #dfdfdf;border-top:1px solid #fafafa;padding:10px 5px}.x-panel-bl,.x-panel-ml,.x-panel-tl{background-color:#f5f5f5;padding-left:8px}.x-panel-ml,.x-panel-mr{background-image:none}.x-panel-bl{border:1px solid #e3e3e3;border-top:0 #e3e3e3;padding-bottom:8px}.x-panel-ml{border-left:1px solid #e3e3e3;border-right:1px solid #e3e3e3}.x-panel-mr{padding-right:8px}.x-panel-br,.x-panel-mr,.x-panel-tr{background-color:#f7f7f7}.x-tool{background:none;border-radius:50%;color:#515151;font-size:14px;margin:0 3px 0 0;position:relative;transition:all .3s}.x-tool,.x-tool:after{height:18px;width:18px}.x-tool:after{box-sizing:border-box;left:0;padding-top:2px;position:absolute;text-align:center;top:0;vertical-align:middle}.x-tool:hover{background:#234368;color:#fff}.x-tool.x-tool-toggle:after{content:"\f077";padding-top:2px}.x-tool.x-tool-toggle-over:after,.x-tool.x-tool-toggle:hover:after{content:"\f077"}.x-panel-collapsed .x-tool.x-tool-toggle-over:after,.x-panel-collapsed .x-tool.x-tool-toggle:after,.x-panel-collapsed .x-tool.x-tool-toggle:hover:after{content:"\f078";padding-top:3px}.x-tool.x-tool-close:after{content:"\f00d"}.x-tool.x-tool-minimize:after{content:"\f066"}.x-tool.x-tool-maximize:after{content:"\f065"}.x-tool.x-tool-restore:after{content:"\f066"}.x-tool.x-tool-gear:after{content:"\f013"}.x-tool.x-tool-pin:after{content:"\f111"}.x-tool.x-tool-pin-over:after,.x-tool.x-tool-pin:hover:after,.x-tool.x-tool-unpin:after{content:"\f192"}.x-tool.x-tool-unpin-over:after,.x-tool.x-tool-unpin:hover:after{content:"\f111"}.x-tool.x-tool-right:after{content:"\f054";padding-left:1px}.x-tool.x-tool-left:after{content:"\f053";padding-right:2px}.x-tool.x-tool-up:after{content:"\f077";padding-top:1px}.x-tool.x-tool-down:after{content:"\f078";padding-top:1px}.x-tool.x-tool-minus:after{content:"\f068"}.x-tool.x-tool-plus:after{content:"\f067"}.x-panel-dd-spacer{border-color:#dfdfdf}.x-panel-fbar div,.x-panel-fbar input,.x-panel-fbar label,.x-panel-fbar select,.x-panel-fbar span,.x-panel-fbar td{font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.x-panel-header{border:1px solid silver;border-radius:3px 3px 0 0;font-size:14px;font-weight:700;margin-top:0;padding:10px 10px 8px}.x-portal-space{border-bottom:1px solid #afafaf;padding:0}.x-column-inner{overflow:visible}.x-column-inner>.x-column{margin-right:0;overflow:visible}.x-column-inner>.x-column:not(.x-hide-display)~.x-column{margin-left:15px;margin-right:0}.x-panel-nofooter .x-panel-bc{background-image:none;height:0}.x-panel-ghost{background-color:#dbdbdb}.x-panel-dd-spacer,.x-panel-ghost ul{border-color:#d0d0d0}.x-dlg-mask{background-color:#ccc}.x-html-editor-wrap{background-color:#fff;border-color:#bcbcbc}.x-panel-noborder .x-panel-header-noborder{border-bottom-color:#0000}.x-border-layout-ct{background-color:#fafafa}.x-accordion-hd{background-image:url(../images/modx-theme/panel/light-hd.gif);color:#222;font-weight:400}.x-layout-collapsed{background-color:#e4e4e4;border-color:#dfdfdf;width:7px!important}.x-layout-collapsed-over{background-color:#e6e6e6}.x-layout-split-west .x-layout-mini{background-image:url(../images/modx-theme/layout/mini-left.gif)}.x-layout-split-east .x-layout-mini{background-image:url(../images/modx-theme/layout/mini-right.gif)}.x-layout-split-north .x-layout-mini{background-image:url(../images/modx-theme/layout/mini-top.gif)}.x-layout-split-south .x-layout-mini{background-image:url(../images/modx-theme/layout/mini-bottom.gif)}.x-layout-cmini-west .x-layout-mini{background-image:url(../images/modx-theme/layout/mini-right.gif)}.x-layout-cmini-east .x-layout-mini{background-image:url(../images/modx-theme/layout/mini-left.gif)}.x-layout-cmini-north .x-layout-mini{background-image:url(../images/modx-theme/layout/mini-bottom.gif)}.x-layout-cmini-south .x-layout-mini{background-image:url(../images/modx-theme/layout/mini-top.gif)}.x-list-header{background-color:#f9f9f9;background-image:url(../images/modx-theme/grid/grid3-hrow.gif)}.x-list-header-inner div em{border-left-color:#dfdfdf}.x-list-body dt em,.x-list-header-inner div em{font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.x-list-over{background-color:#eee}.x-list-selected{background-color:#e7e7e7}.x-list-resizer{border-left-color:#555;border-right-color:#555}.x-list-header-inner em.sort-asc,.x-list-header-inner em.sort-desc{background-image:url(../images/modx-theme/grid/sort-hd.gif);border-color:#dfdfdf}.x-slider-horz,.x-slider-horz .x-slider-end,.x-slider-horz .x-slider-inner{background-image:url(../images/modx-theme/slider/slider-bg.png)}.x-slider-horz .x-slider-thumb{background-image:url(../images/modx-theme/slider/slider-thumb.png)}.x-slider-vert,.x-slider-vert .x-slider-end,.x-slider-vert .x-slider-inner{background-image:url(../images/modx-theme/slider/slider-v-bg.png)}.x-slider-vert .x-slider-thumb{background-image:url(../images/modx-theme/slider/slider-v-thumb.png)}.x-portal .x-panel-tl .x-panel-header{background:none;font-size:14px;padding:8px 0}.x-portal .x-tool{margin-top:0}.x-portal .x-panel-body{font-weight:400;margin-bottom:5px;padding:0;text-transform:none}.x-portal-space{margin-bottom:5px}.x-grid3-body .x-grid3-td-checker{background-image:none!important}.modx-combo-desc{color:#515151;font-size:.9em;font-style:italic}.modx-combo-title{font-weight:700}.modx-grid-draggable .x-grid3-row{cursor:move}#modx-grid-deprecated-log .x-grid-group-hd div{height:auto}.actions button.primary-button,.primary-button.inline-button,.primary-button.x-btn,.primary-button.x-date-mp-cancel,.primary-button.x-date-mp-ok,.primary-button.x-form-trigger,.primary-button.x-superboxselect-item,.x-window.x-window-plain .x-toolbar-left-row .x-toolbar-cell:first-child .x-btn,.x-window.x-window-plain .x-toolbar-left-row .x-toolbar-cell:nth-child(2) .x-btn{background:#6cb24a;box-shadow:none;color:#fff;transition:background-color .2s ease-out}.actions button.x-btn-focus.primary-button:not(.x-btn-over),.x-btn-focus.primary-button.inline-button:not(.x-btn-over),.x-btn-focus.primary-button.x-btn:not(.x-btn-over),.x-btn-focus.primary-button.x-date-mp-cancel:not(.x-btn-over),.x-btn-focus.primary-button.x-date-mp-ok:not(.x-btn-over),.x-btn-focus.primary-button.x-form-trigger:not(.x-btn-over),.x-btn-focus.primary-button.x-superboxselect-item:not(.x-btn-over),.x-window.x-window-plain .x-toolbar-left-row .x-toolbar-cell:first-child .x-btn-focus.x-btn:not(.x-btn-over),.x-window.x-window-plain .x-toolbar-left-row .x-toolbar-cell:nth-child(2) .x-btn-focus.x-btn:not(.x-btn-over){background:#6cb24a;color:#fff}.actions button.primary-button:hover,.actions button.x-btn-over.primary-button,.primary-button.inline-button:hover,.primary-button.x-btn:hover,.primary-button.x-date-mp-cancel:hover,.primary-button.x-date-mp-ok:hover,.primary-button.x-form-trigger:hover,.primary-button.x-superboxselect-item:hover,.x-btn-over.primary-button.inline-button,.x-btn-over.primary-button.x-btn,.x-btn-over.primary-button.x-date-mp-cancel,.x-btn-over.primary-button.x-date-mp-ok,.x-btn-over.primary-button.x-form-trigger,.x-btn-over.primary-button.x-superboxselect-item,.x-window.x-window-plain .x-toolbar-left-row .x-toolbar-cell:first-child .x-btn-over.x-btn,.x-window.x-window-plain .x-toolbar-left-row .x-toolbar-cell:first-child .x-btn:hover,.x-window.x-window-plain .x-toolbar-left-row .x-toolbar-cell:nth-child(2) .x-btn-over.x-btn,.x-window.x-window-plain .x-toolbar-left-row .x-toolbar-cell:nth-child(2) .x-btn:hover{background:#528738;box-shadow:none;color:#fff}.actions button.primary-button:active,.actions button.x-btn-click.primary-button,.primary-button.inline-button:active,.primary-button.x-btn:active,.primary-button.x-date-mp-cancel:active,.primary-button.x-date-mp-ok:active,.primary-button.x-form-trigger:active,.primary-button.x-superboxselect-item:active,.x-btn-click.primary-button.inline-button,.x-btn-click.primary-button.x-btn,.x-btn-click.primary-button.x-date-mp-cancel,.x-btn-click.primary-button.x-date-mp-ok,.x-btn-click.primary-button.x-form-trigger,.x-btn-click.primary-button.x-superboxselect-item,.x-window.x-window-plain .x-toolbar-left-row .x-toolbar-cell:first-child .x-btn-click.x-btn,.x-window.x-window-plain .x-toolbar-left-row .x-toolbar-cell:first-child .x-btn:active,.x-window.x-window-plain .x-toolbar-left-row .x-toolbar-cell:nth-child(2) .x-btn-click.x-btn,.x-window.x-window-plain .x-toolbar-left-row .x-toolbar-cell:nth-child(2) .x-btn:active{background:#385c26;box-shadow:none;color:#fff}.actions button.x-item-disabled.primary-button,.x-item-disabled.primary-button.inline-button,.x-item-disabled.primary-button.x-btn,.x-item-disabled.primary-button.x-date-mp-cancel,.x-item-disabled.primary-button.x-date-mp-ok,.x-item-disabled.primary-button.x-form-trigger,.x-item-disabled.primary-button.x-superboxselect-item,.x-window.x-window-plain .x-toolbar-left-row .x-toolbar-cell:first-child .x-item-disabled.x-btn,.x-window.x-window-plain .x-toolbar-left-row .x-toolbar-cell:nth-child(2) .x-item-disabled.x-btn{background:#6cb24a;box-shadow:none;color:#fff;filter:alpha(opacity=60);opacity:.6}.actions button,.inline-button,.x-btn,.x-date-mp-cancel,.x-date-mp-ok,.x-date-picker .x-btn,.x-form-trigger,.x-superboxselect-item{zoom:1;background-color:#fff;background-repeat:no-repeat;border:0;border-radius:3px;box-shadow:0 0 0 1px #e4e4e4;color:#515151;cursor:pointer;display:inline-block;*display:inline;line-height:1;padding:10px 15px;position:relative;text-decoration:none;transition:background-color .2s ease-out}.actions .ext-webkit button em,.ext-webkit .actions button em,.ext-webkit .inline-button em,.ext-webkit .x-btn em,.ext-webkit .x-date-mp-cancel em,.ext-webkit .x-date-mp-ok em,.ext-webkit .x-form-trigger em,.ext-webkit .x-superboxselect-item em{font-size:0}.actions button button,.inline-button button,.x-btn button,.x-date-mp-cancel button,.x-date-mp-ok button,.x-date-picker .x-btn button,.x-form-trigger button,.x-superboxselect-item button{background-repeat:no-repeat;color:inherit;cursor:pointer;font-size:13px;font-style:normal;height:16px;line-height:1;min-width:100%;padding:0}.actions .ext-ie8 button button,.ext-ie8 .actions button button,.ext-ie8 .inline-button button,.ext-ie8 .x-btn button,.ext-ie8 .x-date-mp-cancel button,.ext-ie8 .x-date-mp-ok button,.ext-ie8 .x-form-trigger button,.ext-ie8 .x-superboxselect-item button{padding-top:0}.actions button .x-btn-arrow,.actions button .x-btn-split,.inline-button .x-btn-arrow,.inline-button .x-btn-split,.x-btn .x-btn-arrow,.x-btn .x-btn-split,.x-date-mp-cancel .x-btn-arrow,.x-date-mp-cancel .x-btn-split,.x-date-mp-ok .x-btn-arrow,.x-date-mp-ok .x-btn-split,.x-date-picker .x-btn .x-btn-arrow,.x-date-picker .x-btn .x-btn-split,.x-form-trigger .x-btn-arrow,.x-form-trigger .x-btn-split,.x-superboxselect-item .x-btn-arrow,.x-superboxselect-item .x-btn-split{display:block;padding-right:20px;position:relative}.actions button .x-btn-arrow:before,.actions button .x-btn-split:before,.inline-button .x-btn-arrow:before,.inline-button .x-btn-split:before,.x-btn .x-btn-arrow:before,.x-btn .x-btn-split:before,.x-date-mp-cancel .x-btn-arrow:before,.x-date-mp-cancel .x-btn-split:before,.x-date-mp-ok .x-btn-arrow:before,.x-date-mp-ok .x-btn-split:before,.x-form-trigger .x-btn-arrow:before,.x-form-trigger .x-btn-split:before,.x-superboxselect-item .x-btn-arrow:before,.x-superboxselect-item .x-btn-split:before{color:inherit;content:"\f0d7";font-size:14px;margin-top:0;position:absolute;right:0;top:50%}.actions button .x-btn-arrow button,.actions button .x-btn-split button,.inline-button .x-btn-arrow button,.inline-button .x-btn-split button,.x-btn .x-btn-arrow button,.x-btn .x-btn-split button,.x-date-mp-cancel .x-btn-arrow button,.x-date-mp-cancel .x-btn-split button,.x-date-mp-ok .x-btn-arrow button,.x-date-mp-ok .x-btn-split button,.x-form-trigger .x-btn-arrow button,.x-form-trigger .x-btn-split button,.x-superboxselect-item .x-btn-arrow button,.x-superboxselect-item .x-btn-split button{border-right-color:inherit;border-right-style:solid;border-right-width:1px;padding-right:10px}.actions button.x-btn-focus:not(.x-btn-over),.x-btn-focus.inline-button:not(.x-btn-over),.x-btn-focus.x-btn:not(.x-btn-over),.x-btn-focus.x-date-mp-cancel:not(.x-btn-over),.x-btn-focus.x-date-mp-ok:not(.x-btn-over),.x-btn-focus.x-form-trigger:not(.x-btn-over),.x-btn-focus.x-superboxselect-item:not(.x-btn-over){background:#fff;color:#515151}.actions button.x-btn-click,.actions button.x-btn-over,.actions button:active,.actions button:hover,.inline-button:active,.inline-button:hover,.x-btn-click.inline-button,.x-btn-click.x-btn,.x-btn-click.x-date-mp-cancel,.x-btn-click.x-date-mp-ok,.x-btn-click.x-form-trigger,.x-btn-click.x-superboxselect-item,.x-btn-over.inline-button,.x-btn-over.x-btn,.x-btn-over.x-date-mp-cancel,.x-btn-over.x-date-mp-ok,.x-btn-over.x-form-trigger,.x-btn-over.x-superboxselect-item,.x-btn:active,.x-btn:hover,.x-date-mp-cancel:active,.x-date-mp-cancel:hover,.x-date-mp-ok:active,.x-date-mp-ok:hover,.x-form-trigger:active,.x-form-trigger:hover,.x-superboxselect-item:active,.x-superboxselect-item:hover{background-color:#e4e4e4;box-shadow:#dcdcdc;color:#515151}.actions button.x-btn-menu-active .x-btn-split:before,.x-btn-menu-active.inline-button .x-btn-split:before,.x-btn-menu-active.x-btn .x-btn-split:before,.x-btn-menu-active.x-date-mp-cancel .x-btn-split:before,.x-btn-menu-active.x-date-mp-ok .x-btn-split:before,.x-btn-menu-active.x-form-trigger .x-btn-split:before,.x-btn-menu-active.x-superboxselect-item .x-btn-split:before{content:"\f0d8"}.actions button.x-item-disabled,.x-item-disabled.inline-button,.x-item-disabled.x-btn,.x-item-disabled.x-date-mp-cancel,.x-item-disabled.x-date-mp-ok,.x-item-disabled.x-form-trigger,.x-item-disabled.x-superboxselect-item{background-color:#fff;box-shadow:0 0 0 1px #e4e4e4;color:#1e1e1e;filter:alpha(opacity=60);opacity:.6}button{margin:2px}.x-panel-btns .x-btn{margin:0 0 0 7px}.actions{bottom:8px;margin:0;overflow:visible;position:absolute}.actions li{float:left;line-height:.7;margin-right:2px}.actions button,.inline-button,.x-date-mp-cancel,.x-date-mp-ok,.x-date-picker .x-btn,.x-form-trigger,.x-superboxselect-item{box-shadow:0 0 0 1px #dcdcdc;box-sizing:initial;padding:5px}.actions button:active,.actions button:focus,.actions button:hover,.inline-button:active,.inline-button:focus,.inline-button:hover,.x-date-mp-cancel:active,.x-date-mp-cancel:focus,.x-date-mp-cancel:hover,.x-date-mp-ok:active,.x-date-mp-ok:focus,.x-date-mp-ok:hover,.x-date-picker .x-btn:active,.x-date-picker .x-btn:focus,.x-date-picker .x-btn:hover,.x-form-trigger:active,.x-form-trigger:focus,.x-form-trigger:hover,.x-superboxselect-item:active,.x-superboxselect-item:focus,.x-superboxselect-item:hover{box-shadow:#999}.actions button.yellow,.inline-button.yellow,.x-date-mp-cancel.yellow,.x-date-mp-ok.yellow,.x-date-picker .x-btn.yellow,.x-form-trigger.yellow,.x-superboxselect-item.yellow{background:#fce588;box-shadow:0 0 0 1px #fce588;color:#515151!important}.actions button.yellow:focus,.actions button.yellow:hover,.inline-button.yellow:focus,.inline-button.yellow:hover,.x-date-mp-cancel.yellow:focus,.x-date-mp-cancel.yellow:hover,.x-date-mp-ok.yellow:focus,.x-date-mp-ok.yellow:hover,.x-date-picker .x-btn.yellow:focus,.x-date-picker .x-btn.yellow:hover,.x-form-trigger.yellow:focus,.x-form-trigger.yellow:hover,.x-superboxselect-item.yellow:focus,.x-superboxselect-item.yellow:hover{background:#fbe06f;box-shadow:0 0 0 1px #fbe06f}.actions button.yellow:active,.inline-button.yellow:active,.x-date-mp-cancel.yellow:active,.x-date-mp-ok.yellow:active,.x-date-picker .x-btn.yellow:active,.x-form-trigger.yellow:active,.x-superboxselect-item.yellow:active{background:#fbda56;box-shadow:0 0 0 1px #fbda56}.actions button.orange,.inline-button.orange,.x-date-mp-cancel.orange,.x-date-mp-ok.orange,.x-date-picker .x-btn.orange,.x-form-trigger.orange,.x-superboxselect-item.orange{background:#f0b429;box-shadow:0 0 0 1px #f0b429;color:#fff!important}.actions button.orange:focus,.actions button.orange:hover,.inline-button.orange:focus,.inline-button.orange:hover,.x-date-mp-cancel.orange:focus,.x-date-mp-cancel.orange:hover,.x-date-mp-ok.orange:focus,.x-date-mp-ok.orange:hover,.x-date-picker .x-btn.orange:focus,.x-date-picker .x-btn.orange:hover,.x-form-trigger.orange:focus,.x-form-trigger.orange:hover,.x-superboxselect-item.orange:focus,.x-superboxselect-item.orange:hover{background:#eeac11;box-shadow:0 0 0 1px #eeac11}.actions button.orange:active,.inline-button.orange:active,.x-date-mp-cancel.orange:active,.x-date-mp-ok.orange:active,.x-date-picker .x-btn.orange:active,.x-form-trigger.orange:active,.x-superboxselect-item.orange:active{background:#d79b0f;box-shadow:0 0 0 1px #d79b0f}.actions button.red,.inline-button.red,.x-date-mp-cancel.red,.x-date-mp-ok.red,.x-date-picker .x-btn.red,.x-form-trigger.red,.x-superboxselect-item.red{background:#cf1124;box-shadow:0 0 0 1px #cf1124;color:#fff!important}.actions button.red:focus,.actions button.red:hover,.inline-button.red:focus,.inline-button.red:hover,.x-date-mp-cancel.red:focus,.x-date-mp-cancel.red:hover,.x-date-mp-ok.red:focus,.x-date-mp-ok.red:hover,.x-date-picker .x-btn.red:focus,.x-date-picker .x-btn.red:hover,.x-form-trigger.red:focus,.x-form-trigger.red:hover,.x-superboxselect-item.red:focus,.x-superboxselect-item.red:hover{background:#c11022;box-shadow:0 0 0 1px #c11022}.actions button.red:active,.inline-button.red:active,.x-date-mp-cancel.red:active,.x-date-mp-ok.red:active,.x-date-picker .x-btn.red:active,.x-form-trigger.red:active,.x-superboxselect-item.red:active{background:#b30f1f;box-shadow:0 0 0 1px #b30f1f}.actions button.green,.inline-button.green,.x-date-mp-cancel.green,.x-date-mp-ok.green,.x-date-picker .x-btn.green,.x-form-trigger.green,.x-superboxselect-item.green{background:#6cb24a;box-shadow:0 0 0 1px #6cb24a;color:#fff!important}.actions button.green:focus,.actions button.green:hover,.inline-button.green:focus,.inline-button.green:hover,.x-date-mp-cancel.green:focus,.x-date-mp-cancel.green:hover,.x-date-mp-ok.green:focus,.x-date-mp-ok.green:hover,.x-date-picker .x-btn.green:focus,.x-date-picker .x-btn.green:hover,.x-form-trigger.green:focus,.x-form-trigger.green:hover,.x-superboxselect-item.green:focus,.x-superboxselect-item.green:hover{background:#61a043;box-shadow:0 0 0 1px #61a043}.actions button.green:active,.inline-button.green:active,.x-date-mp-cancel.green:active,.x-date-mp-ok.green:active,.x-date-picker .x-btn.green:active,.x-form-trigger.green:active,.x-superboxselect-item.green:active{background:#568e3b;box-shadow:0 0 0 1px #568e3b}.actions button.blue,.inline-button.blue,.x-date-mp-cancel.blue,.x-date-mp-ok.blue,.x-date-picker .x-btn.blue,.x-form-trigger.blue,.x-superboxselect-item.blue{background:#4a90e2;box-shadow:0 0 0 1px #4a90e2;color:#fff!important}.actions button.blue:focus,.actions button.blue:hover,.inline-button.blue:focus,.inline-button.blue:hover,.x-date-mp-cancel.blue:focus,.x-date-mp-cancel.blue:hover,.x-date-mp-ok.blue:focus,.x-date-mp-ok.blue:hover,.x-date-picker .x-btn.blue:focus,.x-date-picker .x-btn.blue:hover,.x-form-trigger.blue:focus,.x-form-trigger.blue:hover,.x-superboxselect-item.blue:focus,.x-superboxselect-item.blue:hover{background:#3483de;box-shadow:0 0 0 1px #3483de}.actions button.blue:active,.inline-button.blue:active,.x-date-mp-cancel.blue:active,.x-date-mp-ok.blue:active,.x-date-picker .x-btn.blue:active,.x-form-trigger.blue:active,.x-superboxselect-item.blue:active{background:#2275d7;box-shadow:0 0 0 1px #2275d7}.x-toolbar .x-form-field-trigger-wrap{background:#fff;border:0;border-radius:3px;box-shadow:0 0 0 1px #e4e4e4;cursor:pointer;line-height:1}.x-toolbar .x-form-field-trigger-wrap .x-form-text{background:#fff;border:0;margin:0!important}.x-toolbar .x-form-field-trigger-wrap .x-form-trigger:before{margin-top:0}.x-toolbar .x-form-field-trigger-wrap.x-trigger-wrap-focus{box-shadow:0 0 0 1px #999}html[dir=rtl] .x-toolbar-left table{float:right}.x-toolbar .x-toolbar-left-row .x-btn,.x-toolbar .x-toolbar-left-row .x-form-field-trigger-wrap,.x-toolbar .x-toolbar-left-row .x-form-text{margin:0 3px}.x-toolbar .x-toolbar-left-row td .x-btn{display:block}.x-toolbar .x-toolbar-left-row .x-form-filter{border-radius:3px 0 0 3px;z-index:1}.x-toolbar .x-toolbar-left-row .x-form-filter:not(.x-form-empty-field){border-color:#000}.x-toolbar .x-toolbar-left-row .x-form-filter.x-form-focus{border-color:#999}.x-toolbar .x-toolbar-left-row .x-form-filter-clear{border-radius:0 3px 3px 0;margin-right:0}.x-toolbar .x-toolbar-right-row .x-btn,.x-toolbar .x-toolbar-right-row .x-form-field-trigger-wrap,.x-toolbar .x-toolbar-right-row .x-form-text{margin:0 3px}.x-toolbar .x-toolbar-right-row td .x-btn{display:block}.x-toolbar .x-toolbar-right-row .x-form-filter{border-radius:3px 0 0 3px;z-index:1}.x-toolbar .x-toolbar-right-row .x-form-filter:not(.x-form-empty-field){border-color:#000}.x-toolbar .x-toolbar-right-row .x-form-filter.x-form-focus{border-color:#999}.x-toolbar .x-toolbar-right-row .x-form-filter-clear{border-radius:0 3px 3px 0;margin-left:0}.x-toolbar .x-form-text{border-radius:3px;font-size:13px!important;padding:8px 13px}.x-toolbar.x-small-editor .x-form-text{padding-top:8px}.x-toolbar .xtb-sep{margin:0;width:0}.x-tree .x-toolbar .x-btn{padding:7px}.x-tree .x-toolbar .x-btn-icon{box-shadow:none;padding:7px}.x-tree .x-toolbar .x-btn-icon.x-btn-over{background:none;box-shadow:none;color:#234368}.x-tree .x-toolbar .x-btn-icon.x-btn-click{background:none;box-shadow:none;color:#1b3451}.x-tree .x-toolbar .x-btn-icon:before{content:none}.x-tree .x-toolbar .x-toolbar-left-row .x-form-field-wrap,.x-tree .x-toolbar .x-toolbar-right-row .x-form-field-wrap{margin-left:6px!important;margin-right:6px}#modx-action-buttons{background:#f1f1f1;border:0;border-radius:3px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;left:auto;padding:.5rem 1rem;position:fixed;right:0;top:0;z-index:12}#modx-action-buttons .x-toolbar-cell{padding:.25rem}#modx-action-buttons .x-btn{margin:0}#modx-action-buttons #modx-abtn-menu .x-btn-split{padding:0}#modx-action-buttons #modx-abtn-menu .x-btn-split:before{display:none}#modx-action-buttons #modx-abtn-menu .x-btn-split .x-btn-text{border:none;padding:0}#modx-action-buttons .x-toolbar-left{zoom:1;width:auto!important}@media screen and (max-width:960px){#modx-action-buttons{background:#0000;border-radius:0;bottom:auto;left:auto;max-width:100%;padding:0 15px;position:relative;right:auto;top:auto}#modx-action-buttons table table:not(#modx-tree-panel-usergroup table,#modx-grid-lexicon table,#modx-panel-property-sets),#modx-action-buttons table table:not(#modx-tree-panel-usergroup table,#modx-grid-lexicon table,#modx-panel-property-sets) tbody{display:block}#modx-action-buttons table table:not(#modx-tree-panel-usergroup table,#modx-grid-lexicon table,#modx-panel-property-sets) tbody tr{display:flex;flex-wrap:wrap;margin-left:auto;margin-right:auto;max-width:1200px}#modx-action-buttons table table:not(#modx-tree-panel-usergroup table,#modx-grid-lexicon table,#modx-panel-property-sets) tbody tr:after{clear:both;content:"";display:block}#modx-action-buttons table table:not(#modx-tree-panel-usergroup table,#modx-grid-lexicon table,#modx-panel-property-sets) tbody tr td{display:inline-block;flex-grow:1;float:left;margin-bottom:1em;padding:0!important}#modx-action-buttons table table:not(#modx-tree-panel-usergroup table,#modx-grid-lexicon table,#modx-panel-property-sets) tbody tr td .x-btn{margin-left:3px;margin-right:3px}#modx-panel-welcome #modx-action-buttons{display:none}#modx-action-buttons .x-toolbar-cell{margin:5px;width:auto}.tab-panel-wrapper .x-panel-tbar table:not(#modx-tree-panel-usergroup table,#modx-grid-lexicon table,#modx-panel-property-sets),.tab-panel-wrapper .x-panel-tbar table:not(#modx-tree-panel-usergroup table,#modx-grid-lexicon table,#modx-panel-property-sets) tbody{display:block}.tab-panel-wrapper .x-panel-tbar table:not(#modx-tree-panel-usergroup table,#modx-grid-lexicon table,#modx-panel-property-sets) tbody tr{display:flex;flex-wrap:wrap;margin-left:auto;margin-right:auto;max-width:1200px}.tab-panel-wrapper .x-panel-tbar table:not(#modx-tree-panel-usergroup table,#modx-grid-lexicon table,#modx-panel-property-sets) tbody tr:after{clear:both;content:"";display:block}.tab-panel-wrapper .x-panel-tbar table:not(#modx-tree-panel-usergroup table,#modx-grid-lexicon table,#modx-panel-property-sets) tbody tr td{display:inline-block;flex-grow:1;float:left;margin-bottom:1em;padding:0!important}.tab-panel-wrapper .x-panel-tbar table:not(#modx-tree-panel-usergroup table,#modx-grid-lexicon table,#modx-panel-property-sets) tbody tr td .x-btn{margin-left:3px;margin-right:3px}.tab-panel-wrapper .x-panel-tbar .x-toolbar-left input,.tab-panel-wrapper .x-panel-tbar .x-toolbar-right input{box-sizing:border-box;height:auto!important;margin-left:0;width:100%}html.ext-strict body #modx-container .x-small-editor .x-form-text{height:auto!important}#modx-grid-element-properties table:not(#modx-tree-panel-usergroup table,#modx-grid-lexicon table,#modx-panel-property-sets),#modx-grid-element-properties table:not(#modx-tree-panel-usergroup table,#modx-grid-lexicon table,#modx-panel-property-sets) tbody{display:block}#modx-grid-element-properties table:not(#modx-tree-panel-usergroup table,#modx-grid-lexicon table,#modx-panel-property-sets) tbody tr{display:flex;flex-wrap:wrap;margin-left:auto;margin-right:auto;max-width:1200px}#modx-grid-element-properties table:not(#modx-tree-panel-usergroup table,#modx-grid-lexicon table,#modx-panel-property-sets) tbody tr:after{clear:both;content:"";display:block}#modx-grid-element-properties table:not(#modx-tree-panel-usergroup table,#modx-grid-lexicon table,#modx-panel-property-sets) tbody tr td{display:inline-block;flex-grow:1;float:left;margin-bottom:1em;padding:0!important}#modx-grid-element-properties table:not(#modx-tree-panel-usergroup table,#modx-grid-lexicon table,#modx-panel-property-sets) tbody tr td .x-btn{margin-left:3px;margin-right:3px}#modx-grid-element-properties .x-toolbar-left{margin-bottom:0}#modx-grid-element-properties .x-toolbar-cell>*{box-sizing:border-box;margin-left:auto;margin-right:auto;width:100%!important}}.x-btn-icon button{font-size:18px;height:18px;position:relative;width:18px}.x-btn-icon.arrow_up button{background:none!important;position:relative}.x-btn-icon.arrow_up button:before{bottom:auto;content:"\f3bf";top:1px}.x-btn-icon.arrow_down button{background:none!important;position:relative}.x-btn-icon.arrow_down button:before{bottom:auto;content:"\f3be";top:1px}.x-btn-icon.refresh button{background:none!important;position:relative}.x-btn-icon.refresh button:before{bottom:auto;content:"\f021";top:1px}.x-btn-icon.icon-folder button:before{content:"\f07b"}.x-btn-icon.icon-page_white button:before{content:"\f15c"}.x-btn-icon.icon-file_upload button:before{content:"\f35b"}.x-btn-icon.icon-file_manager button:before{content:"\f14d"}.x-btn-text-icon button{padding-left:20px!important}.x-html-editor-tb .x-btn{background-color:initial;background-image:none;border:0;box-shadow:none;margin:0}.x-html-editor-tb .x-btn-over{border:0}.x-btn-group{border:1px solid #dbe0e4;border-radius:3px;margin-right:2px;padding:0}.x-btn-group .x-btn{background-color:initial;background-image:none;border:1px solid #0000;box-shadow:0 0 1px #0000}.x-btn-group .x-btn button{color:#868b8f;height:auto!important}.x-btn-group .x-btn-over{background:#dfdfdf;background:#f0f0f0;border:1px solid #dbe0e4}.x-btn-group .x-btn-over button{color:#5b7a98}.x-btn-group .x-btn-click{background-color:#fff;background-image:none;box-shadow:inset 0 0 3px #aaa;margin:0 2px 0 0}.x-btn-group-bwrap{padding:1px 0 0}.x-btn-group-header{background-color:#dbe0e4;color:#73797f;text-shadow:0 1px 0 #fafafa}.x-btn-group-tl,.x-btn-group-tr{background-image:none;padding:0}.x-btn-group-bc,.x-btn-group-bl,.x-btn-group-br,.x-btn-group-ml,.x-btn-group-tc{background-image:none}.x-btn-group-ml{padding-left:1px}.x-btn-group-mr{background-image:none;padding-right:1px}.x-btn em.x-btn-arrow-bottom{background-image:url(../images/modx-theme/button/s-arrow-b-noline.gif)}.x-btn em.x-btn-split-bottom{background-image:url(../images/modx-theme/button/s-arrow-b.gif)}.x-btn-click em.x-btn-split-bottom,.x-btn-menu-active em.x-btn-split-bottom,.x-btn-over em.x-btn-split-bottom,.x-btn-pressed em.x-btn-split-bottom{background-image:url(../images/modx-theme/button/s-arrow-bo.gif)}.x-btn-group-notitle .x-btn-group-tc{background-image:url(../images/modx-theme/button/group-tb.gif)}#modx-leftbar .x-toolbar-ct .x-btn{background:#f1f1f1;border:none;box-shadow:none;color:#383838;display:inline-block;filter:alpha(opacity=100);height:30px;margin:0 3px;opacity:1;padding:0;position:relative;width:25px}#modx-leftbar .x-toolbar-ct .x-btn>em>button{font-size:18px;height:24px;left:2px;overflow:visible;position:absolute;text-shadow:none;top:4px}#modx-leftbar .x-toolbar-ct .x-btn.x-btn-click,#modx-leftbar .x-toolbar-ct .x-btn.x-btn-focus,#modx-leftbar .x-toolbar-ct .x-btn.x-btn-over,#modx-leftbar .x-toolbar-ct .x-btn:active,#modx-leftbar .x-toolbar-ct .x-btn:focus,#modx-leftbar .x-toolbar-ct .x-btn:hover{background:none;box-shadow:none;color:#234368}#modx-leftbar .x-toolbar-ct .x-btn.x-btn-click button,#modx-leftbar .x-toolbar-ct .x-btn.x-btn-focus button,#modx-leftbar .x-toolbar-ct .x-btn.x-btn-over button,#modx-leftbar .x-toolbar-ct .x-btn:active button,#modx-leftbar .x-toolbar-ct .x-btn:focus button,#modx-leftbar .x-toolbar-ct .x-btn:hover button{color:inherit}#modx-leftbar .x-toolbar-ct .x-btn span{vertical-align:middle}#modx-leftbar .x-toolbar-ct .x-toolbar-right .x-btn>em>button{font-size:20px}#modx-leftbar .x-toolbar-ct .x-toolbar-right .x-btn#emptifier .x-item-disabled{color:#777!important;filter:alpha(opacity=60); - /* !important prevents hover / active styles */opacity:.6}#modx-leftbar .x-toolbar-ct .x-toolbar-right .x-btn#emptifier .x-item-disabled button{color:inherit}.tree-new-resource>em>button:before{content:"\f15b"}.tree-new-weblink>em>button:before{content:"\f0c1"}.tree-new-symlink>em>button:before{content:"\f0c5";font-weight:400}.tree-new-static-resource>em>button:before{content:"\f15c";font-weight:400}#modx-leftbar .x-toolbar-ct .x-btn .tree-new-symlink>em>button{left:2px;top:4px}#modx-leftbar .x-toolbar-ct .x-btn .tree-new-weblink>em>button{left:2px}.tree-new-template>em>button:before{content:"\f0db"}.tree-new-tv>em>button:before{content:"\f022";font-weight:400}.tree-new-chunk>em>button:before{content:"\f009";font-weight:900}.tree-new-snippet>em>button:before{content:"\f121"}.tree-new-plugin>em>button:before{content:"\f085"}.tree-new-category>em>button:before{content:"\f07b"}.modx-tv .resizable:hover:after,.modx-tv .resizable:hover:before{background-color:#99999940;color:#999}.modx-tv .resizable:after,.modx-tv .resizable:before{background-color:#99999926;color:#adadad;font-size:smaller;margin-right:.25%;pointer-events:none;position:absolute;right:0;text-align:center;width:15px;z-index:2}.modx-tv .resizable:before{bottom:12px;content:"\f106";height:7px;line-height:.9}.modx-tv .resizable:after{border-bottom-right-radius:3px;bottom:4px;content:"\f107";height:8px;line-height:.6}.modx-tv .resizable textarea{resize:vertical}.modx-tv .x-form-textarea:not(div){font-family:inherit}textarea{overflow:auto}.x-form-textarea,textarea.x-form-field{display:block;padding:5px}.modx-code-content,.x-form-textarea,textarea.x-form-field{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.modx-text-content,textarea[name=description],textarea[name=introtext]{font:normal 13px/1.4 -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.x-form-text,.x-form-textarea,textarea.x-form-field{background-color:#fff;background-image:none;border:1px solid #e4e4e4;border-radius:3px;max-width:100%;position:relative;transition:border-color .25s}.x-viewport .x-form-textarea .x-form-focus,.x-viewport .x-trigger-wrap-focus,.x-viewport input.x-form-focus,.x-viewport textarea.x-form-focus{border-color:#999}.x-viewport .x-trigger-wrap-open{border-radius:3px 3px 0 0}.x-form-invalid,textarea.x-form-invalid{border-color:#cf1124!important}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}#modx-input-props,#modx-widget-props{padding:15px 0 0}.x-form-item{display:block;margin:0;outline:0 none;position:relative;z-index:1}.x-form-item label.x-form-item-label{color:#515151;font-size:13px;font-weight:700;position:relative}.x-form-item label.x-form-item-label .modx-tv-label-title{display:inline-block}.x-form-item label.x-form-item-label .modx-tv-label-description{display:inline-block;font-style:italic;font-weight:400}.x-form-item label.x-form-item-label .modx-field-utils,.x-form-item label.x-form-item-label .modx-tv-reset{cursor:pointer;display:inline-block;filter:alpha(opacity=0);height:16px;opacity:0;padding:0 0 0 3px;position:relative;right:0;top:0;transition:all .25s;width:16px}.x-form-item label.x-form-item-label .modx-field-utils:before,.x-form-item label.x-form-item-label .modx-tv-reset:before{bottom:2px;box-sizing:border-box;color:#a8a8a8;content:"\f2ea";font-size:14px;height:16px;left:0;position:relative;text-align:center;vertical-align:middle;width:16px}.x-form-item label.x-form-item-label .modx-field-utils.modx-field-reset:before,.x-form-item label.x-form-item-label .modx-tv-reset.modx-field-reset:before{content:"\f2ea"}.x-form-item label.x-form-item-label .modx-field-utils.modx-field-reset:hover:before,.x-form-item label.x-form-item-label .modx-tv-reset.modx-field-reset:hover:before{color:#6cb24a}.x-form-item label.x-form-item-label .modx-field-utils.modx-field-clear:before,.x-form-item label.x-form-item-label .modx-tv-reset.modx-field-clear:before{content:"\f12d";font-size:15px;margin-bottom:4px}.x-form-item label.x-form-item-label .modx-field-utils.modx-field-clear:hover:before,.x-form-item label.x-form-item-label .modx-tv-reset.modx-field-clear:hover:before{color:#cf1124}.x-form-item label.x-form-item-label .modx-field-utils:hover:before,.x-form-item label.x-form-item-label .modx-tv-reset:hover:before{color:#6cb24a}.x-form-item label.x-form-item-label .modx-field-utils:active:before,.x-form-item label.x-form-item-label .modx-tv-reset:active:before{color:#1b3451}.x-form-item label.x-form-item-label:hover .modx-field-utils,.x-form-item label.x-form-item-label:hover .modx-tv-reset{filter:alpha(opacity=100);opacity:1}.x-form-item.modx-tv{padding:0!important}.x-form-item .modx-tv-inherited{color:#515151;display:inline-block;font-size:10px;font-style:italic;position:absolute;right:0;top:19px}.x-form-item .modx-tv-image-preview{margin-top:7px}.x-form-item .modx-tv-image-preview img{display:block;max-height:400px;max-width:400px}.x-form-item .modx-tag-list{list-style:none;margin:0;overflow:auto;padding:0}.x-form-item .modx-tag-list .modx-tag-opt{background-color:#e4e4e4;border-radius:0 3px 3px 0;cursor:pointer;display:inline-block;margin:4px 5px 0 10px;padding:1px 5px;position:relative}.x-form-item .modx-tag-list .modx-tag-opt:before{border-color:#0000 #e4e4e4 #0000 #0000;border-style:solid;border-width:10px 10px 10px 0;content:"";height:0;left:-10px;position:absolute;top:0;transform:rotate(1turn);width:0}.x-form-item .modx-tag-list .modx-tag-opt:after{background-color:#fff;border-radius:50%;content:"";height:4px;left:-4px;position:absolute;top:8px;width:4px}.x-form-item .modx-tag-list .modx-tag-opt.modx-tag-checked,.x-form-item .modx-tag-list .modx-tag-opt:hover{background-color:#234368;color:#fff;text-decoration:none}.x-form-item .modx-tag-list .modx-tag-opt.modx-tag-checked:before,.x-form-item .modx-tag-list .modx-tag-opt:hover:before{border-color:#0000 #234368 #0000 #0000}.x-form-item .modx-tag-list .modx-tag-opt.modx-tag-checked:hover,.x-form-item .modx-tag-list .modx-tag-opt:hover:hover{background-color:#1b3451}.x-form-item .modx-tag-list .modx-tag-opt.modx-tag-checked:hover:before,.x-form-item .modx-tag-list .modx-tag-opt:hover:hover:before{border-color:#0000 #1b3451 #0000 #0000}.x-form-item .modx-tv-legacy-select{border:1px solid #e4e4e4;border-radius:3px;padding:5px;transition:all .25s}.x-form-item .modx-tv-legacy-select:focus{border:1px solid #1b3451}.x-form-item .modx-tv-legacy-select option[selected]{background-color:#e4e4e4}.x-form-label-left .x-form-item{padding:15px 0 0}.x-form-label-left .x-form-item:first-of-type{padding:0}.x-form-label-left .x-form-item label.x-form-item-label{display:inline-block;margin:0;padding:7px 0}.x-form-label-top .x-form-item{padding:0}.x-form-label-top .x-form-item label.x-form-item-label{display:inline-block;margin:15px 0 4px;padding:0}.x-window .x-form-item .x-form-item-label{padding:10px 0 4px}.x-form-item.x-hide-label{padding-top:10px!important}#modx-resource-content .x-form-item.x-hide-label{padding-top:0!important}.x-form-item.x-hide-label label.x-form-item-label{display:none}.x-form-item.disabled label{color:#a8a8a8}.x-form-item .x-form-element{font:normal 13px/1.4 -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;padding:0}.x-form-item .x-form-element .x-form-invalid-icon{color:#cf1124}.x-form-item .x-form-element .x-form-invalid-icon:before{content:"\f071";left:3px;position:absolute}.x-form-item .x-column-inner>.x-column~.x-column{margin-left:5px}.x-form-item .x-column-inner>.x-column .x-form-field-wrap{width:auto!important}.x-form-item .container{margin:0}.x-form-item .x-btn{padding:7px 10px}.desc-under{color:#999;display:block;font-size:12px;font-style:italic;margin:.4em 0 0;transition:color .25s}.desc-under:hover{color:#4d4d4d}.desc-under.toggle-slider-above{margin:.3em 0;padding-left:3.9em}.desc-under .warning{color:#cf1124;overflow:hidden;padding:0}.desc-under .example-list ul{margin:.4em 0}.desc-under .example-list ul li{margin-bottom:.25em;padding-left:1.25em;position:relative}.desc-under .example-list ul li:before{color:#adadad;content:"\f101";left:.2em;position:absolute;top:0}.desc-under .copy-this,.desc-under .example-input{border-radius:2px;padding:0 .3em;transition:width 1s}.desc-under .example-input{background-color:#f6faf5;color:#6e935d}.desc-under .example-input:hover{background-color:#eff6ec;color:#578c3d;cursor:pointer}.desc-under .copy-this{background-color:#f1f6fc;color:#5e8bbf;position:relative}.desc-under .copy-this:hover{background-color:#e7f1fb;color:#1b5ca8;cursor:pointer}.desc-under .copy-this:hover:after{color:#6892c4;content:"\f0c5";cursor:default;margin-left:.5em;position:absolute}.desc-under .copy-this:hover:active,.desc-under .copy-this:hover:active:after{color:#515151}.desc-under .feedback{color:#1b5ca8;font-style:normal;margin-left:1.4rem}.desc-under .feedback.item-copied{opacity:1;transition:opacity 1.5s}.desc-under a{border-bottom:1px dotted #999;color:#999;text-decoration:none}.desc-under a:hover{color:#515151}.desc-under .deemphasize{font-style:normal}.fs-toggle{border-top:1px dashed #e4e4e4;margin-bottom:.5em;margin-top:2em;padding-top:1em}.x-fieldset{border:1px solid #e4e4e4;border-radius:3px!important; - /* !important ensures the border radius, also when the fieldset has a class that sets it to 0 */margin:15px 0 0;overflow:visible;padding:0;position:relative}.x-fieldset .x-fieldset-header{color:#515151;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-weight:700;margin:0 0 0 10px;padding:0 5px 0 3px;position:relative}.x-fieldset .x-fieldset-header .x-fieldset-header-text{line-height:18px}.x-fieldset .x-fieldset-bwrap .x-fieldset-body{overflow-x:hidden!important;padding:0 10px 10px}.x-fieldset.form-row-wrapper .x-fieldset-bwrap .x-fieldset-body{padding:0 15px 15px}.x-fieldset#tv-input-opts-fs,.x-fieldset#tv-output-opts-fs{border:0;margin:0}.x-fieldset#tv-input-opts-fs .x-fieldset-bwrap .x-fieldset-body,.x-fieldset#tv-output-opts-fs .x-fieldset-bwrap .x-fieldset-body{padding:0}.x-fieldset#tv-input-opts-fs .x-fieldset .x-fieldset-bwrap .x-fieldset-body,.x-fieldset#tv-output-opts-fs .x-fieldset .x-fieldset-bwrap .x-fieldset-body{padding:0 15px 15px}.x-form-field{font:inherit}.x-form-field.x-form-composite{margin-bottom:0!important}.x-form-field.x-form-composite .x-btn{top:1px!important}.x-static-text-field{color:inherit;font-size:inherit}.x-static-text-field.x-form-focus{border-color:#e4e4e4!important}.x-form-text{line-height:20px;min-height:20px;padding:5px}.x-form-field-wrap{background:#fff;border:1px solid #e4e4e4;border-radius:3px;max-width:100%}.x-form-field-wrap .x-form-text:not(.x-form-invalid){border:0}.x-form-field-wrap .x-form-trigger{border:0;border-radius:0 2px 2px 0;box-shadow:none;height:100%!important;padding:0;position:absolute;right:0;top:0;width:30px}.x-form-field-wrap .x-form-trigger:before{box-sizing:border-box;content:"\f078";filter:alpha(opacity=60);font-size:14px;left:50%;opacity:.8;position:absolute;text-align:center;top:50%;transform:translate(-50%,-50%);transition:opacity .25s;width:30px}.x-form-field-wrap .x-form-trigger.x-form-trigger-click:before,.x-form-field-wrap .x-form-trigger.x-form-trigger-over:before,.x-form-field-wrap .x-form-trigger:active:before,.x-form-field-wrap .x-form-trigger:hover:before{filter:alpha(opacity=100);opacity:1}.x-form-field-wrap .x-form-trigger.x-form-date-trigger:before{content:"\f133";font-weight:400}.x-form-field-wrap .x-form-trigger.x-form-time-trigger:before{content:"\f017";font-weight:400}.x-form-field-wrap .x-form-trigger.x-form-file-trigger:before{content:"\f15b";font-weight:400}.x-form-field-wrap .x-form-trigger.x-form-image-trigger:before{content:"\f1c5";font-weight:400}.x-form-field-wrap .x-form-trigger.x-form-code-trigger:before{content:"\f1c9";font-weight:400}.x-form-field-wrap.x-datetime-wrap{background:none;border:0}.x-form-field-wrap.x-datetime-wrap .ux-datetime-date,.x-form-field-wrap.x-datetime-wrap .ux-datetime-time{vertical-align:top}.x-form-field-wrap.x-datetime-wrap .ux-datetime-date .x-form-invalid-msg,.x-form-field-wrap.x-datetime-wrap .ux-datetime-time .x-form-invalid-msg{white-space:normal}.x-form-field-wrap.x-datetime-wrap .ux-datetime-date .x-form-trigger:before{content:"\f133"}.x-form-field-wrap.x-datetime-wrap .ux-datetime-time .x-form-trigger:before{content:"\f017"}.x-form-field-wrap.x-form-fileupload-wrap{overflow:visible;position:relative}.x-form-field-wrap.x-form-fileupload-wrap .x-form-file{filter:alpha(opacity=0);min-height:20px;opacity:0;padding:5px;position:absolute;right:0;top:0;z-index:2}.x-form-field-wrap.x-form-fileupload-wrap .x-form-file-btn{border-left:1px solid #e4e4e4;border-radius:0 3px 3px 0;box-shadow:none;line-height:0;padding:7px;position:absolute;right:0;top:0;z-index:1}.x-form-field-wrap.x-form-fileupload-wrap .x-form-file-text{position:relative;z-index:3}.modx-tv-type-listbox-multiple .x-form-field-wrap{border-color:#fff}.modx-tv-type-listbox-multiple .x-form-field-wrap .x-form-text{border:1px solid #e4e4e4;margin:-1px}.modx-tv-type-listbox-multiple .x-form-field-wrap .x-form-text.x-form-focus{border-color:#999}#x-form-el-modx-user-photo .x-form-file-trigger:before{content:"\f1c5"}.x-fieldset-checkbox-toggle legend,.x-form-check-wrap{height:auto!important;line-height:18px}.x-form-label-left .x-fieldset-checkbox-toggle legend,.x-form-label-left .x-form-check-wrap{padding:7px 0}.x-form-label-top .x-fieldset-checkbox-toggle legend,.x-form-label-top .x-form-check-wrap{padding:0}.x-toolbar .x-toolbar-cell .x-fieldset-checkbox-toggle legend .x-form-cb-label,.x-toolbar .x-toolbar-cell .x-form-check-wrap .x-form-cb-label{padding-left:1.9em}.x-toolbar .x-toolbar-cell .x-fieldset-checkbox-toggle legend .x-form-cb-label:before,.x-toolbar .x-toolbar-cell .x-form-check-wrap .x-form-cb-label:before{color:#ccc}.x-toolbar .x-toolbar-cell .x-fieldset-checkbox-toggle legend .x-form-cb-label:active:before,.x-toolbar .x-toolbar-cell .x-fieldset-checkbox-toggle legend .x-form-cb-label:focus:before,.x-toolbar .x-toolbar-cell .x-fieldset-checkbox-toggle legend .x-form-cb-label:hover:before,.x-toolbar .x-toolbar-cell .x-form-check-wrap .x-form-cb-label:active:before,.x-toolbar .x-toolbar-cell .x-form-check-wrap .x-form-cb-label:focus:before,.x-toolbar .x-toolbar-cell .x-form-check-wrap .x-form-cb-label:hover:before{color:#999}.x-fieldset-checkbox-toggle legend .x-fieldset-header-text,.x-fieldset-checkbox-toggle legend .x-form-cb-label,.x-form-check-wrap .x-fieldset-header-text,.x-form-check-wrap .x-form-cb-label{color:#515151;cursor:pointer;display:inline-block;font-weight:400;margin:0;padding-left:1.9em;position:relative;top:0}.ext-ie8 .x-fieldset-checkbox-toggle legend .x-fieldset-header-text,.ext-ie8 .x-fieldset-checkbox-toggle legend .x-form-cb-label,.ext-ie8 .x-form-check-wrap .x-fieldset-header-text,.ext-ie8 .x-form-check-wrap .x-form-cb-label{padding-left:3px}.ext-ie8 .x-fieldset-checkbox-toggle legend .x-fieldset-header-text:before,.ext-ie8 .x-fieldset-checkbox-toggle legend .x-form-cb-label:before,.ext-ie8 .x-form-check-wrap .x-fieldset-header-text:before,.ext-ie8 .x-form-check-wrap .x-form-cb-label:before{content:""}.x-fieldset-checkbox-toggle legend .x-fieldset-header-text:before,.x-fieldset-checkbox-toggle legend .x-form-cb-label:before,.x-form-check-wrap .x-fieldset-header-text:before,.x-form-check-wrap .x-form-cb-label:before{box-sizing:border-box;content:"";font-size:18px;height:18px;left:0;padding-right:3px;position:absolute;text-align:center;top:0;vertical-align:middle;width:18px}.x-fieldset-checkbox-toggle legend .x-fieldset-header-text:focus:before,.x-fieldset-checkbox-toggle legend .x-fieldset-header-text:hover:before,.x-fieldset-checkbox-toggle legend .x-form-cb-label:focus:before,.x-fieldset-checkbox-toggle legend .x-form-cb-label:hover:before,.x-form-check-wrap .x-fieldset-header-text:focus:before,.x-form-check-wrap .x-fieldset-header-text:hover:before,.x-form-check-wrap .x-form-cb-label:focus:before,.x-form-check-wrap .x-form-cb-label:hover:before{color:#234368}.x-fieldset-checkbox-toggle legend .x-fieldset-header-text:active:before,.x-fieldset-checkbox-toggle legend .x-form-cb-label:active:before,.x-form-check-wrap .x-fieldset-header-text:active:before,.x-form-check-wrap .x-form-cb-label:active:before{color:#1b3451}.x-fieldset-checkbox-toggle legend .x-form-checkbox,.x-fieldset-checkbox-toggle legend .x-form-radio,.x-fieldset-checkbox-toggle legend input[type=checkbox],.x-form-check-wrap .x-form-checkbox,.x-form-check-wrap .x-form-radio,.x-form-check-wrap input[type=checkbox]{cursor:pointer;height:18px;left:0;opacity:0;position:absolute;top:0;width:18px;z-index:1}.ext-ie8 .x-fieldset-checkbox-toggle legend .x-form-checkbox,.ext-ie8 .x-fieldset-checkbox-toggle legend .x-form-radio,.ext-ie8 .x-fieldset-checkbox-toggle legend input[type=checkbox],.ext-ie8 .x-form-check-wrap .x-form-checkbox,.ext-ie8 .x-form-check-wrap .x-form-radio,.ext-ie8 .x-form-check-wrap input[type=checkbox]{height:13px;left:auto;position:relative;top:auto;width:13px}.x-fieldset-checkbox-toggle legend .x-form-checkbox:focus+.x-fieldset-header-text:before,.x-fieldset-checkbox-toggle legend .x-form-checkbox:focus+.x-form-cb-label:before,.x-fieldset-checkbox-toggle legend .x-form-checkbox:hover+.x-fieldset-header-text:before,.x-fieldset-checkbox-toggle legend .x-form-checkbox:hover+.x-form-cb-label:before,.x-fieldset-checkbox-toggle legend .x-form-radio:focus+.x-fieldset-header-text:before,.x-fieldset-checkbox-toggle legend .x-form-radio:focus+.x-form-cb-label:before,.x-fieldset-checkbox-toggle legend .x-form-radio:hover+.x-fieldset-header-text:before,.x-fieldset-checkbox-toggle legend .x-form-radio:hover+.x-form-cb-label:before,.x-fieldset-checkbox-toggle legend input[type=checkbox]:focus+.x-fieldset-header-text:before,.x-fieldset-checkbox-toggle legend input[type=checkbox]:focus+.x-form-cb-label:before,.x-fieldset-checkbox-toggle legend input[type=checkbox]:hover+.x-fieldset-header-text:before,.x-fieldset-checkbox-toggle legend input[type=checkbox]:hover+.x-form-cb-label:before,.x-form-check-wrap .x-form-checkbox:focus+.x-fieldset-header-text:before,.x-form-check-wrap .x-form-checkbox:focus+.x-form-cb-label:before,.x-form-check-wrap .x-form-checkbox:hover+.x-fieldset-header-text:before,.x-form-check-wrap .x-form-checkbox:hover+.x-form-cb-label:before,.x-form-check-wrap .x-form-radio:focus+.x-fieldset-header-text:before,.x-form-check-wrap .x-form-radio:focus+.x-form-cb-label:before,.x-form-check-wrap .x-form-radio:hover+.x-fieldset-header-text:before,.x-form-check-wrap .x-form-radio:hover+.x-form-cb-label:before,.x-form-check-wrap input[type=checkbox]:focus+.x-fieldset-header-text:before,.x-form-check-wrap input[type=checkbox]:focus+.x-form-cb-label:before,.x-form-check-wrap input[type=checkbox]:hover+.x-fieldset-header-text:before,.x-form-check-wrap input[type=checkbox]:hover+.x-form-cb-label:before{color:#234368}.x-fieldset-checkbox-toggle legend .x-form-checkbox:active+.x-fieldset-header-text:before,.x-fieldset-checkbox-toggle legend .x-form-checkbox:active+.x-form-cb-label:before,.x-fieldset-checkbox-toggle legend .x-form-radio:active+.x-fieldset-header-text:before,.x-fieldset-checkbox-toggle legend .x-form-radio:active+.x-form-cb-label:before,.x-fieldset-checkbox-toggle legend input[type=checkbox]:active+.x-fieldset-header-text:before,.x-fieldset-checkbox-toggle legend input[type=checkbox]:active+.x-form-cb-label:before,.x-form-check-wrap .x-form-checkbox:active+.x-fieldset-header-text:before,.x-form-check-wrap .x-form-checkbox:active+.x-form-cb-label:before,.x-form-check-wrap .x-form-radio:active+.x-fieldset-header-text:before,.x-form-check-wrap .x-form-radio:active+.x-form-cb-label:before,.x-form-check-wrap input[type=checkbox]:active+.x-fieldset-header-text:before,.x-form-check-wrap input[type=checkbox]:active+.x-form-cb-label:before{color:#1b3451}.x-fieldset-checkbox-toggle legend .x-form-checkbox+.x-form-cb-label:before,.x-fieldset-checkbox-toggle legend input[type=checkbox]+.x-fieldset-header-text:before,.x-form-check-wrap .x-form-checkbox+.x-form-cb-label:before,.x-form-check-wrap input[type=checkbox]+.x-fieldset-header-text:before{content:"\f0c8";font-weight:400}.x-fieldset-checkbox-toggle legend .x-form-checkbox:checked+.x-form-cb-label:before,.x-fieldset-checkbox-toggle legend input[type=checkbox]:checked+.x-fieldset-header-text:before,.x-form-check-wrap .x-form-checkbox:checked+.x-form-cb-label:before,.x-form-check-wrap input[type=checkbox]:checked+.x-fieldset-header-text:before{content:"\f14a";font-weight:400}.x-fieldset-checkbox-toggle legend .x-form-radio+.x-form-cb-label:before,.x-form-check-wrap .x-form-radio+.x-form-cb-label:before{content:"\f111";font-weight:400}.x-fieldset-checkbox-toggle legend .x-form-radio:checked+.x-form-cb-label:before,.x-form-check-wrap .x-form-radio:checked+.x-form-cb-label:before{content:"\f192";font-weight:400}#modx-chunk-tabs.space-before,#modx-plugin-tabs.space-before,#modx-resource-tabs .display-switch.space-before,#modx-snippet-tabs.space-before,#modx-template-tabs.space-before,#modx-tv-editor-tabs.space-before,#modx-tv-tabs .display-switch.space-before,.display-switch.space-before{margin-top:.75rem}#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox],#modx-chunk-tabs .x-fieldset legend [type=checkbox],#modx-chunk-tabs .x-form-check-wrap [type=checkbox],#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox],#modx-plugin-tabs .x-fieldset legend [type=checkbox],#modx-plugin-tabs .x-form-check-wrap [type=checkbox],#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox],#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox],#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox],#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox],#modx-snippet-tabs .x-fieldset legend [type=checkbox],#modx-snippet-tabs .x-form-check-wrap [type=checkbox],#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox],#modx-template-tabs .x-fieldset legend [type=checkbox],#modx-template-tabs .x-form-check-wrap [type=checkbox],#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox],#modx-tv-editor-tabs .x-fieldset legend [type=checkbox],#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox],#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox],#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox],#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox],.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox],.display-switch .x-fieldset legend [type=checkbox],.display-switch .x-form-check-wrap [type=checkbox]{left:-9999px;position:absolute}html[dir=rtl] #modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox],html[dir=rtl] #modx-chunk-tabs .x-fieldset legend [type=checkbox],html[dir=rtl] #modx-chunk-tabs .x-form-check-wrap [type=checkbox],html[dir=rtl] #modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox],html[dir=rtl] #modx-plugin-tabs .x-fieldset legend [type=checkbox],html[dir=rtl] #modx-plugin-tabs .x-form-check-wrap [type=checkbox],html[dir=rtl] #modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox],html[dir=rtl] #modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox],html[dir=rtl] #modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox],html[dir=rtl] #modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox],html[dir=rtl] #modx-snippet-tabs .x-fieldset legend [type=checkbox],html[dir=rtl] #modx-snippet-tabs .x-form-check-wrap [type=checkbox],html[dir=rtl] #modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox],html[dir=rtl] #modx-template-tabs .x-fieldset legend [type=checkbox],html[dir=rtl] #modx-template-tabs .x-form-check-wrap [type=checkbox],html[dir=rtl] #modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox],html[dir=rtl] #modx-tv-editor-tabs .x-fieldset legend [type=checkbox],html[dir=rtl] #modx-tv-editor-tabs .x-form-check-wrap [type=checkbox],html[dir=rtl] #modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox],html[dir=rtl] #modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox],html[dir=rtl] #modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox],html[dir=rtl] .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox],html[dir=rtl] .display-switch .x-fieldset legend [type=checkbox],html[dir=rtl] .display-switch .x-form-check-wrap [type=checkbox]{left:unset;right:-9999px}#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text,#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label,#modx-chunk-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text,#modx-chunk-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label,#modx-plugin-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text,#modx-plugin-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label,#modx-snippet-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text,#modx-snippet-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label,#modx-template-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text,#modx-template-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label,#modx-template-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text,#modx-template-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label,.display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text,.display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label,.display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text,.display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label{box-sizing:border-box;cursor:pointer;line-height:1;margin-left:0;padding-left:3.6em;padding-top:.2em;position:relative}#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-chunk-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-chunk-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-chunk-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-chunk-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-plugin-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-plugin-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-plugin-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-plugin-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-snippet-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-snippet-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-snippet-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-snippet-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-template-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-template-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-template-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-template-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-template-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-template-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-template-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-template-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,.display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,.display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,.display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,.display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,.display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,.display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,.display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,.display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before{content:"";font-size:inherit;position:absolute;transition:all .2s ease}#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-chunk-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-chunk-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-plugin-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-plugin-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-snippet-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-snippet-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-template-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-template-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-template-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-template-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,.display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,.display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,.display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,.display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before{background:#e4e4e4;border-radius:1.2em;height:1.6em;left:0;top:0;width:3em;z-index:10}#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-chunk-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-chunk-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-plugin-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-plugin-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-snippet-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-snippet-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-template-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-template-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-template-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-template-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,.display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,.display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,.display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,.display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after{background-color:#fff;border-radius:50%;height:1.3em;left:.1em;margin-top:-.65em;top:.8em;width:1.3em;z-index:11}#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-chunk-tabs .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-chunk-tabs .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:after,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-plugin-tabs .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-plugin-tabs .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:after,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:after,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-snippet-tabs .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-snippet-tabs .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:after,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-template-tabs .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-template-tabs .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-template-tabs .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-template-tabs .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:after,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:after,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:after,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:after,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:after,.display-switch .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:after,.display-switch .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:after,.display-switch .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:after,.display-switch .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:after{left:1.6em;top:.8em}#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-chunk-tabs .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-chunk-tabs .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:before,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-plugin-tabs .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-plugin-tabs .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:before,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-snippet-tabs .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-snippet-tabs .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:before,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-template-tabs .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-template-tabs .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-template-tabs .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-template-tabs .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:before,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:before,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:before,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:before,.display-switch .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:before,.display-switch .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:before,.display-switch .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:before,.display-switch .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:before{background-color:#6cb24a;border-color:#6cb24a}#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-chunk-tabs .x-fieldset legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-chunk-tabs .x-fieldset legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-chunk-tabs .x-form-check-wrap [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-chunk-tabs .x-form-check-wrap [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-plugin-tabs .x-fieldset legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-plugin-tabs .x-fieldset legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-plugin-tabs .x-form-check-wrap [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-plugin-tabs .x-form-check-wrap [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-snippet-tabs .x-fieldset legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-snippet-tabs .x-fieldset legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-snippet-tabs .x-form-check-wrap [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-snippet-tabs .x-form-check-wrap [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-template-tabs .x-fieldset legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-template-tabs .x-fieldset legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-template-tabs .x-form-check-wrap [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-template-tabs .x-form-check-wrap [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox].danger:checked+.x-form-cb-label:before,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-form-cb-label:before,.display-switch .x-fieldset legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,.display-switch .x-fieldset legend [type=checkbox].danger:checked+.x-form-cb-label:before,.display-switch .x-form-check-wrap [type=checkbox].danger:checked+.x-fieldset-header-text:before,.display-switch .x-form-check-wrap [type=checkbox].danger:checked+.x-form-cb-label:before{background-color:#cf1124;border-color:#cf1124}#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-chunk-tabs .x-fieldset legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-chunk-tabs .x-fieldset legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-chunk-tabs .x-form-check-wrap [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-chunk-tabs .x-form-check-wrap [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-plugin-tabs .x-fieldset legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-plugin-tabs .x-fieldset legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-plugin-tabs .x-form-check-wrap [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-plugin-tabs .x-form-check-wrap [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-snippet-tabs .x-fieldset legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-snippet-tabs .x-fieldset legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-snippet-tabs .x-form-check-wrap [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-snippet-tabs .x-form-check-wrap [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-template-tabs .x-fieldset legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-template-tabs .x-fieldset legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-template-tabs .x-form-check-wrap [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-template-tabs .x-form-check-wrap [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox].warning:checked+.x-form-cb-label:before,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-form-cb-label:before,.display-switch .x-fieldset legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,.display-switch .x-fieldset legend [type=checkbox].warning:checked+.x-form-cb-label:before,.display-switch .x-form-check-wrap [type=checkbox].warning:checked+.x-fieldset-header-text:before,.display-switch .x-form-check-wrap [type=checkbox].warning:checked+.x-form-cb-label:before{background-color:#f0b429;border-color:#f0b429}.switch-container{padding-top:1.6rem}.x-form-check-group,.x-form-radio-group{overflow:hidden;padding-bottom:.5em}.x-form-check-group .x-column .x-form-item:first-child,.x-form-radio-group .x-column .x-form-item:first-child{padding:4px 0 0}.x-form-check-group.aggregated-group,.x-form-radio-group.aggregated-group{padding-left:1em;padding-right:1em}.x-superboxselect{margin:0;outline:0;padding:0 5px 5px;position:relative;white-space:normal;width:auto!important}.ext-strict .x-toolbar .x-small-editor .x-superboxselect,.x-superboxselect{height:auto!important}.x-superboxselect ul{cursor:text;min-height:20px;overflow:visible;padding-right:61px;white-space:normal;width:auto!important}.x-toolbar .x-superboxselect ul{margin:-5px 0 0 -5px}.x-superboxselect ul li{margin:5px 5px 0 0;padding:0}.x-superboxselect ul li.x-superboxselect-item{cursor:default;font-size:12px;padding:4px 18px 4px 4px!important;position:relative}.x-superboxselect ul li.x-superboxselect-item.x-superboxselect-item-focus{background-color:#234368;box-shadow:0 0 0 1px #234368;color:#fff}.x-superboxselect ul li.x-superboxselect-item .x-superboxselect-item-close{border:0;color:inherit;cursor:pointer;display:inline-block;filter:alpha(opacity=60);height:100%;opacity:.6;outline:0;padding:0;position:absolute;right:0;top:0;transition:opacity .25s;width:16px}.x-superboxselect ul li.x-superboxselect-item .x-superboxselect-item-close:before{box-sizing:border-box;color:inherit;content:"\f00d";font-size:14px;margin-top:-7px;position:absolute;right:0;text-align:center;top:50%;vertical-align:middle;width:16px}.x-superboxselect ul li.x-superboxselect-item .x-superboxselect-item-close:focus,.x-superboxselect ul li.x-superboxselect-item .x-superboxselect-item-close:hover{filter:alpha(opacity=100);opacity:1}.x-superboxselect ul li.x-superboxselect-input{display:inline-block}.x-superboxselect ul li.x-superboxselect-input input{background:none;border:0;line-height:20px;outline:0}.x-superboxselect.x-superboxselect-stacked li{box-sizing:border-box;margin:5px 0 0;width:100%}.x-superboxselect .x-superboxselect-btns{height:100%;overflow:visible;position:absolute;right:0;top:0;width:61px}.x-superboxselect .x-superboxselect-btns .x-superboxselect-btn-expand{border-radius:0;right:31px}.x-superboxselect .x-superboxselect-btns .x-superboxselect-btn-clear{border-left:1px solid #e4e4e4}.x-superboxselect .x-superboxselect-btns .x-superboxselect-btn-clear:before{content:"\f00d"}.inline-form{border:0;padding:15px 15px 0}.inline-form label{color:#777;display:block;font-weight:700;margin-bottom:2px}.inline-form input[type=text],.inline-form textarea{background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:3px;position:relative;width:97%}.inline-form input[type=text]{font-size:13px;height:20px!important;padding:5px}.modx-tv-description{color:#515151;font-size:10px;line-height:1.2;margin-top:2px!important}.modx-tv-reload-btn{float:right;position:absolute;right:19px;z-index:10}.modx-tv-reload-btn div{z-index:10}.modx-tv-th label{cursor:pointer}.modx-tv-th .tv-description{color:#515151;font-size:11px;font-weight:400}.x-editor .x-form-check-wrap{background-color:#fff}.x-grid-editor .x-form-field-wrap{background:#f6f2f7 url(../images/modx-theme/form/combo-bck.png) repeat-x scroll 0 100%}.x-grid-editor .x-form-field-wrap input{background-color:initial!important}.x-grid-editor .x-form-field-wrap img{background-color:#fff;background-image:url(../images/modx-theme/form/trigger.png)}.x-form-grow-sizer,.x-form-invalid-msg{font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.x-form-invalid-msg{color:#cf1124;margin-top:2px;min-width:95%;position:relative}.x-form-invalid-msg:before{color:inherit;content:"\f071";left:3px;position:absolute;top:3px}.x-form-empty-field{color:#515151}.x-grid3 .x-small-editor .x-form-field-wrap,.x-grid3 .x-small-editor .x-form-text{font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;margin-top:7px;padding:2px 5px}.x-grid3 .x-small-editor .x-form-field-wrap .x-form-text,.x-grid3 .x-small-editor .x-form-text .x-form-text{margin:0;padding:0}.x-grid3 .x-small-editor .x-form-field-wrap{overflow:hidden}.x-combo-list{border:0;border-radius:3px;overflow:visible}.x-combo-list .x-combo-list-inner{background-color:#fff;border:1px solid #999;border-radius:3px;margin-left:-1px;width:100%!important}.x-combo-list .x-combo-list-item{border:0!important;border-bottom:1px solid #e4e4e4!important;color:#515151;min-height:18.2px;padding:6px 8px}.x-combo-list .x-combo-list-item:last-child{border-bottom-color:#fff!important}.x-combo-list .x-combo-list-item.x-combo-selected{background-color:#e4e4e4;border:0!important;border-bottom:1px solid #e4e4e4!important;color:#1b3451}.x-combo-list .x-combo-list-item.x-combo-list-item-grouped{padding:6px 14px}.x-combo-list .x-combo-list-item .x-combo-list-title{display:block;font-weight:700;margin:0 0 5px}.x-combo-list .x-combo-list-group{border-bottom:1px solid #e4e4e4;color:#515151;font-weight:700;padding:6px 8px}.x-combo-list .x-toolbar{border:0;border-radius:0 0 3px 3px;box-shadow:0 0 0 1px #234368;margin-top:-1px;position:relative}.x-combo-list .x-toolbar .x-toolbar-ct{padding:5px 0 15px}.x-combo-list .x-toolbar .x-toolbar-left table{margin:0 auto}.x-combo-list .x-toolbar .x-toolbar-cell{display:inline-block}.x-combo-list .x-toolbar .x-toolbar-cell .x-btn,.x-combo-list .x-toolbar .x-toolbar-cell .x-form-text{background:#0000;box-shadow:none;font-size:10px;line-height:16px;margin-right:2px;min-height:16px;padding:2px}.x-combo-list .x-toolbar .x-toolbar-cell .x-btn{padding:1px;transition:color .25s}.x-combo-list .x-toolbar .x-toolbar-cell .x-btn.x-btn-over,.x-combo-list .x-toolbar .x-toolbar-cell .x-btn:focus,.x-combo-list .x-toolbar .x-toolbar-cell .x-btn:hover{color:#234368}.x-combo-list .x-toolbar .x-toolbar-cell .x-btn.x-btn-click,.x-combo-list .x-toolbar .x-toolbar-cell .x-btn:active{color:#1b3451}.x-combo-list .x-toolbar .x-toolbar-cell .x-btn.x-item-disabled{color:#515151;opacity:.4}.x-combo-list .x-toolbar .x-toolbar-cell .x-btn button:before{left:0;line-height:20px;right:0;top:0}.x-combo-list .x-toolbar .x-toolbar-cell .x-form-text{background:#fbfbfb;width:23px}.x-combo-list .x-toolbar .xtb-text{font-size:10px;line-height:1;margin:0 auto;padding:0;text-align:center}.x-combo-list .x-toolbar .x-toolbar-cell:first-child .x-btn{margin-left:1px}.x-combo-list .x-toolbar .x-toolbar-cell+.x-toolbar-cell+.x-toolbar-cell .xtb-text{display:none;left:0;position:absolute;right:0;top:2px}.x-combo-list .x-toolbar .x-toolbar-cell+.x-toolbar-cell+.x-toolbar-cell+.x-toolbar-cell+.x-toolbar-cell .xtb-text{bottom:4px;display:inline-block;left:0;position:absolute;right:0;top:auto}.x-combo-list .x-toolbar .x-toolbar-cell+.x-toolbar-cell+.x-toolbar-cell+.x-toolbar-cell+.x-toolbar-cell+.x-toolbar-cell+.x-toolbar-cell+.x-toolbar-cell+.x-toolbar-cell .x-btn{margin-right:0}.x-combo-list .x-toolbar .x-toolbar-cell:last-child{opacity:0;transition:opacity .25s}.x-combo-list .x-toolbar .x-toolbar-cell:last-child .x-btn{bottom:2px;font-size:12px;line-height:1;margin:0;opacity:.4;padding:0;position:absolute;right:1px}.x-combo-list .x-toolbar .x-toolbar-cell:last-child .x-btn:hover{opacity:1}.x-combo-list .x-toolbar .x-toolbar-cell:last-child .x-btn button{height:16px;width:16px}.x-combo-list .x-toolbar .x-toolbar-cell:last-child .x-btn button:before{font-size:12px}.x-combo-list .x-toolbar:hover .x-toolbar-cell:last-child{opacity:1}.x-combo-list .x-resizable-handle-southeast{bottom:1px;right:3px}.x-combo-list.modx-superboxselect .x-combo-list-inner{margin-left:0}.x-combo-list-hd{background-image:url(../images/modx-theme/layout/panel-title-light-bg.gif);border-bottom-color:#bcbcbc;color:#464646}.x-combo-list-small{font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.x-date-mp,.x-date-picker{background-color:#fbfbfb}.x-date-mp .x-btn,.x-date-mp .x-date-mp-cancel,.x-date-mp .x-date-mp-ok,.x-date-picker .x-btn,.x-date-picker .x-date-mp-cancel,.x-date-picker .x-date-mp-ok{border:0;margin:0 0 0 7px;padding:5px 10px}.x-date-mp .x-btn:first-child,.x-date-mp .x-date-mp-cancel:first-child,.x-date-mp .x-date-mp-ok:first-child,.x-date-picker .x-btn:first-child,.x-date-picker .x-date-mp-cancel:first-child,.x-date-picker .x-date-mp-ok:first-child{margin:0}.x-date-mp .x-btn button,.x-date-mp .x-date-mp-cancel button,.x-date-mp .x-date-mp-ok button,.x-date-picker .x-btn button,.x-date-picker .x-date-mp-cancel button,.x-date-picker .x-date-mp-ok button{font-size:11px;font-style:normal;margin:0}.x-date-mp .x-date-mp-cancel,.x-date-mp .x-date-mp-ok,.x-date-picker .x-date-mp-cancel,.x-date-picker .x-date-mp-ok{height:16px}.x-date-middle{padding:5px 3px}.x-date-left a,.x-date-mp-ybtn a.x-date-mp-next,.x-date-mp-ybtn a.x-date-mp-prev,.x-date-right a{display:inline-block;filter:alpha(opacity=60);margin:0 auto;opacity:.6;position:relative;transition:opacity .25s}.x-date-left a:before,.x-date-mp-ybtn a.x-date-mp-next:before,.x-date-mp-ybtn a.x-date-mp-prev:before,.x-date-right a:before{box-sizing:border-box;color:#234368;content:"";font-size:18px;height:18px;left:0;position:absolute;text-align:center;top:0;vertical-align:middle;width:18px}.x-date-left a:hover,.x-date-mp-ybtn a.x-date-mp-next:hover,.x-date-mp-ybtn a.x-date-mp-prev:hover,.x-date-right a:hover{filter:alpha(opacity=100);opacity:1}.x-date-mp-ybtn a.x-date-mp-next:before,.x-date-right a:before{content:"\f0da";left:auto;right:0}.x-date-left a:before,.x-date-mp-ybtn a.x-date-mp-prev:before{content:"\f0d9"}.x-date-inner{margin:0 auto}.x-date-inner th{border-bottom-color:#e4e4e4;color:#515151;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-weight:700}.x-date-inner td,.x-date-mp td{background-color:#fff;border:0;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;padding:1px}.x-date-inner a,td.x-date-mp-month a,td.x-date-mp-year a{border-radius:3px;color:#999;font:inherit;font-weight:700}td.x-date-mp-month a,td.x-date-mp-year a{margin:0 3px}.x-date-inner .x-date-disabled a:hover,.x-date-inner .x-date-nextday a:hover,.x-date-inner .x-date-prevday a:hover,.x-date-inner a:hover,td.x-date-mp-month a:hover,td.x-date-mp-year a:hover{background-color:#dcdcdc;color:#515151}.x-date-inner .x-date-disabled a{background-color:#e4e4e4;color:#999}.x-date-inner .x-date-active{color:#000}.x-date-inner .x-date-today a{border-color:#234368}.x-date-inner span{font-style:normal}.x-date-inner .x-date-active span,.x-date-inner .x-date-selected span{font-weight:700}.x-date-inner .x-date-selected a,td.x-date-mp-sel a{background-color:#234368;border-color:#fff;color:#fff}.x-date-inner .x-date-nextday a,.x-date-inner .x-date-prevday a{color:#dcdcdc}.x-date-bottom,.x-date-mp-btns{border-top:1px solid #e4e4e4;padding:5px}.x-date-bottom td,.x-date-mp-btns td{background-color:initial;border-top:1px solid #e4e4e4}td.x-date-mp-sep{border-right:1px solid #e4e4e4}.x-date-mmenu{background-color:#eee!important}.x-date-mmenu .x-menu-item{color:#000;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.radio-version .x-form-check-wrap .x-form-cb-label{display:block}.radio-version .x-form-check-wrap .x-form-cb-label .changelog{float:right}.x-form-template-picker .x-form-template-picker-search{padding:0!important}.x-form-template-picker .x-form-template-picker-templates .x-form-radio-group{background-color:#fff;border:1px solid #e4e4e4;border-radius:3px;height:194px;overflow:auto}.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-category,.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-item{border-bottom:1px solid #e4e4e4}.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-category:last-child,.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-item:last-child{border-bottom:0}.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-category .x-form-check-wrap .x-form-cb-label,.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-item .x-form-check-wrap .x-form-cb-label{display:block}.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-category .x-form-check-wrap .x-form-cb-label:before,.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-item .x-form-check-wrap .x-form-cb-label:before{display:none}.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-category .x-form-check-wrap .x-form-radio:checked+.x-form-cb-label,.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-category .x-form-check-wrap:not(.x-item-disabled) .x-form-cb-label:hover,.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-item .x-form-check-wrap .x-form-radio:checked+.x-form-cb-label,.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-item .x-form-check-wrap:not(.x-item-disabled) .x-form-cb-label:hover{background-color:#e4e4e4;color:#1b3451}.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-item{padding:0!important}.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-item .x-form-cb-label{padding:10px 14px}.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-category{padding:0!important}.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-category .x-form-cb-label{font-weight:700!important;padding:10px 8px}.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-category .x-item-disabled{filter:alpha(opacity=100);opacity:1;-moz-opacity:1}.x-form-template-preview{background-color:#fff;background:url(../images/tp-no-preview.png) no-repeat 50%;border:1px solid #e4e4e4;border-radius:3px;height:236px;overflow:hidden}.x-form-template-preview .x-panel-body,.x-form-template-preview .x-panel-bwrap{height:100%;position:relative}.x-form-template-preview .x-form-template-preview-image{height:100%;-o-object-fit:cover;object-fit:cover}.x-form-template-preview .x-form-template-preview-desc{background-color:#000c;bottom:0;color:#fff;left:0;padding:10px 20px;position:absolute;right:0}#modx-tv-tabs{width:100%}.x-tab-panel-noborder{border:1px solid #e2e3de;margin:20px 0;overflow:visible}.x-tab-panel-noborder .x-tab-panel-body-noborder{background-color:#fff;border-radius:3px}.x-tab-panel-footer,.x-tab-panel-header{border:0;position:relative}.x-tab-panel-header ul.x-tab-strip{background-color:initial!important;border:0;margin:0;position:relative;top:1px}.x-tab-panel-footer-plain .x-tab-strip-spacer,.x-tab-panel-header-plain .x-tab-strip-spacer{border:none;height:0}.x-tab-panel .x-tab-panel{padding-top:18px}.x-tab-panel .x-tab-panel.vertical-tabs-panel{padding-top:0}.x-tab-panel .x-tab-panel .x-tab-strip-wrap .x-tab-strip{background-color:#fbfbfb!important}.x-tab-panel-header,.x-tab-strip{padding-left:0}.x-tab-panel-bwrap{border-radius:3px;overflow:visible}.x-tab-panel-bwrap .x-tab-panel-bwrap{box-shadow:none}ul.x-tab-strip li{background-color:initial;border-top-left-radius:3px;border-top-right-radius:3px;color:#53595f;cursor:pointer;font:14px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;line-height:2.2;margin-left:0;padding:0 12px;position:relative;z-index:1}html[dir=rtl] ul.x-tab-strip li{float:right}ul.x-tab-strip li:hover{background-color:#e4e4e4;color:#000}ul.x-tab-strip li.x-tab-strip-active{background-color:#fff;color:#234368;cursor:default}.vertical-tabs-header ul.x-tab-strip li.x-tab-strip-active{border-radius:0}ul.x-tab-strip li.x-tab-strip-active:hover{background-color:#fff}ul.x-tab-strip li.x-tab-edge{height:0;visibility:hidden}.x-tab-panel,.x-tab-panel-header,.x-tab-strip-wrap{border:none;overflow:visible}.x-tab-strip-wrap{margin:0;overflow:hidden;padding:2px 0 0}.x-tab-strip-closable{padding-right:15px!important}.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close{background-image:url(../images/modx-theme/tabs/tab-close.gif);right:2px}ul.x-tab-strip-top li:first-child{margin-left:0}ul.x-tab-strip-bottom{background-color:#f4f4f4;border-top-color:#dfdfdf}ul.x-tab-strip-bottom .x-tab-right{background-image:url(../images/modx-theme/tabs/tab-btm-inactive-right-bg.gif)}ul.x-tab-strip-bottom .x-tab-right .x-tab-right{background-image:url(../images/modx-theme/tabs/tab-btm-right-bg.gif)}ul.x-tab-strip-bottom .x-tab-right .x-tab-left{background-image:url(../images/modx-theme/tabs/tab-btm-left-bg.gif)}ul.x-tab-strip-bottom .x-tab-left{background-image:url(../images/modx-theme/tabs/tab-btm-inactive-left-bg.gif)}.x-tab-panel-body{background-color:#fff;border:0;overflow:visible}.x-tab-scroller-left,.x-tab-scroller-right{border:0}.x-tab-scroller-left:before,.x-tab-scroller-right:before{box-sizing:border-box;color:#383838;content:"";filter:alpha(opacity=100);font-size:28px;margin-top:-20px;opacity:1;position:absolute;right:0;text-align:center;top:50%;transition:opacity .25s;width:18px}.x-tab-scroller-left-over:before,.x-tab-scroller-right-over:before{color:#234368}.x-tab-scroller-left-disabled,.x-tab-scroller-right-disabled{cursor:default}.x-tab-scroller-left-disabled:before,.x-tab-scroller-right-disabled:before{color:#383838;filter:alpha(opacity=100);opacity:.4}.x-tab-scroller-left:before{content:"\f0d9"}.x-tab-scroller-right:before{content:"\f0da"}.x-tab-panel-bbar .x-toolbar,.x-tab-panel-tbar .x-toolbar{border-color:#dfdfdf}.x-tab-panel-body-noborder .x-panel-body-noheader:first-child{border-top:0}.x-tab-panel-bbar-noborder .x-toolbar{border-top-color:#0000}.x-tab-panel-tbar-noborder .x-toolbar{border-bottom-color:#0000}.vertical-tabs-panel{background-color:#fff;margin:0;overflow:hidden}.vertical-tabs-panel.wrapped{border:1px solid #e4e4e4}.vertical-tabs-panel .vertical-tabs-header{background:#fff!important;border-right:1px solid #e4e4e4!important;float:left;margin-bottom:-10000px;padding-bottom:10000px!important;width:168px!important}@media screen and (max-width:960px){.vertical-tabs-panel .vertical-tabs-header{width:80px!important}}.vertical-tabs-panel .vertical-tabs-header .x-tab-strip-wrap{background-color:initial;display:inline-block;line-height:0;margin:0;padding:0;width:auto!important}.vertical-tabs-panel .vertical-tabs-header .x-tab-strip-wrap ul.x-tab-strip{border:0;display:inline-block;top:0;width:auto}.vertical-tabs-panel .vertical-tabs-header .x-tab-strip-wrap ul.x-tab-strip>li{border-bottom:1px solid #e4e4e4;border-right:1px solid #e4e4e4;color:#515151;float:none;line-height:1;margin:0;overflow:hidden;padding:10px 15px;transition:background-color .25s,color .25s}@media screen and (max-width:960px){.vertical-tabs-panel .vertical-tabs-header .x-tab-strip-wrap ul.x-tab-strip>li{font-size:12px;padding:8px}}.vertical-tabs-panel .vertical-tabs-header .x-tab-strip-wrap ul.x-tab-strip>li:hover{background:#fff}.vertical-tabs-panel .vertical-tabs-header .x-tab-strip-wrap ul.x-tab-strip>li.x-tab-strip-active{background:#fff;border-color:#234368 #fff #234368 #234368;box-shadow:none;color:#234368;width:168px}@media screen and (max-width:960px){.vertical-tabs-panel .vertical-tabs-header .x-tab-strip-wrap ul.x-tab-strip>li.x-tab-strip-active{width:80px!important}}.vertical-tabs-panel .vertical-tabs-header .x-tab-strip-wrap ul.x-tab-strip>li.x-tab-edge{height:0;visibility:hidden}.vertical-tabs-panel .vertical-tabs-header .x-tab-strip-wrap ul.x-tab-strip>li.x-tab-edge .x-tab-strip-text{display:none}.vertical-tabs-panel .vertical-tabs-header .x-tab-strip-wrap ul.x-tab-strip>li .x-tab-strip-text{line-height:1.4;padding:2px 0;white-space:pre-wrap}.vertical-tabs-panel .vertical-tabs-header h4{background:#fff;border-bottom:1px solid #e4e4e4;color:#53595f;font-size:16px;padding:15px 0 15px 15px}.vertical-tabs-panel .vertical-tabs-header .x-tab-strip-spacer{display:none}.vertical-tabs-panel .x-tab-panel-bwrap{box-shadow:none}.vertical-tabs-panel .x-tab-panel-bwrap .x-tab-panel-body{border-top:0;width:auto!important}.vertical-tabs-panel .x-tab-panel-bwrap .vertical-tabs-body{border:0;padding:15px 20px 15px 15px}.tvs-wrapper.below-content{border-radius:3px;margin:1rem}.tvs-wrapper.below-content .vertical-tabs-panel{border-radius:3px}@media screen and (max-width:960px){.tvs-wrapper.below-content{margin:0}}.window-vtabs .x-panel-mr{padding-right:0}.window-vtabs .vertical-tabs-panel{margin:0;width:100%!important}#modx-split-wrapper .x-border-layout-ct{background:#0000}#modx-leftbar-tabs-xcollapsed{display:none!important}#modx-leftbar{background-color:#fff;min-width:288px;z-index:0}@media screen and (min-width:961px){#modx-leftbar{max-width:50%}}#modx-leftbar .x-toolbar{border:0;padding:0!important}#modx-header{background:#234368;height:100%;max-width:70px;position:absolute;z-index:2}#modx-navbar{display:flex;flex-direction:column;font-weight:700;font:normal 13px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;height:100%;padding:0 5px}#modx-navbar .icon{color:#fff;font-size:20px;line-height:20px;vertical-align:middle}#modx-navbar a,#modx-navbar li{background:#0000;margin:0;padding:0;position:relative;text-align:center;width:100%}#modx-navbar a{color:#fff;cursor:pointer;display:block;font-size:10px;line-height:12px;text-decoration:none}#modx-navbar a .description{font-size:9px;opacity:.7}#modx-navbar a .description,#modx-navbar a .icon,#modx-navbar a .label{display:block;width:100%}#modx-navbar li a:hover{opacity:.7}#modx-navbar #modx-user-menu a .description,#modx-navbar #modx-user-menu a .label{display:none}#modx-navbar #modx-user-menu a #user-username{align-self:center;max-width:7ch;overflow:hidden;padding-top:.25rem;text-overflow:ellipsis;white-space:nowrap}#modx-navbar #modx-leftbar-trigger a,#modx-navbar #modx-manager-search-icon a,#modx-navbar #modx-user-menu a{padding:12px 0}#modx-navbar #modx-topnav{list-style:none;margin:0;padding:0}#modx-navbar #modx-topnav>li{border-top:1px solid #ffffff1a}#modx-navbar #modx-topnav>li:not(#modx-home-dashboard):not(#modx-manager-search-icon):not(#modx-leftbar-trigger)>a{display:block;padding:12px 0;position:relative}#modx-navbar #modx-user-menu{margin-top:auto}#modx-navbar #modx-user-menu #user-avatar img{border-radius:20px;display:block;height:40px;margin:auto;width:40px}#modx-navbar #modx-user-menu #limenu-user a{display:flex;flex-direction:column;justify-content:center}#modx-navbar #modx-home-dashboard{border-radius:3px;height:40px;line-height:40px;padding:10px;width:40px}#modx-navbar #modx-site-info{font-size:10px}#modx-navbar #modx-site-info .full_appname,#modx-navbar #modx-site-info .site_name{color:#fff}#modx-navbar #modx-site-info>.info-item{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#modx-leftbar-trigger{transition:all .2s ease}#modx-leftbar-trigger .icon:before{content:"\f060"}#modx-leftbar-trigger.collapsed .icon:before{content:"\f061"!important}#modx-footer .modx-subnav,#modx-header .modx-subnav{background:#fff;border:1px solid #ffffff1a;border-radius:3px;box-shadow:0 0 15px 0 #0003;box-sizing:border-box;display:block;list-style:none;opacity:0;position:absolute;transition:all .15s ease;visibility:hidden}#modx-footer .modx-subnav li,#modx-header .modx-subnav li{background:#fff;border-radius:3px;display:block;margin:0;padding:0;position:relative}#modx-footer .modx-subnav li:not(:first-child),#modx-header .modx-subnav li:not(:first-child){border-top:1px solid #e4e4e4}#modx-footer .modx-subnav li:hover:after,#modx-header .modx-subnav li:hover:after{border-right-color:#e4e4e4}#modx-footer .modx-subnav li.sub:after,#modx-header .modx-subnav li.sub:after{color:#999;content:"\f0da";font-size:14px;margin-top:0;position:absolute;right:10px;top:50%;transform:translateY(-50%)}#modx-footer .modx-subnav li a,#modx-header .modx-subnav li a{background-color:#fff;border-radius:3px;color:#515151;cursor:pointer;display:block;font-size:13px;font-weight:700;line-height:1.5;margin:0;padding:8px 15px;text-align:left;text-decoration:none;text-shadow:none;width:270px}#modx-footer .modx-subnav li a .icon,#modx-header .modx-subnav li a .icon{display:inline-block;font-size:18px;opacity:.07;padding-left:5px}#modx-footer .modx-subnav li a span,#modx-header .modx-subnav li a span{color:#999;display:block;float:none;font-size:12px;font-weight:400;line-height:1.3;margin-top:6px;width:100%}#modx-footer .modx-subnav li a:hover,#modx-header .modx-subnav li a:hover{background:#e4e4e4;border-bottom-color:#e4e4e4;border-top-color:#e4e4e4;color:#53595f}#modx-footer .modx-subnav li a:hover .description,#modx-header .modx-subnav li a:hover .description{color:#707070}#modx-footer .modx-subnav.active,#modx-header .modx-subnav.active{opacity:1;visibility:visible}#modx-footer .modx-subnav .modx-subsubnav,#modx-header .modx-subnav .modx-subsubnav{background:#fff;border:1px solid #ffffff1a;border-radius:3px;box-shadow:0 0 15px 0 #0003;list-style:none;position:absolute}#modx-footer .modx-subnav .modx-subsubnav-arrow,#modx-header .modx-subnav .modx-subsubnav-arrow{border:8px solid #0000;border-right-color:#fff;content:" ";display:none;pointer-events:none;position:absolute;right:0;top:50%;transform:translateY(-50%)}#modx-footer .modx-subnav .modx-subsubnav.active+.modx-subsubnav-arrow,#modx-header .modx-subnav .modx-subsubnav.active+.modx-subsubnav-arrow{display:block}@media screen and (min-width:961px){#modx-footer .modx-subnav .modx-subsubnav,#modx-header .modx-subnav .modx-subsubnav{opacity:0;visibility:hidden}#modx-footer .modx-subnav .modx-subsubnav.active,#modx-header .modx-subnav .modx-subsubnav.active{opacity:1;visibility:visible}}#modx-footer .modx-subnav-arrow,#modx-header .modx-subnav-arrow{border:12px solid #0000;border-right-color:#fff;content:" ";margin-top:-6px;pointer-events:none;position:absolute;right:100%}#modx-footer #language .modx-subsubnav,#modx-header #language .modx-subsubnav{max-height:calc(100vh - 12px);overflow-x:hidden;overflow-y:auto}@media screen and (max-width:960px){#modx-header{height:auto!important;min-width:100%;position:relative}#modx-navbar{flex-direction:row;flex-wrap:wrap}#modx-navbar #modx-headnav{order:1;width:50%}#modx-navbar #modx-headnav a{line-height:normal!important}#modx-navbar #modx-headnav img{max-width:35px}#modx-navbar #modx-topnav{order:0;width:100%}#modx-navbar #modx-user-menu{flex-direction:row-reverse;flex-wrap:nowrap;margin-top:0;order:2;width:50%}#modx-navbar>ul{align-items:center;display:flex;flex-wrap:wrap;justify-content:center}#modx-navbar>ul>li{flex-basis:50px}#modx-navbar #modx-site-info{display:none}#modx-navbar #modx-home-dashboard{margin:0;padding:5px}#modx-leftbar-trigger .icon{padding:3px 4px}#modx-leftbar-trigger .icon:before{content:"\f062"}#modx-leftbar-trigger.collapsed .icon:before{content:"\f063"!important}#modx-footer .modx-subnav,#modx-header .modx-subnav{min-width:300px}#modx-footer .modx-subnav .description,#modx-header .modx-subnav .description{display:none}#modx-footer .modx-subnav li,#modx-header .modx-subnav li{border-radius:0}#modx-footer .modx-subnav li.sub:after,#modx-header .modx-subnav li.sub:after{display:none}#modx-footer .modx-subnav li a,#modx-header .modx-subnav li a{white-space:nowrap;width:auto}#modx-footer .modx-subnav .modx-subsubnav,#modx-header .modx-subnav .modx-subsubnav{box-shadow:none;display:block;left:auto;max-height:none!important;overflow-y:initial!important;position:static}#modx-footer .modx-subnav .modx-subsubnav li>a,#modx-header .modx-subnav .modx-subsubnav li>a{margin-left:1rem}#modx-footer .modx-subnav-arrow,#modx-header .modx-subnav-arrow{display:none}#modx-footer .modx-subnav,#modx-header .modx-subnav{max-height:calc(100vh - 109px);overflow-x:hidden;overflow-y:auto}}@media (max-height:520px){#modx-footer .modx-subnav .description,#modx-header .modx-subnav .description{display:none}}#modx-manager-search{background:#fff;border-radius:3px 3px 0 0;height:38px;min-width:100px;padding:10px 10px 5px}#modx-manager-search .x-form-text{background:none}#modx-manager-search .x-form-field-wrap{background-image:none;color:#565353;font-size:12px;outline:none!important}#modx-manager-search .x-form-field-wrap .x-form-text{color:#515151;font-weight:400;letter-spacing:0;text-shadow:none}#modx-manager-search .x-form-field-wrap .x-form-empty-field{color:#6a747a}#modx-manager-search .x-form-field-wrap .x-form-trigger{display:none}.modx-manager-search-results{background:#e4e4e4;border:1px solid #e4e4e4;border-radius:0 0 3px 3px;box-shadow:0 4px 10px 0 #0003;box-sizing:border-box;height:auto!important;position:relative;width:402px!important}.modx-manager-search-results .loading-indicator{background:none;color:#515151;font-size:14px;margin:10px 0;text-align:center}.modx-manager-search-results .loading-indicator:before{content:"\f110";margin-right:5px}.modx-manager-search-results .x-combo-list-inner{background:#fff;border:0;margin:0;overflow:auto;width:100%!important}@media screen and (max-width:960px){.modx-manager-search-results .x-combo-list-inner{height:auto!important;line-height:4em}.modx-manager-search-results .x-combo-list-inner .section>*{padding-bottom:.5em;padding-top:.5em}}.modx-manager-search-results .section{border-left:1px solid #ededed;font-size:12px;line-height:12px;margin-left:100px;position:relative;width:auto}.modx-manager-search-results .x-combo-list-item,.modx-manager-search-results h3{color:#515151;line-height:18px;margin:0;padding:4px 6px}.modx-manager-search-results h3{color:#53595f;font-size:11px;font-weight:400;left:-108px;line-height:11px;position:absolute;text-align:right;top:0;width:95px}.modx-manager-search-results a{color:inherit;cursor:pointer;display:inline-block;padding-left:20px;position:relative;text-decoration:none}.modx-manager-search-results i{color:#234368;left:0;position:absolute;top:4px}.modx-manager-search-results em{font-style:normal;opacity:.7}.modx-manager-search-results .x-combo-list-item{overflow:visible;white-space:normal}.modx-manager-search-results .x-combo-list-item a{display:block}.modx-manager-search-results .x-combo-list-item.x-combo-selected,.modx-manager-search-results .x-combo-list-item:hover{background-color:#e4e4e4;border:0;margin-left:0;z-index:10}.modx-manager-search-results .x-combo-list-item.x-combo-selected h3,.modx-manager-search-results .x-combo-list-item:hover h3{left:0}.modx-manager-search-results .x-combo-list-item.x-combo-selected p,.modx-manager-search-results .x-combo-list-item:hover p{border-left-color:#0000}.modx-manager-search-results .x-combo-list-item.x-combo-selected a,.modx-manager-search-results .x-combo-list-item:hover a{color:#515151}.modx-manager-search-results .icon-user{background-image:none!important}.breadcrumbs .panel-desc{margin-top:0}.crumb_wrapper{background:#fbfbfb;border-bottom:1px solid #e4e4e4;border-top:1px solid #e4e4e4;margin-top:15px}.crumb_wrapper .crumbs{height:34px;overflow:hidden}.crumb_wrapper .crumbs li{color:#53595f;float:left;font-size:12px;font-weight:400;line-height:12px;padding:0 0 0 20px;position:relative;z-index:1}.crumb_wrapper .crumbs li.first{padding:0}.crumb_wrapper .crumbs li.first:before{content:"\f015";display:inline-block;font-size:20px;left:0;line-height:34px;position:absolute;text-align:center;text-indent:0;top:0;z-index:2}#packages-breadcrumbs .crumb_wrapper .crumbs li.first:before{content:"\f1b2"}.crumb_wrapper .crumbs li.first:hover:before{color:#fff}.crumb_wrapper .crumbs li.first:hover{background-color:#515151}.crumb_wrapper .crumbs li.first .root{background-color:initial;box-sizing:initial;display:inline-block;line-height:12px;margin:0;padding:12px;text-indent:-999em;width:35px;z-index:3}.crumb_wrapper .crumbs li.first .root:before{display:none}.crumb_wrapper .crumbs li.first .root:hover{background-color:initial}.crumb_wrapper .crumbs li:hover button,.crumb_wrapper .crumbs li:hover span,.crumb_wrapper .crumbs li:hover span:after{background-color:#515151;color:#fff}.crumb_wrapper .crumbs li:hover button:after,.crumb_wrapper .crumbs li:hover span:after{border-color:#fbfbfb #fbfbfb #515151 #515151;border-style:solid;border-width:1px}.crumb_wrapper .crumbs li:hover button:before,.crumb_wrapper .crumbs li:hover span:before{background-color:#515151}.crumb_wrapper .crumbs li:hover+li button:before,.crumb_wrapper .crumbs li:hover+li span:before{border-left-color:#515151}.crumb_wrapper .crumbs li button{background-color:initial;border:0;color:#53595f;cursor:pointer;font:normal 12px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-weight:700;line-height:1;text-decoration:none}.crumb_wrapper .crumbs li span{background-color:#fbfbfb}.crumb_wrapper .crumbs li button,.crumb_wrapper .crumbs li span{display:inline-block;margin:0 0 0 1px;padding:11px 13px 11px 15px;position:relative}.crumb_wrapper .crumbs li button:before,.crumb_wrapper .crumbs li span:before{background-color:initial;border-bottom:50px solid #0000;border-left:30px solid #fbfbfb;border-top:50px solid #0000;content:"";display:inline-block;height:0;left:-33px;margin-top:-50px;padding-right:3px;position:absolute;top:50%;transform:scale(.99999);width:0;z-index:-1}.crumb_wrapper .crumbs li button:after,.crumb_wrapper .crumbs li span:after{background-color:#fbfbfb;border:1px solid #dcdcdc;border-bottom:0;border-left:0;border-radius:3px;content:"";display:inline-block;height:34px;position:absolute;right:-22px;top:0;transform:scaleX(.6) rotate(45deg);width:34px;z-index:-1}.x-toolbar{background-color:#f7f7f7;background-image:none;border-color:#dfdfdf}.x-toolbar .x-toolbar-cell label,.x-toolbar .xtb-text{margin:0 5px 0 7px;padding:0}.x-toolbar .x-item-disabled{filter:alpha(opacity=60);opacity:.6}.x-toolbar td.x-toolbar-cell:first-of-type .xtb-text{margin-left:0}.x-toolbar div,.x-toolbar input,.x-toolbar label,.x-toolbar select,.x-toolbar span,.x-toolbar td{font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;line-height:0}.x-toolbar .x-btn-group-header{line-height:1}.x-toolbar em.x-btn-split-bottom{background-image:url(../images/modx-theme/button/s-arrow-b-noline.gif)}.x-toolbar .x-btn-click em.x-btn-split-bottom,.x-toolbar .x-btn-menu-active em.x-btn-split-bottom,.x-toolbar .x-btn-over em.x-btn-split-bottom,.x-toolbar .x-btn-pressed em.x-btn-split-bottom{background-image:url(../images/modx-theme/button/s-arrow-bo.gif)}.ext-ie .x-toolbar-cell .x-form-field-wrap{height:30px}.x-tbar-page-first{background-image:url(../images/modx-theme/grid/page-first.png)!important}.x-tbar-loading{background-image:url(../images/modx-theme/grid/refresh.png)!important}.x-tbar-page-last{background:none!important;position:relative}.x-tbar-page-last:before{content:"\f04e";left:1px;right:auto;top:1px}.x-tbar-page-next{background:none!important;position:relative}.x-tbar-page-next:before{content:"\f0da";font-size:18px;left:1px;line-height:110%;right:auto}.x-tbar-page-prev{background:none!important;position:relative}.x-tbar-page-prev:before{content:"\f0d9";font-size:18px;left:auto;line-height:110%;right:1px}.x-tbar-loading{background:none!important;position:relative}.x-tbar-loading:before{bottom:auto;content:"\f01e";top:1px}.x-tbar-page-first{background:none!important;position:relative}.x-tbar-page-first:before{content:"\f04a";left:auto;right:1px;top:1px}.x-paging-info{color:#444}.x-toolbar-more-icon{background-image:url(../images/modx-theme/toolbar/more.gif)!important}.x-panel-bbar{padding-top:10px}.modx-browser-rte-buttons .x-panel-bbar{background-color:#fff;border-top:1px solid #fff;padding:5px}.modx-browser-rte-buttons .x-panel-bbar .x-toolbar-layout-ct{width:auto!important}.x-panel-bbar .x-toolbar{background-color:initial;border:0;overflow:hidden;padding:2px 0}.x-panel-bbar .x-toolbar .x-form-text{padding:5px 10px}.x-panel-bbar .x-toolbar .x-form-text.x-tbar-page-number,.x-panel-bbar .x-toolbar .x-form-text.x-tbar-page-size{width:32px}.x-panel-bbar .x-toolbar .x-form-text.x-tbar-page-number{margin-right:3px}.x-panel-bbar .x-toolbar .x-btn{margin-right:10px;padding:8px 13px}.modx-browser-rte .x-panel-bbar .x-toolbar .x-btn{margin-right:0;padding:10px 15px}.x-panel-bbar .x-toolbar .xtb-text{margin:0 3px 0 0}.x-panel-tbar{overflow:visible;padding-bottom:4px}.x-panel-tbar .x-toolbar{border:0;overflow:visible;padding:5px 0}.x-panel-tbar .x-toolbar td{vertical-align:bottom}.x-panel-tbar .x-toolbar input.filter-query{bottom:-1px;position:relative}.x-panel-mc .x-panel-tbar .x-toolbar{background-image:none;border:0;padding:15px 0 7px}.x-panel-tbar-noheader .x-toolbar{background-color:initial;background-image:none;border:0;padding:5px 0}.x-toolbar div,.x-toolbar input,.x-toolbar label,.x-toolbar select,.x-toolbar span,.x-toolbar td{border-radius:3px}.x-html-editor-tb .x-btn-text{background-image:url(../images/modx-theme/editor/tb-sprite.gif)}.x-panel-noborder .x-panel-tbar-noborder .x-toolbar{background-color:initial;border-bottom-color:#0000}.x-panel-noborder .x-panel-bbar-noborder .x-toolbar{border-top-color:#0000}#modx-leftbar .x-tab-panel-noborder{margin:0 8px}#modx-leftbar .x-tab-panel-bwrap{border-radius:0 0 3px 3px;position:relative;z-index:1}#modx-leftbar .x-tab-panel-bwrap .x-tab-panel-body-noborder{background:#f1f1f1;border-radius:0 0 3px 3px}@media screen and (max-width:960px){#modx-leftbar #modx-leftbar-tabpanel{margin:0 auto;padding:.5em;width:auto!important}#modx-leftbar{box-shadow:none;height:auto!important;left:auto!important;margin:0 auto 10px;position:relative!important;top:auto!important;width:100%!important}#modx-leftbar #modx-leftbar-header{display:none}#modx-leftbar .x-plain-body{height:auto!important;width:100%!important}}#modx-leftbar .x-panel-tbar{padding:0}#modx-leftbar .x-toolbar{padding:4px 5px 2px 0}#modx-leftbar .x-tree-root-ct{padding:6px}#modx-leftbar .x-tree .x-panel-body{background:#fff;border-radius:0}#modx-tree-usergroup .x-toolbar-left-row{display:flex;flex-wrap:wrap}#modx-resource-tree-tbar .x-toolbar-left .x-btn .tree-new-resource,#modx-tree-element .x-toolbar-left .x-btn .tree-new-template{margin-left:16px}#modx-split-wrapper #modx-leftbar-tabs-xcollapsed,#modx-split-wrapper .x-layout-split{margin-left:-70px}.x-layout-split{overflow:visible;width:8px;z-index:2}.x-layout-split:hover{background:#999}#modx-leftbar-tabs-xcollapsed .x-layout-mini{left:0}#modx-leftbar-tabs-xcollapsed .x-layout-mini:after{border-left:5px solid #383838;border-right:0}@media screen and (max-width:960px){#modx-leftbar-tabs-xcollapsed .x-layout-mini:after{border:none}}#modx-leftbar-tabs-xcollapsed .x-layout-mini:hover:after{border-left-color:#234368}.modx-tree{padding:0}#modx-file-tree .modx-tree:first-child{padding-top:4px}.x-tree-arrows .x-tree-elbow-end-minus,.x-tree-arrows .x-tree-elbow-end-plus,.x-tree-arrows .x-tree-elbow-minus,.x-tree-arrows .x-tree-elbow-plus{background:none}.x-tree-arrows .x-tree-elbow-end-minus:hover,.x-tree-arrows .x-tree-elbow-end-plus:hover,.x-tree-arrows .x-tree-elbow-minus:hover,.x-tree-arrows .x-tree-elbow-plus:hover{background:#d9d9d9;border-radius:50%}.x-tree-arrows .x-tree-elbow-end-minus:before,.x-tree-arrows .x-tree-elbow-end-plus:before,.x-tree-arrows .x-tree-elbow-minus:before,.x-tree-arrows .x-tree-elbow-plus:before{background:#0000 0 0;content:"\f0da";display:inline-block;margin:0;padding-left:4px;padding-right:4px;text-align:center;width:10px}.x-tree-arrows .x-tree-elbow-end-minus:before,.x-tree-arrows .x-tree-elbow-minus:before{content:"\f0d7"}.x-tree-node-el{background-position:5px;background-repeat:no-repeat;color:#383838;font:normal 14px/2.25 -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;padding:0 8px}.x-tree-node-el.is_folder{background:#0000}.x-tree-node-el .x-btn{box-shadow:none}.x-tree-node-el .icon{display:inline-block;font-size:1.15em;line-height:.75em;vertical-align:-15%;width:1em}.x-tree-node-el a span{padding-left:7px}.x-tree-node-el a span span{padding-left:0}i.icon,i.icon-large{font-style:normal}.deleted i.icon-large.fa-address-book:before,.deleted i.icon-large.fa-address-card:before,.deleted i.icon-large.fa-angry:before,.deleted i.icon-large.fa-arrow-alt-circle-down:before,.deleted i.icon-large.fa-arrow-alt-circle-left:before,.deleted i.icon-large.fa-arrow-alt-circle-right:before,.deleted i.icon-large.fa-arrow-alt-circle-up:before,.deleted i.icon-large.fa-bell-slash:before,.deleted i.icon-large.fa-bell:before,.deleted i.icon-large.fa-bookmark:before,.deleted i.icon-large.fa-building:before,.deleted i.icon-large.fa-calendar-alt:before,.deleted i.icon-large.fa-calendar-check:before,.deleted i.icon-large.fa-calendar-minus:before,.deleted i.icon-large.fa-calendar-plus:before,.deleted i.icon-large.fa-calendar-times:before,.deleted i.icon-large.fa-calendar:before,.deleted i.icon-large.fa-caret-square-down:before,.deleted i.icon-large.fa-caret-square-left:before,.deleted i.icon-large.fa-caret-square-right:before,.deleted i.icon-large.fa-caret-square-up:before,.deleted i.icon-large.fa-chart-bar:before,.deleted i.icon-large.fa-check-circle:before,.deleted i.icon-large.fa-check-square:before,.deleted i.icon-large.fa-circle:before,.deleted i.icon-large.fa-clipboard:before,.deleted i.icon-large.fa-clock:before,.deleted i.icon-large.fa-clone:before,.deleted i.icon-large.fa-closed-captioning:before,.deleted i.icon-large.fa-comment-alt:before,.deleted i.icon-large.fa-comment-dots:before,.deleted i.icon-large.fa-comment:before,.deleted i.icon-large.fa-comments:before,.deleted i.icon-large.fa-compass:before,.deleted i.icon-large.fa-copy:before,.deleted i.icon-large.fa-copyright:before,.deleted i.icon-large.fa-credit-card:before,.deleted i.icon-large.fa-dizzy:before,.deleted i.icon-large.fa-dot-circle:before,.deleted i.icon-large.fa-edit:before,.deleted i.icon-large.fa-envelope-open:before,.deleted i.icon-large.fa-envelope:before,.deleted i.icon-large.fa-eye-slash:before,.deleted i.icon-large.fa-eye:before,.deleted i.icon-large.fa-file-alt:before,.deleted i.icon-large.fa-file-archive:before,.deleted i.icon-large.fa-file-audio:before,.deleted i.icon-large.fa-file-code:before,.deleted i.icon-large.fa-file-excel:before,.deleted i.icon-large.fa-file-image:before,.deleted i.icon-large.fa-file-pdf:before,.deleted i.icon-large.fa-file-powerpoint:before,.deleted i.icon-large.fa-file-video:before,.deleted i.icon-large.fa-file-word:before,.deleted i.icon-large.fa-file:before,.deleted i.icon-large.fa-flag:before,.deleted i.icon-large.fa-flushed:before,.deleted i.icon-large.fa-folder-open:before,.deleted i.icon-large.fa-folder:before,.deleted i.icon-large.fa-frown-open:before,.deleted i.icon-large.fa-frown:before,.deleted i.icon-large.fa-futbol:before,.deleted i.icon-large.fa-gem:before,.deleted i.icon-large.fa-grimace:before,.deleted i.icon-large.fa-grin-alt:before,.deleted i.icon-large.fa-grin-beam-sweat:before,.deleted i.icon-large.fa-grin-beam:before,.deleted i.icon-large.fa-grin-hearts:before,.deleted i.icon-large.fa-grin-squint-tears:before,.deleted i.icon-large.fa-grin-squint:before,.deleted i.icon-large.fa-grin-stars:before,.deleted i.icon-large.fa-grin-tears:before,.deleted i.icon-large.fa-grin-tongue-squint:before,.deleted i.icon-large.fa-grin-tongue-wink:before,.deleted i.icon-large.fa-grin-tongue:before,.deleted i.icon-large.fa-grin-wink:before,.deleted i.icon-large.fa-grin:before,.deleted i.icon-large.fa-hand-lizard:before,.deleted i.icon-large.fa-hand-paper:before,.deleted i.icon-large.fa-hand-peace:before,.deleted i.icon-large.fa-hand-point-down:before,.deleted i.icon-large.fa-hand-point-left:before,.deleted i.icon-large.fa-hand-point-right:before,.deleted i.icon-large.fa-hand-point-up:before,.deleted i.icon-large.fa-hand-pointer:before,.deleted i.icon-large.fa-hand-rock:before,.deleted i.icon-large.fa-hand-scissors:before,.deleted i.icon-large.fa-hand-spock:before,.deleted i.icon-large.fa-handshake:before,.deleted i.icon-large.fa-hdd:before,.deleted i.icon-large.fa-heart:before,.deleted i.icon-large.fa-hospital:before,.deleted i.icon-large.fa-hourglass:before,.deleted i.icon-large.fa-id-badge:before,.deleted i.icon-large.fa-id-card:before,.deleted i.icon-large.fa-image:before,.deleted i.icon-large.fa-images:before,.deleted i.icon-large.fa-keyboard:before,.deleted i.icon-large.fa-kiss-beam:before,.deleted i.icon-large.fa-kiss-wink-heart:before,.deleted i.icon-large.fa-kiss:before,.deleted i.icon-large.fa-laugh-beam:before,.deleted i.icon-large.fa-laugh-squint:before,.deleted i.icon-large.fa-laugh-wink:before,.deleted i.icon-large.fa-laugh:before,.deleted i.icon-large.fa-lemon:before,.deleted i.icon-large.fa-life-ring:before,.deleted i.icon-large.fa-lightbulb:before,.deleted i.icon-large.fa-list-alt:before,.deleted i.icon-large.fa-map:before,.deleted i.icon-large.fa-meh-blank:before,.deleted i.icon-large.fa-meh-rolling-eyes:before,.deleted i.icon-large.fa-meh:before,.deleted i.icon-large.fa-minus-square:before,.deleted i.icon-large.fa-money-bill-alt:before,.deleted i.icon-large.fa-moon:before,.deleted i.icon-large.fa-newspaper:before,.deleted i.icon-large.fa-object-group:before,.deleted i.icon-large.fa-object-ungroup:before,.deleted i.icon-large.fa-paper-plane:before,.deleted i.icon-large.fa-pause-circle:before,.deleted i.icon-large.fa-play-circle:before,.deleted i.icon-large.fa-plus-square:before,.deleted i.icon-large.fa-question-circle:before,.deleted i.icon-large.fa-registered:before,.deleted i.icon-large.fa-sad-cry:before,.deleted i.icon-large.fa-sad-tear:before,.deleted i.icon-large.fa-save:before,.deleted i.icon-large.fa-share-square:before,.deleted i.icon-large.fa-smile-beam:before,.deleted i.icon-large.fa-smile-wink:before,.deleted i.icon-large.fa-smile:before,.deleted i.icon-large.fa-snowflake:before,.deleted i.icon-large.fa-square:before,.deleted i.icon-large.fa-star-half:before,.deleted i.icon-large.fa-star:before,.deleted i.icon-large.fa-sticky-note:before,.deleted i.icon-large.fa-stop-circle:before,.deleted i.icon-large.fa-sun:before,.deleted i.icon-large.fa-surprise:before,.deleted i.icon-large.fa-thumbs-down:before,.deleted i.icon-large.fa-thumbs-up:before,.deleted i.icon-large.fa-times-circle:before,.deleted i.icon-large.fa-tired:before,.deleted i.icon-large.fa-trash-alt:before,.deleted i.icon-large.fa-user-circle:before,.deleted i.icon-large.fa-user:before,.deleted i.icon-large.fa-window-close:before,.deleted i.icon-large.fa-window-maximize:before,.deleted i.icon-large.fa-window-minimize:before,.deleted i.icon-large.fa-window-restore:before,.deleted i.icon-large.icon-address-book:before,.deleted i.icon-large.icon-address-card:before,.deleted i.icon-large.icon-angry:before,.deleted i.icon-large.icon-arrow-alt-circle-down:before,.deleted i.icon-large.icon-arrow-alt-circle-left:before,.deleted i.icon-large.icon-arrow-alt-circle-right:before,.deleted i.icon-large.icon-arrow-alt-circle-up:before,.deleted i.icon-large.icon-bell-slash:before,.deleted i.icon-large.icon-bell:before,.deleted i.icon-large.icon-bookmark:before,.deleted i.icon-large.icon-building:before,.deleted i.icon-large.icon-calendar-alt:before,.deleted i.icon-large.icon-calendar-check:before,.deleted i.icon-large.icon-calendar-minus:before,.deleted i.icon-large.icon-calendar-plus:before,.deleted i.icon-large.icon-calendar-times:before,.deleted i.icon-large.icon-calendar:before,.deleted i.icon-large.icon-caret-square-down:before,.deleted i.icon-large.icon-caret-square-left:before,.deleted i.icon-large.icon-caret-square-right:before,.deleted i.icon-large.icon-caret-square-up:before,.deleted i.icon-large.icon-chart-bar:before,.deleted i.icon-large.icon-check-circle:before,.deleted i.icon-large.icon-check-square:before,.deleted i.icon-large.icon-circle:before,.deleted i.icon-large.icon-clipboard:before,.deleted i.icon-large.icon-clock:before,.deleted i.icon-large.icon-clone:before,.deleted i.icon-large.icon-closed-captioning:before,.deleted i.icon-large.icon-comment-alt:before,.deleted i.icon-large.icon-comment-dots:before,.deleted i.icon-large.icon-comment:before,.deleted i.icon-large.icon-comments:before,.deleted i.icon-large.icon-compass:before,.deleted i.icon-large.icon-copy:before,.deleted i.icon-large.icon-copyright:before,.deleted i.icon-large.icon-credit-card:before,.deleted i.icon-large.icon-dizzy:before,.deleted i.icon-large.icon-dot-circle:before,.deleted i.icon-large.icon-edit:before,.deleted i.icon-large.icon-envelope-open:before,.deleted i.icon-large.icon-envelope:before,.deleted i.icon-large.icon-eye-slash:before,.deleted i.icon-large.icon-eye:before,.deleted i.icon-large.icon-file-alt:before,.deleted i.icon-large.icon-file-archive:before,.deleted i.icon-large.icon-file-audio:before,.deleted i.icon-large.icon-file-code:before,.deleted i.icon-large.icon-file-excel:before,.deleted i.icon-large.icon-file-image:before,.deleted i.icon-large.icon-file-pdf:before,.deleted i.icon-large.icon-file-powerpoint:before,.deleted i.icon-large.icon-file-video:before,.deleted i.icon-large.icon-file-word:before,.deleted i.icon-large.icon-file:before,.deleted i.icon-large.icon-flag:before,.deleted i.icon-large.icon-flushed:before,.deleted i.icon-large.icon-folder-open:before,.deleted i.icon-large.icon-folder:before,.deleted i.icon-large.icon-frown-open:before,.deleted i.icon-large.icon-frown:before,.deleted i.icon-large.icon-futbol:before,.deleted i.icon-large.icon-gem:before,.deleted i.icon-large.icon-grimace:before,.deleted i.icon-large.icon-grin-alt:before,.deleted i.icon-large.icon-grin-beam-sweat:before,.deleted i.icon-large.icon-grin-beam:before,.deleted i.icon-large.icon-grin-hearts:before,.deleted i.icon-large.icon-grin-squint-tears:before,.deleted i.icon-large.icon-grin-squint:before,.deleted i.icon-large.icon-grin-stars:before,.deleted i.icon-large.icon-grin-tears:before,.deleted i.icon-large.icon-grin-tongue-squint:before,.deleted i.icon-large.icon-grin-tongue-wink:before,.deleted i.icon-large.icon-grin-tongue:before,.deleted i.icon-large.icon-grin-wink:before,.deleted i.icon-large.icon-grin:before,.deleted i.icon-large.icon-hand-lizard:before,.deleted i.icon-large.icon-hand-paper:before,.deleted i.icon-large.icon-hand-peace:before,.deleted i.icon-large.icon-hand-point-down:before,.deleted i.icon-large.icon-hand-point-left:before,.deleted i.icon-large.icon-hand-point-right:before,.deleted i.icon-large.icon-hand-point-up:before,.deleted i.icon-large.icon-hand-pointer:before,.deleted i.icon-large.icon-hand-rock:before,.deleted i.icon-large.icon-hand-scissors:before,.deleted i.icon-large.icon-hand-spock:before,.deleted i.icon-large.icon-handshake:before,.deleted i.icon-large.icon-hdd:before,.deleted i.icon-large.icon-heart:before,.deleted i.icon-large.icon-hospital:before,.deleted i.icon-large.icon-hourglass:before,.deleted i.icon-large.icon-id-badge:before,.deleted i.icon-large.icon-id-card:before,.deleted i.icon-large.icon-image:before,.deleted i.icon-large.icon-images:before,.deleted i.icon-large.icon-keyboard:before,.deleted i.icon-large.icon-kiss-beam:before,.deleted i.icon-large.icon-kiss-wink-heart:before,.deleted i.icon-large.icon-kiss:before,.deleted i.icon-large.icon-laugh-beam:before,.deleted i.icon-large.icon-laugh-squint:before,.deleted i.icon-large.icon-laugh-wink:before,.deleted i.icon-large.icon-laugh:before,.deleted i.icon-large.icon-lemon:before,.deleted i.icon-large.icon-life-ring:before,.deleted i.icon-large.icon-lightbulb:before,.deleted i.icon-large.icon-list-alt:before,.deleted i.icon-large.icon-map:before,.deleted i.icon-large.icon-meh-blank:before,.deleted i.icon-large.icon-meh-rolling-eyes:before,.deleted i.icon-large.icon-meh:before,.deleted i.icon-large.icon-minus-square:before,.deleted i.icon-large.icon-money-bill-alt:before,.deleted i.icon-large.icon-moon:before,.deleted i.icon-large.icon-newspaper:before,.deleted i.icon-large.icon-object-group:before,.deleted i.icon-large.icon-object-ungroup:before,.deleted i.icon-large.icon-paper-plane:before,.deleted i.icon-large.icon-pause-circle:before,.deleted i.icon-large.icon-play-circle:before,.deleted i.icon-large.icon-plus-square:before,.deleted i.icon-large.icon-question-circle:before,.deleted i.icon-large.icon-registered:before,.deleted i.icon-large.icon-sad-cry:before,.deleted i.icon-large.icon-sad-tear:before,.deleted i.icon-large.icon-save:before,.deleted i.icon-large.icon-share-square:before,.deleted i.icon-large.icon-smile-beam:before,.deleted i.icon-large.icon-smile-wink:before,.deleted i.icon-large.icon-smile:before,.deleted i.icon-large.icon-snowflake:before,.deleted i.icon-large.icon-square:before,.deleted i.icon-large.icon-star-half:before,.deleted i.icon-large.icon-star:before,.deleted i.icon-large.icon-sticky-note:before,.deleted i.icon-large.icon-stop-circle:before,.deleted i.icon-large.icon-sun:before,.deleted i.icon-large.icon-surprise:before,.deleted i.icon-large.icon-thumbs-down:before,.deleted i.icon-large.icon-thumbs-up:before,.deleted i.icon-large.icon-times-circle:before,.deleted i.icon-large.icon-tired:before,.deleted i.icon-large.icon-trash-alt:before,.deleted i.icon-large.icon-user-circle:before,.deleted i.icon-large.icon-user:before,.deleted i.icon-large.icon-window-close:before,.deleted i.icon-large.icon-window-maximize:before,.deleted i.icon-large.icon-window-minimize:before,.deleted i.icon-large.icon-window-restore:before,.deleted i.icon.fa-address-book:before,.deleted i.icon.fa-address-card:before,.deleted i.icon.fa-angry:before,.deleted i.icon.fa-arrow-alt-circle-down:before,.deleted i.icon.fa-arrow-alt-circle-left:before,.deleted i.icon.fa-arrow-alt-circle-right:before,.deleted i.icon.fa-arrow-alt-circle-up:before,.deleted i.icon.fa-bell-slash:before,.deleted i.icon.fa-bell:before,.deleted i.icon.fa-bookmark:before,.deleted i.icon.fa-building:before,.deleted i.icon.fa-calendar-alt:before,.deleted i.icon.fa-calendar-check:before,.deleted i.icon.fa-calendar-minus:before,.deleted i.icon.fa-calendar-plus:before,.deleted i.icon.fa-calendar-times:before,.deleted i.icon.fa-calendar:before,.deleted i.icon.fa-caret-square-down:before,.deleted i.icon.fa-caret-square-left:before,.deleted i.icon.fa-caret-square-right:before,.deleted i.icon.fa-caret-square-up:before,.deleted i.icon.fa-chart-bar:before,.deleted i.icon.fa-check-circle:before,.deleted i.icon.fa-check-square:before,.deleted i.icon.fa-circle:before,.deleted i.icon.fa-clipboard:before,.deleted i.icon.fa-clock:before,.deleted i.icon.fa-clone:before,.deleted i.icon.fa-closed-captioning:before,.deleted i.icon.fa-comment-alt:before,.deleted i.icon.fa-comment-dots:before,.deleted i.icon.fa-comment:before,.deleted i.icon.fa-comments:before,.deleted i.icon.fa-compass:before,.deleted i.icon.fa-copy:before,.deleted i.icon.fa-copyright:before,.deleted i.icon.fa-credit-card:before,.deleted i.icon.fa-dizzy:before,.deleted i.icon.fa-dot-circle:before,.deleted i.icon.fa-edit:before,.deleted i.icon.fa-envelope-open:before,.deleted i.icon.fa-envelope:before,.deleted i.icon.fa-eye-slash:before,.deleted i.icon.fa-eye:before,.deleted i.icon.fa-file-alt:before,.deleted i.icon.fa-file-archive:before,.deleted i.icon.fa-file-audio:before,.deleted i.icon.fa-file-code:before,.deleted i.icon.fa-file-excel:before,.deleted i.icon.fa-file-image:before,.deleted i.icon.fa-file-pdf:before,.deleted i.icon.fa-file-powerpoint:before,.deleted i.icon.fa-file-video:before,.deleted i.icon.fa-file-word:before,.deleted i.icon.fa-file:before,.deleted i.icon.fa-flag:before,.deleted i.icon.fa-flushed:before,.deleted i.icon.fa-folder-open:before,.deleted i.icon.fa-folder:before,.deleted i.icon.fa-frown-open:before,.deleted i.icon.fa-frown:before,.deleted i.icon.fa-futbol:before,.deleted i.icon.fa-gem:before,.deleted i.icon.fa-grimace:before,.deleted i.icon.fa-grin-alt:before,.deleted i.icon.fa-grin-beam-sweat:before,.deleted i.icon.fa-grin-beam:before,.deleted i.icon.fa-grin-hearts:before,.deleted i.icon.fa-grin-squint-tears:before,.deleted i.icon.fa-grin-squint:before,.deleted i.icon.fa-grin-stars:before,.deleted i.icon.fa-grin-tears:before,.deleted i.icon.fa-grin-tongue-squint:before,.deleted i.icon.fa-grin-tongue-wink:before,.deleted i.icon.fa-grin-tongue:before,.deleted i.icon.fa-grin-wink:before,.deleted i.icon.fa-grin:before,.deleted i.icon.fa-hand-lizard:before,.deleted i.icon.fa-hand-paper:before,.deleted i.icon.fa-hand-peace:before,.deleted i.icon.fa-hand-point-down:before,.deleted i.icon.fa-hand-point-left:before,.deleted i.icon.fa-hand-point-right:before,.deleted i.icon.fa-hand-point-up:before,.deleted i.icon.fa-hand-pointer:before,.deleted i.icon.fa-hand-rock:before,.deleted i.icon.fa-hand-scissors:before,.deleted i.icon.fa-hand-spock:before,.deleted i.icon.fa-handshake:before,.deleted i.icon.fa-hdd:before,.deleted i.icon.fa-heart:before,.deleted i.icon.fa-hospital:before,.deleted i.icon.fa-hourglass:before,.deleted i.icon.fa-id-badge:before,.deleted i.icon.fa-id-card:before,.deleted i.icon.fa-image:before,.deleted i.icon.fa-images:before,.deleted i.icon.fa-keyboard:before,.deleted i.icon.fa-kiss-beam:before,.deleted i.icon.fa-kiss-wink-heart:before,.deleted i.icon.fa-kiss:before,.deleted i.icon.fa-laugh-beam:before,.deleted i.icon.fa-laugh-squint:before,.deleted i.icon.fa-laugh-wink:before,.deleted i.icon.fa-laugh:before,.deleted i.icon.fa-lemon:before,.deleted i.icon.fa-life-ring:before,.deleted i.icon.fa-lightbulb:before,.deleted i.icon.fa-list-alt:before,.deleted i.icon.fa-map:before,.deleted i.icon.fa-meh-blank:before,.deleted i.icon.fa-meh-rolling-eyes:before,.deleted i.icon.fa-meh:before,.deleted i.icon.fa-minus-square:before,.deleted i.icon.fa-money-bill-alt:before,.deleted i.icon.fa-moon:before,.deleted i.icon.fa-newspaper:before,.deleted i.icon.fa-object-group:before,.deleted i.icon.fa-object-ungroup:before,.deleted i.icon.fa-paper-plane:before,.deleted i.icon.fa-pause-circle:before,.deleted i.icon.fa-play-circle:before,.deleted i.icon.fa-plus-square:before,.deleted i.icon.fa-question-circle:before,.deleted i.icon.fa-registered:before,.deleted i.icon.fa-sad-cry:before,.deleted i.icon.fa-sad-tear:before,.deleted i.icon.fa-save:before,.deleted i.icon.fa-share-square:before,.deleted i.icon.fa-smile-beam:before,.deleted i.icon.fa-smile-wink:before,.deleted i.icon.fa-smile:before,.deleted i.icon.fa-snowflake:before,.deleted i.icon.fa-square:before,.deleted i.icon.fa-star-half:before,.deleted i.icon.fa-star:before,.deleted i.icon.fa-sticky-note:before,.deleted i.icon.fa-stop-circle:before,.deleted i.icon.fa-sun:before,.deleted i.icon.fa-surprise:before,.deleted i.icon.fa-thumbs-down:before,.deleted i.icon.fa-thumbs-up:before,.deleted i.icon.fa-times-circle:before,.deleted i.icon.fa-tired:before,.deleted i.icon.fa-trash-alt:before,.deleted i.icon.fa-user-circle:before,.deleted i.icon.fa-user:before,.deleted i.icon.fa-window-close:before,.deleted i.icon.fa-window-maximize:before,.deleted i.icon.fa-window-minimize:before,.deleted i.icon.fa-window-restore:before,.deleted i.icon.icon-address-book:before,.deleted i.icon.icon-address-card:before,.deleted i.icon.icon-angry:before,.deleted i.icon.icon-arrow-alt-circle-down:before,.deleted i.icon.icon-arrow-alt-circle-left:before,.deleted i.icon.icon-arrow-alt-circle-right:before,.deleted i.icon.icon-arrow-alt-circle-up:before,.deleted i.icon.icon-bell-slash:before,.deleted i.icon.icon-bell:before,.deleted i.icon.icon-bookmark:before,.deleted i.icon.icon-building:before,.deleted i.icon.icon-calendar-alt:before,.deleted i.icon.icon-calendar-check:before,.deleted i.icon.icon-calendar-minus:before,.deleted i.icon.icon-calendar-plus:before,.deleted i.icon.icon-calendar-times:before,.deleted i.icon.icon-calendar:before,.deleted i.icon.icon-caret-square-down:before,.deleted i.icon.icon-caret-square-left:before,.deleted i.icon.icon-caret-square-right:before,.deleted i.icon.icon-caret-square-up:before,.deleted i.icon.icon-chart-bar:before,.deleted i.icon.icon-check-circle:before,.deleted i.icon.icon-check-square:before,.deleted i.icon.icon-circle:before,.deleted i.icon.icon-clipboard:before,.deleted i.icon.icon-clock:before,.deleted i.icon.icon-clone:before,.deleted i.icon.icon-closed-captioning:before,.deleted i.icon.icon-comment-alt:before,.deleted i.icon.icon-comment-dots:before,.deleted i.icon.icon-comment:before,.deleted i.icon.icon-comments:before,.deleted i.icon.icon-compass:before,.deleted i.icon.icon-copy:before,.deleted i.icon.icon-copyright:before,.deleted i.icon.icon-credit-card:before,.deleted i.icon.icon-dizzy:before,.deleted i.icon.icon-dot-circle:before,.deleted i.icon.icon-edit:before,.deleted i.icon.icon-envelope-open:before,.deleted i.icon.icon-envelope:before,.deleted i.icon.icon-eye-slash:before,.deleted i.icon.icon-eye:before,.deleted i.icon.icon-file-alt:before,.deleted i.icon.icon-file-archive:before,.deleted i.icon.icon-file-audio:before,.deleted i.icon.icon-file-code:before,.deleted i.icon.icon-file-excel:before,.deleted i.icon.icon-file-image:before,.deleted i.icon.icon-file-pdf:before,.deleted i.icon.icon-file-powerpoint:before,.deleted i.icon.icon-file-video:before,.deleted i.icon.icon-file-word:before,.deleted i.icon.icon-file:before,.deleted i.icon.icon-flag:before,.deleted i.icon.icon-flushed:before,.deleted i.icon.icon-folder-open:before,.deleted i.icon.icon-folder:before,.deleted i.icon.icon-frown-open:before,.deleted i.icon.icon-frown:before,.deleted i.icon.icon-futbol:before,.deleted i.icon.icon-gem:before,.deleted i.icon.icon-grimace:before,.deleted i.icon.icon-grin-alt:before,.deleted i.icon.icon-grin-beam-sweat:before,.deleted i.icon.icon-grin-beam:before,.deleted i.icon.icon-grin-hearts:before,.deleted i.icon.icon-grin-squint-tears:before,.deleted i.icon.icon-grin-squint:before,.deleted i.icon.icon-grin-stars:before,.deleted i.icon.icon-grin-tears:before,.deleted i.icon.icon-grin-tongue-squint:before,.deleted i.icon.icon-grin-tongue-wink:before,.deleted i.icon.icon-grin-tongue:before,.deleted i.icon.icon-grin-wink:before,.deleted i.icon.icon-grin:before,.deleted i.icon.icon-hand-lizard:before,.deleted i.icon.icon-hand-paper:before,.deleted i.icon.icon-hand-peace:before,.deleted i.icon.icon-hand-point-down:before,.deleted i.icon.icon-hand-point-left:before,.deleted i.icon.icon-hand-point-right:before,.deleted i.icon.icon-hand-point-up:before,.deleted i.icon.icon-hand-pointer:before,.deleted i.icon.icon-hand-rock:before,.deleted i.icon.icon-hand-scissors:before,.deleted i.icon.icon-hand-spock:before,.deleted i.icon.icon-handshake:before,.deleted i.icon.icon-hdd:before,.deleted i.icon.icon-heart:before,.deleted i.icon.icon-hospital:before,.deleted i.icon.icon-hourglass:before,.deleted i.icon.icon-id-badge:before,.deleted i.icon.icon-id-card:before,.deleted i.icon.icon-image:before,.deleted i.icon.icon-images:before,.deleted i.icon.icon-keyboard:before,.deleted i.icon.icon-kiss-beam:before,.deleted i.icon.icon-kiss-wink-heart:before,.deleted i.icon.icon-kiss:before,.deleted i.icon.icon-laugh-beam:before,.deleted i.icon.icon-laugh-squint:before,.deleted i.icon.icon-laugh-wink:before,.deleted i.icon.icon-laugh:before,.deleted i.icon.icon-lemon:before,.deleted i.icon.icon-life-ring:before,.deleted i.icon.icon-lightbulb:before,.deleted i.icon.icon-list-alt:before,.deleted i.icon.icon-map:before,.deleted i.icon.icon-meh-blank:before,.deleted i.icon.icon-meh-rolling-eyes:before,.deleted i.icon.icon-meh:before,.deleted i.icon.icon-minus-square:before,.deleted i.icon.icon-money-bill-alt:before,.deleted i.icon.icon-moon:before,.deleted i.icon.icon-newspaper:before,.deleted i.icon.icon-object-group:before,.deleted i.icon.icon-object-ungroup:before,.deleted i.icon.icon-paper-plane:before,.deleted i.icon.icon-pause-circle:before,.deleted i.icon.icon-play-circle:before,.deleted i.icon.icon-plus-square:before,.deleted i.icon.icon-question-circle:before,.deleted i.icon.icon-registered:before,.deleted i.icon.icon-sad-cry:before,.deleted i.icon.icon-sad-tear:before,.deleted i.icon.icon-save:before,.deleted i.icon.icon-share-square:before,.deleted i.icon.icon-smile-beam:before,.deleted i.icon.icon-smile-wink:before,.deleted i.icon.icon-smile:before,.deleted i.icon.icon-snowflake:before,.deleted i.icon.icon-square:before,.deleted i.icon.icon-star-half:before,.deleted i.icon.icon-star:before,.deleted i.icon.icon-sticky-note:before,.deleted i.icon.icon-stop-circle:before,.deleted i.icon.icon-sun:before,.deleted i.icon.icon-surprise:before,.deleted i.icon.icon-thumbs-down:before,.deleted i.icon.icon-thumbs-up:before,.deleted i.icon.icon-times-circle:before,.deleted i.icon.icon-tired:before,.deleted i.icon.icon-trash-alt:before,.deleted i.icon.icon-user-circle:before,.deleted i.icon.icon-user:before,.deleted i.icon.icon-window-close:before,.deleted i.icon.icon-window-maximize:before,.deleted i.icon.icon-window-minimize:before,.deleted i.icon.icon-window-restore:before,.unpublished i.icon-large.fa-address-book:before,.unpublished i.icon-large.fa-address-card:before,.unpublished i.icon-large.fa-angry:before,.unpublished i.icon-large.fa-arrow-alt-circle-down:before,.unpublished i.icon-large.fa-arrow-alt-circle-left:before,.unpublished i.icon-large.fa-arrow-alt-circle-right:before,.unpublished i.icon-large.fa-arrow-alt-circle-up:before,.unpublished i.icon-large.fa-bell-slash:before,.unpublished i.icon-large.fa-bell:before,.unpublished i.icon-large.fa-bookmark:before,.unpublished i.icon-large.fa-building:before,.unpublished i.icon-large.fa-calendar-alt:before,.unpublished i.icon-large.fa-calendar-check:before,.unpublished i.icon-large.fa-calendar-minus:before,.unpublished i.icon-large.fa-calendar-plus:before,.unpublished i.icon-large.fa-calendar-times:before,.unpublished i.icon-large.fa-calendar:before,.unpublished i.icon-large.fa-caret-square-down:before,.unpublished i.icon-large.fa-caret-square-left:before,.unpublished i.icon-large.fa-caret-square-right:before,.unpublished i.icon-large.fa-caret-square-up:before,.unpublished i.icon-large.fa-chart-bar:before,.unpublished i.icon-large.fa-check-circle:before,.unpublished i.icon-large.fa-check-square:before,.unpublished i.icon-large.fa-circle:before,.unpublished i.icon-large.fa-clipboard:before,.unpublished i.icon-large.fa-clock:before,.unpublished i.icon-large.fa-clone:before,.unpublished i.icon-large.fa-closed-captioning:before,.unpublished i.icon-large.fa-comment-alt:before,.unpublished i.icon-large.fa-comment-dots:before,.unpublished i.icon-large.fa-comment:before,.unpublished i.icon-large.fa-comments:before,.unpublished i.icon-large.fa-compass:before,.unpublished i.icon-large.fa-copy:before,.unpublished i.icon-large.fa-copyright:before,.unpublished i.icon-large.fa-credit-card:before,.unpublished i.icon-large.fa-dizzy:before,.unpublished i.icon-large.fa-dot-circle:before,.unpublished i.icon-large.fa-edit:before,.unpublished i.icon-large.fa-envelope-open:before,.unpublished i.icon-large.fa-envelope:before,.unpublished i.icon-large.fa-eye-slash:before,.unpublished i.icon-large.fa-eye:before,.unpublished i.icon-large.fa-file-alt:before,.unpublished i.icon-large.fa-file-archive:before,.unpublished i.icon-large.fa-file-audio:before,.unpublished i.icon-large.fa-file-code:before,.unpublished i.icon-large.fa-file-excel:before,.unpublished i.icon-large.fa-file-image:before,.unpublished i.icon-large.fa-file-pdf:before,.unpublished i.icon-large.fa-file-powerpoint:before,.unpublished i.icon-large.fa-file-video:before,.unpublished i.icon-large.fa-file-word:before,.unpublished i.icon-large.fa-file:before,.unpublished i.icon-large.fa-flag:before,.unpublished i.icon-large.fa-flushed:before,.unpublished i.icon-large.fa-folder-open:before,.unpublished i.icon-large.fa-folder:before,.unpublished i.icon-large.fa-frown-open:before,.unpublished i.icon-large.fa-frown:before,.unpublished i.icon-large.fa-futbol:before,.unpublished i.icon-large.fa-gem:before,.unpublished i.icon-large.fa-grimace:before,.unpublished i.icon-large.fa-grin-alt:before,.unpublished i.icon-large.fa-grin-beam-sweat:before,.unpublished i.icon-large.fa-grin-beam:before,.unpublished i.icon-large.fa-grin-hearts:before,.unpublished i.icon-large.fa-grin-squint-tears:before,.unpublished i.icon-large.fa-grin-squint:before,.unpublished i.icon-large.fa-grin-stars:before,.unpublished i.icon-large.fa-grin-tears:before,.unpublished i.icon-large.fa-grin-tongue-squint:before,.unpublished i.icon-large.fa-grin-tongue-wink:before,.unpublished i.icon-large.fa-grin-tongue:before,.unpublished i.icon-large.fa-grin-wink:before,.unpublished i.icon-large.fa-grin:before,.unpublished i.icon-large.fa-hand-lizard:before,.unpublished i.icon-large.fa-hand-paper:before,.unpublished i.icon-large.fa-hand-peace:before,.unpublished i.icon-large.fa-hand-point-down:before,.unpublished i.icon-large.fa-hand-point-left:before,.unpublished i.icon-large.fa-hand-point-right:before,.unpublished i.icon-large.fa-hand-point-up:before,.unpublished i.icon-large.fa-hand-pointer:before,.unpublished i.icon-large.fa-hand-rock:before,.unpublished i.icon-large.fa-hand-scissors:before,.unpublished i.icon-large.fa-hand-spock:before,.unpublished i.icon-large.fa-handshake:before,.unpublished i.icon-large.fa-hdd:before,.unpublished i.icon-large.fa-heart:before,.unpublished i.icon-large.fa-hospital:before,.unpublished i.icon-large.fa-hourglass:before,.unpublished i.icon-large.fa-id-badge:before,.unpublished i.icon-large.fa-id-card:before,.unpublished i.icon-large.fa-image:before,.unpublished i.icon-large.fa-images:before,.unpublished i.icon-large.fa-keyboard:before,.unpublished i.icon-large.fa-kiss-beam:before,.unpublished i.icon-large.fa-kiss-wink-heart:before,.unpublished i.icon-large.fa-kiss:before,.unpublished i.icon-large.fa-laugh-beam:before,.unpublished i.icon-large.fa-laugh-squint:before,.unpublished i.icon-large.fa-laugh-wink:before,.unpublished i.icon-large.fa-laugh:before,.unpublished i.icon-large.fa-lemon:before,.unpublished i.icon-large.fa-life-ring:before,.unpublished i.icon-large.fa-lightbulb:before,.unpublished i.icon-large.fa-list-alt:before,.unpublished i.icon-large.fa-map:before,.unpublished i.icon-large.fa-meh-blank:before,.unpublished i.icon-large.fa-meh-rolling-eyes:before,.unpublished i.icon-large.fa-meh:before,.unpublished i.icon-large.fa-minus-square:before,.unpublished i.icon-large.fa-money-bill-alt:before,.unpublished i.icon-large.fa-moon:before,.unpublished i.icon-large.fa-newspaper:before,.unpublished i.icon-large.fa-object-group:before,.unpublished i.icon-large.fa-object-ungroup:before,.unpublished i.icon-large.fa-paper-plane:before,.unpublished i.icon-large.fa-pause-circle:before,.unpublished i.icon-large.fa-play-circle:before,.unpublished i.icon-large.fa-plus-square:before,.unpublished i.icon-large.fa-question-circle:before,.unpublished i.icon-large.fa-registered:before,.unpublished i.icon-large.fa-sad-cry:before,.unpublished i.icon-large.fa-sad-tear:before,.unpublished i.icon-large.fa-save:before,.unpublished i.icon-large.fa-share-square:before,.unpublished i.icon-large.fa-smile-beam:before,.unpublished i.icon-large.fa-smile-wink:before,.unpublished i.icon-large.fa-smile:before,.unpublished i.icon-large.fa-snowflake:before,.unpublished i.icon-large.fa-square:before,.unpublished i.icon-large.fa-star-half:before,.unpublished i.icon-large.fa-star:before,.unpublished i.icon-large.fa-sticky-note:before,.unpublished i.icon-large.fa-stop-circle:before,.unpublished i.icon-large.fa-sun:before,.unpublished i.icon-large.fa-surprise:before,.unpublished i.icon-large.fa-thumbs-down:before,.unpublished i.icon-large.fa-thumbs-up:before,.unpublished i.icon-large.fa-times-circle:before,.unpublished i.icon-large.fa-tired:before,.unpublished i.icon-large.fa-trash-alt:before,.unpublished i.icon-large.fa-user-circle:before,.unpublished i.icon-large.fa-user:before,.unpublished i.icon-large.fa-window-close:before,.unpublished i.icon-large.fa-window-maximize:before,.unpublished i.icon-large.fa-window-minimize:before,.unpublished i.icon-large.fa-window-restore:before,.unpublished i.icon-large.icon-address-book:before,.unpublished i.icon-large.icon-address-card:before,.unpublished i.icon-large.icon-angry:before,.unpublished i.icon-large.icon-arrow-alt-circle-down:before,.unpublished i.icon-large.icon-arrow-alt-circle-left:before,.unpublished i.icon-large.icon-arrow-alt-circle-right:before,.unpublished i.icon-large.icon-arrow-alt-circle-up:before,.unpublished i.icon-large.icon-bell-slash:before,.unpublished i.icon-large.icon-bell:before,.unpublished i.icon-large.icon-bookmark:before,.unpublished i.icon-large.icon-building:before,.unpublished i.icon-large.icon-calendar-alt:before,.unpublished i.icon-large.icon-calendar-check:before,.unpublished i.icon-large.icon-calendar-minus:before,.unpublished i.icon-large.icon-calendar-plus:before,.unpublished i.icon-large.icon-calendar-times:before,.unpublished i.icon-large.icon-calendar:before,.unpublished i.icon-large.icon-caret-square-down:before,.unpublished i.icon-large.icon-caret-square-left:before,.unpublished i.icon-large.icon-caret-square-right:before,.unpublished i.icon-large.icon-caret-square-up:before,.unpublished i.icon-large.icon-chart-bar:before,.unpublished i.icon-large.icon-check-circle:before,.unpublished i.icon-large.icon-check-square:before,.unpublished i.icon-large.icon-circle:before,.unpublished i.icon-large.icon-clipboard:before,.unpublished i.icon-large.icon-clock:before,.unpublished i.icon-large.icon-clone:before,.unpublished i.icon-large.icon-closed-captioning:before,.unpublished i.icon-large.icon-comment-alt:before,.unpublished i.icon-large.icon-comment-dots:before,.unpublished i.icon-large.icon-comment:before,.unpublished i.icon-large.icon-comments:before,.unpublished i.icon-large.icon-compass:before,.unpublished i.icon-large.icon-copy:before,.unpublished i.icon-large.icon-copyright:before,.unpublished i.icon-large.icon-credit-card:before,.unpublished i.icon-large.icon-dizzy:before,.unpublished i.icon-large.icon-dot-circle:before,.unpublished i.icon-large.icon-edit:before,.unpublished i.icon-large.icon-envelope-open:before,.unpublished i.icon-large.icon-envelope:before,.unpublished i.icon-large.icon-eye-slash:before,.unpublished i.icon-large.icon-eye:before,.unpublished i.icon-large.icon-file-alt:before,.unpublished i.icon-large.icon-file-archive:before,.unpublished i.icon-large.icon-file-audio:before,.unpublished i.icon-large.icon-file-code:before,.unpublished i.icon-large.icon-file-excel:before,.unpublished i.icon-large.icon-file-image:before,.unpublished i.icon-large.icon-file-pdf:before,.unpublished i.icon-large.icon-file-powerpoint:before,.unpublished i.icon-large.icon-file-video:before,.unpublished i.icon-large.icon-file-word:before,.unpublished i.icon-large.icon-file:before,.unpublished i.icon-large.icon-flag:before,.unpublished i.icon-large.icon-flushed:before,.unpublished i.icon-large.icon-folder-open:before,.unpublished i.icon-large.icon-folder:before,.unpublished i.icon-large.icon-frown-open:before,.unpublished i.icon-large.icon-frown:before,.unpublished i.icon-large.icon-futbol:before,.unpublished i.icon-large.icon-gem:before,.unpublished i.icon-large.icon-grimace:before,.unpublished i.icon-large.icon-grin-alt:before,.unpublished i.icon-large.icon-grin-beam-sweat:before,.unpublished i.icon-large.icon-grin-beam:before,.unpublished i.icon-large.icon-grin-hearts:before,.unpublished i.icon-large.icon-grin-squint-tears:before,.unpublished i.icon-large.icon-grin-squint:before,.unpublished i.icon-large.icon-grin-stars:before,.unpublished i.icon-large.icon-grin-tears:before,.unpublished i.icon-large.icon-grin-tongue-squint:before,.unpublished i.icon-large.icon-grin-tongue-wink:before,.unpublished i.icon-large.icon-grin-tongue:before,.unpublished i.icon-large.icon-grin-wink:before,.unpublished i.icon-large.icon-grin:before,.unpublished i.icon-large.icon-hand-lizard:before,.unpublished i.icon-large.icon-hand-paper:before,.unpublished i.icon-large.icon-hand-peace:before,.unpublished i.icon-large.icon-hand-point-down:before,.unpublished i.icon-large.icon-hand-point-left:before,.unpublished i.icon-large.icon-hand-point-right:before,.unpublished i.icon-large.icon-hand-point-up:before,.unpublished i.icon-large.icon-hand-pointer:before,.unpublished i.icon-large.icon-hand-rock:before,.unpublished i.icon-large.icon-hand-scissors:before,.unpublished i.icon-large.icon-hand-spock:before,.unpublished i.icon-large.icon-handshake:before,.unpublished i.icon-large.icon-hdd:before,.unpublished i.icon-large.icon-heart:before,.unpublished i.icon-large.icon-hospital:before,.unpublished i.icon-large.icon-hourglass:before,.unpublished i.icon-large.icon-id-badge:before,.unpublished i.icon-large.icon-id-card:before,.unpublished i.icon-large.icon-image:before,.unpublished i.icon-large.icon-images:before,.unpublished i.icon-large.icon-keyboard:before,.unpublished i.icon-large.icon-kiss-beam:before,.unpublished i.icon-large.icon-kiss-wink-heart:before,.unpublished i.icon-large.icon-kiss:before,.unpublished i.icon-large.icon-laugh-beam:before,.unpublished i.icon-large.icon-laugh-squint:before,.unpublished i.icon-large.icon-laugh-wink:before,.unpublished i.icon-large.icon-laugh:before,.unpublished i.icon-large.icon-lemon:before,.unpublished i.icon-large.icon-life-ring:before,.unpublished i.icon-large.icon-lightbulb:before,.unpublished i.icon-large.icon-list-alt:before,.unpublished i.icon-large.icon-map:before,.unpublished i.icon-large.icon-meh-blank:before,.unpublished i.icon-large.icon-meh-rolling-eyes:before,.unpublished i.icon-large.icon-meh:before,.unpublished i.icon-large.icon-minus-square:before,.unpublished i.icon-large.icon-money-bill-alt:before,.unpublished i.icon-large.icon-moon:before,.unpublished i.icon-large.icon-newspaper:before,.unpublished i.icon-large.icon-object-group:before,.unpublished i.icon-large.icon-object-ungroup:before,.unpublished i.icon-large.icon-paper-plane:before,.unpublished i.icon-large.icon-pause-circle:before,.unpublished i.icon-large.icon-play-circle:before,.unpublished i.icon-large.icon-plus-square:before,.unpublished i.icon-large.icon-question-circle:before,.unpublished i.icon-large.icon-registered:before,.unpublished i.icon-large.icon-sad-cry:before,.unpublished i.icon-large.icon-sad-tear:before,.unpublished i.icon-large.icon-save:before,.unpublished i.icon-large.icon-share-square:before,.unpublished i.icon-large.icon-smile-beam:before,.unpublished i.icon-large.icon-smile-wink:before,.unpublished i.icon-large.icon-smile:before,.unpublished i.icon-large.icon-snowflake:before,.unpublished i.icon-large.icon-square:before,.unpublished i.icon-large.icon-star-half:before,.unpublished i.icon-large.icon-star:before,.unpublished i.icon-large.icon-sticky-note:before,.unpublished i.icon-large.icon-stop-circle:before,.unpublished i.icon-large.icon-sun:before,.unpublished i.icon-large.icon-surprise:before,.unpublished i.icon-large.icon-thumbs-down:before,.unpublished i.icon-large.icon-thumbs-up:before,.unpublished i.icon-large.icon-times-circle:before,.unpublished i.icon-large.icon-tired:before,.unpublished i.icon-large.icon-trash-alt:before,.unpublished i.icon-large.icon-user-circle:before,.unpublished i.icon-large.icon-user:before,.unpublished i.icon-large.icon-window-close:before,.unpublished i.icon-large.icon-window-maximize:before,.unpublished i.icon-large.icon-window-minimize:before,.unpublished i.icon-large.icon-window-restore:before,.unpublished i.icon.fa-address-book:before,.unpublished i.icon.fa-address-card:before,.unpublished i.icon.fa-angry:before,.unpublished i.icon.fa-arrow-alt-circle-down:before,.unpublished i.icon.fa-arrow-alt-circle-left:before,.unpublished i.icon.fa-arrow-alt-circle-right:before,.unpublished i.icon.fa-arrow-alt-circle-up:before,.unpublished i.icon.fa-bell-slash:before,.unpublished i.icon.fa-bell:before,.unpublished i.icon.fa-bookmark:before,.unpublished i.icon.fa-building:before,.unpublished i.icon.fa-calendar-alt:before,.unpublished i.icon.fa-calendar-check:before,.unpublished i.icon.fa-calendar-minus:before,.unpublished i.icon.fa-calendar-plus:before,.unpublished i.icon.fa-calendar-times:before,.unpublished i.icon.fa-calendar:before,.unpublished i.icon.fa-caret-square-down:before,.unpublished i.icon.fa-caret-square-left:before,.unpublished i.icon.fa-caret-square-right:before,.unpublished i.icon.fa-caret-square-up:before,.unpublished i.icon.fa-chart-bar:before,.unpublished i.icon.fa-check-circle:before,.unpublished i.icon.fa-check-square:before,.unpublished i.icon.fa-circle:before,.unpublished i.icon.fa-clipboard:before,.unpublished i.icon.fa-clock:before,.unpublished i.icon.fa-clone:before,.unpublished i.icon.fa-closed-captioning:before,.unpublished i.icon.fa-comment-alt:before,.unpublished i.icon.fa-comment-dots:before,.unpublished i.icon.fa-comment:before,.unpublished i.icon.fa-comments:before,.unpublished i.icon.fa-compass:before,.unpublished i.icon.fa-copy:before,.unpublished i.icon.fa-copyright:before,.unpublished i.icon.fa-credit-card:before,.unpublished i.icon.fa-dizzy:before,.unpublished i.icon.fa-dot-circle:before,.unpublished i.icon.fa-edit:before,.unpublished i.icon.fa-envelope-open:before,.unpublished i.icon.fa-envelope:before,.unpublished i.icon.fa-eye-slash:before,.unpublished i.icon.fa-eye:before,.unpublished i.icon.fa-file-alt:before,.unpublished i.icon.fa-file-archive:before,.unpublished i.icon.fa-file-audio:before,.unpublished i.icon.fa-file-code:before,.unpublished i.icon.fa-file-excel:before,.unpublished i.icon.fa-file-image:before,.unpublished i.icon.fa-file-pdf:before,.unpublished i.icon.fa-file-powerpoint:before,.unpublished i.icon.fa-file-video:before,.unpublished i.icon.fa-file-word:before,.unpublished i.icon.fa-file:before,.unpublished i.icon.fa-flag:before,.unpublished i.icon.fa-flushed:before,.unpublished i.icon.fa-folder-open:before,.unpublished i.icon.fa-folder:before,.unpublished i.icon.fa-frown-open:before,.unpublished i.icon.fa-frown:before,.unpublished i.icon.fa-futbol:before,.unpublished i.icon.fa-gem:before,.unpublished i.icon.fa-grimace:before,.unpublished i.icon.fa-grin-alt:before,.unpublished i.icon.fa-grin-beam-sweat:before,.unpublished i.icon.fa-grin-beam:before,.unpublished i.icon.fa-grin-hearts:before,.unpublished i.icon.fa-grin-squint-tears:before,.unpublished i.icon.fa-grin-squint:before,.unpublished i.icon.fa-grin-stars:before,.unpublished i.icon.fa-grin-tears:before,.unpublished i.icon.fa-grin-tongue-squint:before,.unpublished i.icon.fa-grin-tongue-wink:before,.unpublished i.icon.fa-grin-tongue:before,.unpublished i.icon.fa-grin-wink:before,.unpublished i.icon.fa-grin:before,.unpublished i.icon.fa-hand-lizard:before,.unpublished i.icon.fa-hand-paper:before,.unpublished i.icon.fa-hand-peace:before,.unpublished i.icon.fa-hand-point-down:before,.unpublished i.icon.fa-hand-point-left:before,.unpublished i.icon.fa-hand-point-right:before,.unpublished i.icon.fa-hand-point-up:before,.unpublished i.icon.fa-hand-pointer:before,.unpublished i.icon.fa-hand-rock:before,.unpublished i.icon.fa-hand-scissors:before,.unpublished i.icon.fa-hand-spock:before,.unpublished i.icon.fa-handshake:before,.unpublished i.icon.fa-hdd:before,.unpublished i.icon.fa-heart:before,.unpublished i.icon.fa-hospital:before,.unpublished i.icon.fa-hourglass:before,.unpublished i.icon.fa-id-badge:before,.unpublished i.icon.fa-id-card:before,.unpublished i.icon.fa-image:before,.unpublished i.icon.fa-images:before,.unpublished i.icon.fa-keyboard:before,.unpublished i.icon.fa-kiss-beam:before,.unpublished i.icon.fa-kiss-wink-heart:before,.unpublished i.icon.fa-kiss:before,.unpublished i.icon.fa-laugh-beam:before,.unpublished i.icon.fa-laugh-squint:before,.unpublished i.icon.fa-laugh-wink:before,.unpublished i.icon.fa-laugh:before,.unpublished i.icon.fa-lemon:before,.unpublished i.icon.fa-life-ring:before,.unpublished i.icon.fa-lightbulb:before,.unpublished i.icon.fa-list-alt:before,.unpublished i.icon.fa-map:before,.unpublished i.icon.fa-meh-blank:before,.unpublished i.icon.fa-meh-rolling-eyes:before,.unpublished i.icon.fa-meh:before,.unpublished i.icon.fa-minus-square:before,.unpublished i.icon.fa-money-bill-alt:before,.unpublished i.icon.fa-moon:before,.unpublished i.icon.fa-newspaper:before,.unpublished i.icon.fa-object-group:before,.unpublished i.icon.fa-object-ungroup:before,.unpublished i.icon.fa-paper-plane:before,.unpublished i.icon.fa-pause-circle:before,.unpublished i.icon.fa-play-circle:before,.unpublished i.icon.fa-plus-square:before,.unpublished i.icon.fa-question-circle:before,.unpublished i.icon.fa-registered:before,.unpublished i.icon.fa-sad-cry:before,.unpublished i.icon.fa-sad-tear:before,.unpublished i.icon.fa-save:before,.unpublished i.icon.fa-share-square:before,.unpublished i.icon.fa-smile-beam:before,.unpublished i.icon.fa-smile-wink:before,.unpublished i.icon.fa-smile:before,.unpublished i.icon.fa-snowflake:before,.unpublished i.icon.fa-square:before,.unpublished i.icon.fa-star-half:before,.unpublished i.icon.fa-star:before,.unpublished i.icon.fa-sticky-note:before,.unpublished i.icon.fa-stop-circle:before,.unpublished i.icon.fa-sun:before,.unpublished i.icon.fa-surprise:before,.unpublished i.icon.fa-thumbs-down:before,.unpublished i.icon.fa-thumbs-up:before,.unpublished i.icon.fa-times-circle:before,.unpublished i.icon.fa-tired:before,.unpublished i.icon.fa-trash-alt:before,.unpublished i.icon.fa-user-circle:before,.unpublished i.icon.fa-user:before,.unpublished i.icon.fa-window-close:before,.unpublished i.icon.fa-window-maximize:before,.unpublished i.icon.fa-window-minimize:before,.unpublished i.icon.fa-window-restore:before,.unpublished i.icon.icon-address-book:before,.unpublished i.icon.icon-address-card:before,.unpublished i.icon.icon-angry:before,.unpublished i.icon.icon-arrow-alt-circle-down:before,.unpublished i.icon.icon-arrow-alt-circle-left:before,.unpublished i.icon.icon-arrow-alt-circle-right:before,.unpublished i.icon.icon-arrow-alt-circle-up:before,.unpublished i.icon.icon-bell-slash:before,.unpublished i.icon.icon-bell:before,.unpublished i.icon.icon-bookmark:before,.unpublished i.icon.icon-building:before,.unpublished i.icon.icon-calendar-alt:before,.unpublished i.icon.icon-calendar-check:before,.unpublished i.icon.icon-calendar-minus:before,.unpublished i.icon.icon-calendar-plus:before,.unpublished i.icon.icon-calendar-times:before,.unpublished i.icon.icon-calendar:before,.unpublished i.icon.icon-caret-square-down:before,.unpublished i.icon.icon-caret-square-left:before,.unpublished i.icon.icon-caret-square-right:before,.unpublished i.icon.icon-caret-square-up:before,.unpublished i.icon.icon-chart-bar:before,.unpublished i.icon.icon-check-circle:before,.unpublished i.icon.icon-check-square:before,.unpublished i.icon.icon-circle:before,.unpublished i.icon.icon-clipboard:before,.unpublished i.icon.icon-clock:before,.unpublished i.icon.icon-clone:before,.unpublished i.icon.icon-closed-captioning:before,.unpublished i.icon.icon-comment-alt:before,.unpublished i.icon.icon-comment-dots:before,.unpublished i.icon.icon-comment:before,.unpublished i.icon.icon-comments:before,.unpublished i.icon.icon-compass:before,.unpublished i.icon.icon-copy:before,.unpublished i.icon.icon-copyright:before,.unpublished i.icon.icon-credit-card:before,.unpublished i.icon.icon-dizzy:before,.unpublished i.icon.icon-dot-circle:before,.unpublished i.icon.icon-edit:before,.unpublished i.icon.icon-envelope-open:before,.unpublished i.icon.icon-envelope:before,.unpublished i.icon.icon-eye-slash:before,.unpublished i.icon.icon-eye:before,.unpublished i.icon.icon-file-alt:before,.unpublished i.icon.icon-file-archive:before,.unpublished i.icon.icon-file-audio:before,.unpublished i.icon.icon-file-code:before,.unpublished i.icon.icon-file-excel:before,.unpublished i.icon.icon-file-image:before,.unpublished i.icon.icon-file-pdf:before,.unpublished i.icon.icon-file-powerpoint:before,.unpublished i.icon.icon-file-video:before,.unpublished i.icon.icon-file-word:before,.unpublished i.icon.icon-file:before,.unpublished i.icon.icon-flag:before,.unpublished i.icon.icon-flushed:before,.unpublished i.icon.icon-folder-open:before,.unpublished i.icon.icon-folder:before,.unpublished i.icon.icon-frown-open:before,.unpublished i.icon.icon-frown:before,.unpublished i.icon.icon-futbol:before,.unpublished i.icon.icon-gem:before,.unpublished i.icon.icon-grimace:before,.unpublished i.icon.icon-grin-alt:before,.unpublished i.icon.icon-grin-beam-sweat:before,.unpublished i.icon.icon-grin-beam:before,.unpublished i.icon.icon-grin-hearts:before,.unpublished i.icon.icon-grin-squint-tears:before,.unpublished i.icon.icon-grin-squint:before,.unpublished i.icon.icon-grin-stars:before,.unpublished i.icon.icon-grin-tears:before,.unpublished i.icon.icon-grin-tongue-squint:before,.unpublished i.icon.icon-grin-tongue-wink:before,.unpublished i.icon.icon-grin-tongue:before,.unpublished i.icon.icon-grin-wink:before,.unpublished i.icon.icon-grin:before,.unpublished i.icon.icon-hand-lizard:before,.unpublished i.icon.icon-hand-paper:before,.unpublished i.icon.icon-hand-peace:before,.unpublished i.icon.icon-hand-point-down:before,.unpublished i.icon.icon-hand-point-left:before,.unpublished i.icon.icon-hand-point-right:before,.unpublished i.icon.icon-hand-point-up:before,.unpublished i.icon.icon-hand-pointer:before,.unpublished i.icon.icon-hand-rock:before,.unpublished i.icon.icon-hand-scissors:before,.unpublished i.icon.icon-hand-spock:before,.unpublished i.icon.icon-handshake:before,.unpublished i.icon.icon-hdd:before,.unpublished i.icon.icon-heart:before,.unpublished i.icon.icon-hospital:before,.unpublished i.icon.icon-hourglass:before,.unpublished i.icon.icon-id-badge:before,.unpublished i.icon.icon-id-card:before,.unpublished i.icon.icon-image:before,.unpublished i.icon.icon-images:before,.unpublished i.icon.icon-keyboard:before,.unpublished i.icon.icon-kiss-beam:before,.unpublished i.icon.icon-kiss-wink-heart:before,.unpublished i.icon.icon-kiss:before,.unpublished i.icon.icon-laugh-beam:before,.unpublished i.icon.icon-laugh-squint:before,.unpublished i.icon.icon-laugh-wink:before,.unpublished i.icon.icon-laugh:before,.unpublished i.icon.icon-lemon:before,.unpublished i.icon.icon-life-ring:before,.unpublished i.icon.icon-lightbulb:before,.unpublished i.icon.icon-list-alt:before,.unpublished i.icon.icon-map:before,.unpublished i.icon.icon-meh-blank:before,.unpublished i.icon.icon-meh-rolling-eyes:before,.unpublished i.icon.icon-meh:before,.unpublished i.icon.icon-minus-square:before,.unpublished i.icon.icon-money-bill-alt:before,.unpublished i.icon.icon-moon:before,.unpublished i.icon.icon-newspaper:before,.unpublished i.icon.icon-object-group:before,.unpublished i.icon.icon-object-ungroup:before,.unpublished i.icon.icon-paper-plane:before,.unpublished i.icon.icon-pause-circle:before,.unpublished i.icon.icon-play-circle:before,.unpublished i.icon.icon-plus-square:before,.unpublished i.icon.icon-question-circle:before,.unpublished i.icon.icon-registered:before,.unpublished i.icon.icon-sad-cry:before,.unpublished i.icon.icon-sad-tear:before,.unpublished i.icon.icon-save:before,.unpublished i.icon.icon-share-square:before,.unpublished i.icon.icon-smile-beam:before,.unpublished i.icon.icon-smile-wink:before,.unpublished i.icon.icon-smile:before,.unpublished i.icon.icon-snowflake:before,.unpublished i.icon.icon-square:before,.unpublished i.icon.icon-star-half:before,.unpublished i.icon.icon-star:before,.unpublished i.icon.icon-sticky-note:before,.unpublished i.icon.icon-stop-circle:before,.unpublished i.icon.icon-sun:before,.unpublished i.icon.icon-surprise:before,.unpublished i.icon.icon-thumbs-down:before,.unpublished i.icon.icon-thumbs-up:before,.unpublished i.icon.icon-times-circle:before,.unpublished i.icon.icon-tired:before,.unpublished i.icon.icon-trash-alt:before,.unpublished i.icon.icon-user-circle:before,.unpublished i.icon.icon-user:before,.unpublished i.icon.icon-window-close:before,.unpublished i.icon.icon-window-maximize:before,.unpublished i.icon.icon-window-minimize:before,.unpublished i.icon.icon-window-restore:before{font-weight:400}.x-tree-node-el .icon-plus-circle,.x-tree-node-el .icon-refresh{font-size:1em;vertical-align:0}.unpublished,.unpublished a span{color:#9c9c9c!important;font-style:normal}.unpublished a span i.icon,.unpublished a span i.icon-large,.unpublished i.icon,.unpublished i.icon-large{color:#9c9c9c!important}.hidemenu,.hidemenu a span{color:#999;font-style:italic}.hidemenu.unpublished a span i.icon,.hidemenu.unpublished a span i.icon-large,.hidemenu.unpublished i.icon,.hidemenu.unpublished i.icon-large,.hidemenu a span.unpublished a span i.icon,.hidemenu a span.unpublished a span i.icon-large,.hidemenu a span.unpublished i.icon,.hidemenu a span.unpublished i.icon-large{color:#999}.hidemenu a span i.icon,.hidemenu a span i.icon-large,.hidemenu i.icon,.hidemenu i.icon-large{color:#383838}.deleted,.deleted a span,.deleted i.icon,.deleted i.icon-large{color:#af5a62bf!important}.deleted a span{text-decoration:line-through}.element-node-disabled a span{color:#919191}.x-tree-node{background:#fff;color:#999;position:relative}.x-tree-node .element-node-disabled a span,.x-tree-node .element-node-disabled i.icon,.x-tree-node .x-tree-node-disabled a span,.x-tree-node .x-tree-node-disabled i.icon{color:#919191}.element-node-locked a span{font-style:inherit}.modx-tree-node-tool-ct{bottom:0;line-height:1.8;position:absolute;right:6px;top:0}html[dir=rtl] .modx-tree-node-tool-ct{left:6px;right:unset}.modx-tree-node-tool-ct .x-btn:focus,.modx-tree-node-tool-ct .x-btn:hover{color:#6cb24a!important}#modx-gr-tree-resource .modx-tree-node-tool-ct,#modx-ih-resource-tree .modx-tree-node-tool-ct{display:none}.x-tree-node-el .modx-tree-node-btn-create{bottom:0;line-height:34px;opacity:0;overflow:hidden;position:absolute;right:6px;top:0;transition:opacity .4s ease-in}html[dir=rtl] .x-tree-node-el .modx-tree-node-btn-create{left:6px;right:unset}.x-tree-node-el .modx-tree-node-btn-create .x-btn{color:#515151;opacity:.4;transition:opacity .2s ease-in-out,color .2s ease-in-out}.x-tree-node-el .modx-tree-node-btn-create .x-btn:focus,.x-tree-node-el .modx-tree-node-btn-create .x-btn:hover{color:#6cb24a;opacity:1}#modx-gr-tree-resource .x-tree-node-el .modx-tree-node-btn-create,#modx-ih-resource-tree .x-tree-node-el .modx-tree-node-btn-create{display:none}.x-tree-node-el:focus-within .modx-tree-node-btn-create,.x-tree-node-el:focus .modx-tree-node-btn-create,.x-tree-node-el:hover .modx-tree-node-btn-create{opacity:1}.tree-pseudoroot-node.x-tree-node-el{background-color:#f1f1f1;font:500 14px/3 -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;padding:0 5px;position:relative}.tree-pseudoroot-node.x-tree-node-el>.icon,.tree-pseudoroot-node.x-tree-node-el a span{color:#53595f}.tree-pseudoroot-node.x-tree-node-el .modx-tree-node-tool-ct{filter:alpha(opacity=50);line-height:3;opacity:.5}.tree-pseudoroot-node.x-tree-node-el .modx-tree-node-tool-ct .x-btn{margin-left:2px}.tree-pseudoroot-node.x-tree-node-el.x-tree-node-collapsed{border-bottom:1px solid #e4e4e4}.tree-pseudoroot-node.x-tree-node-el.x-tree-node-expanded,.tree-pseudoroot-node.x-tree-node-el.x-tree-node-expanded>.icon,.tree-pseudoroot-node.x-tree-node-el.x-tree-node-expanded span{color:#53595f}.tree-pseudoroot-node.x-tree-node-el.x-tree-node-over{background-color:#e4e4e4;color:#53595f}.tree-pseudoroot-node.x-tree-node-el+.x-tree-node-ct,.tree-pseudoroot-node.x-tree-node-el+div>.x-tree-node-ct{background:#fbfbfb;overflow-x:auto}.tree-pseudoroot-node.x-tree-node-el+.x-tree-node-ct:empty,.tree-pseudoroot-node.x-tree-node-el+div>.x-tree-node-ct:empty{padding:0}.tree-pseudoroot-node.x-tree-node-el:hover .modx-tree-node-tool-ct{filter:alpha(opacity=100);opacity:1}.tree-pseudoroot-node.x-tree-node-el:hover .modx-tree-node-tool-ct .x-btn{color:inherit}.x-tree-elbow,.x-tree-elbow-end{display:inline-block}#modx-leftbar .icon,.x-tree-node .icon{background:none;border:0;display:inline-block;filter:alpha(opacity=80);margin:0;opacity:.8;padding:3px;text-align:center}#modx-leftbar .icon.icon-code:before,#modx-leftbar .icon.icon-cogs:before,#modx-leftbar .icon.icon-columns:before,#modx-leftbar .icon.icon-folder:before,#modx-leftbar .icon.icon-th-large:before,.x-tree-node .icon.icon-code:before,.x-tree-node .icon.icon-cogs:before,.x-tree-node .icon.icon-columns:before,.x-tree-node .icon.icon-folder:before,.x-tree-node .icon.icon-th-large:before{font-weight:900}#modx-leftbar .icon i,.x-tree-node .icon i{font-style:normal}#modx-leftbar .icon button,.x-tree-node .icon button{display:none}.x-tree-node-ct .x-tree-node .icon{left:-1px;position:relative;top:-1px}.x-dd-drag-ghost a,.x-dd-drag-ghost a span,.x-tree-node a,.x-tree-node a span{color:#383838}.x-tree-node div.x-tree-drag-insert-below{border-bottom:2px solid #a8c3e2!important}.x-tree-node div.x-tree-drag-insert-above{border-top:2px solid #a8c3e2!important}.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below a{border-bottom:2px solid #a8c3e2!important}.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above a{border-top:2px solid #a8c3e2!important}.x-tree-node .x-tree-drag-append a span,.x-tree-node .x-tree-node-over{background-color:#e4e4e4}.x-tree-node .x-tree-selected{background-color:#d6e7f8}.x-tree-node .x-tree-expanded{background-color:#e4e4e4;color:#234368}.x-tree-node .x-tree-expanded a,.x-tree-node .x-tree-expanded a span{color:#234368}.icon-rss:before{content:"\f09e"}.icon-cal:before,.icon-ical:before,.icon-ics:before,.icon-vcs:before{content:"\f133"}.icon-db:before,.icon-sql:before{content:"\f1c0"}.icon-7z:before,.icon-bz2:before,.icon-dmg:before,.icon-gz:before,.icon-iso:before,.icon-rar:before,.icon-tar:before,.icon-tgz:before,.icon-zip:before{content:"\f1c6"}.icon-backup:before,.icon-bak:before,.icon-bk:before{content:"\f1da"}.icon-bmp:before,.icon-gif:before,.icon-jpeg:before,.icon-jpg:before,.icon-png:before,.icon-svg:before,.icon-tiff:before{content:"\f1c5"}.icon-bat:before,.icon-scr:before,.icon-sh:before{content:"\f120"}.icon-log:before,.icon-txt:before{content:"\f15c"}.icon-aac:before,.icon-aif:before,.icon-aiff:before,.icon-flac:before,.icon-m4a:before,.icon-mp3:before,.icon-ogg:before,.icon-wav:before,.icon-wma:before{content:"\f1c7"}.icon-3gp:before,.icon-avi:before,.icon-fla:before,.icon-flv:before,.icon-m4v:before,.icon-mov:before,.icon-mp4:before,.icon-mpeg:before,.icon-mpg:before,.icon-swf:before,.icon-wmv:before{content:"\f1c8"}.icon-access:before,.icon-htaccess:before{content:"\f023"}.icon-as:before,.icon-cfm:before,.icon-jar:before,.icon-java:before,.icon-php:before,.icon-rb:before{content:"\f1c9"}.icon-doc:before,.icon-docx:before{content:"\f1c2"}.icon-csv:before,.icon-xls:before,.icon-xlsx:before{content:"\f1c3"}.icon-ppt:before,.icon-pptx:before{content:"\f1c4"}.icon-pdf:before{content:"\f1c1"}.icon-coffeescript:before,.icon-css:before,.icon-htm:before,.icon-html:before,.icon-js:before,.icon-json:before,.icon-less:before,.icon-scss:before,.icon-styl:before,.icon-xml:before{content:"\f1c9"}.icon-action{background-image:url(../images/restyle/icons/application_osx_terminal.png)!important;background-position:50%!important;background-repeat:no-repeat!important;min-height:16px;min-width:16px;vertical-align:middle}.icon-action.x-tree-node-el{background-position:5px 5px!important}.icon-action:before{content:" "}.icon-namespace{background-image:url(../images/restyle/icons/computer.png)!important;background-position:50%!important;background-repeat:no-repeat!important;min-height:16px;min-width:16px;vertical-align:middle}.icon-namespace.x-tree-node-el{background-position:5px 5px!important}.icon-namespace:before{content:" "}.icon-list-new{background-image:url(../images/restyle/icons/layout_add.png)!important;background-position:50%!important;background-repeat:no-repeat!important;min-height:16px;min-width:16px;vertical-align:middle}.icon-list-new.x-tree-node-el{background-position:5px 5px!important}.icon-list-new:before{content:" "}.icon-mark-active{background-image:url(../images/restyle/icons/layout_edit.png)!important;background-position:50%!important;background-repeat:no-repeat!important;min-height:16px;min-width:16px;vertical-align:middle}.icon-mark-active.x-tree-node-el{background-position:5px 5px!important}.icon-mark-active:before{content:" "}.icon-mark-complete{background-image:url(../images/restyle/icons/layout_header.png)!important;background-position:50%!important;background-repeat:no-repeat!important;min-height:16px;min-width:16px;vertical-align:middle}.icon-mark-complete.x-tree-node-el{background-position:5px 5px!important}.icon-mark-complete:before{content:" "}.icon-package{background-image:url(../images/restyle/icons/package.png)!important;background-position:50%!important;background-repeat:no-repeat!important;min-height:16px;min-width:16px;padding-right:5px!important;vertical-align:middle}.icon-package.x-tree-node-el{background-position:5px 5px!important}.icon-package:before{content:" "}.icon-locked{background-image:url(../images/restyle/icons/lock_edit.png)!important;background-position:50%!important;background-repeat:no-repeat!important;min-height:16px;min-width:16px;vertical-align:middle}.icon-locked.x-tree-node-el{background-position:5px 5px!important}.icon-locked:before{content:" "}.icon-lock{content:"\f023"}#modx-resource-tree-panel .x-accordion-hd{background-position:0 0}#modx-element-tree-panel .x-accordion-hd{background-position:0 -32px}#modx-file-tree-panel .x-accordion-hd{background-position:0 -64px}#modx-static-page-settings .x-accordion-hd{background-position:0 -96px}.x-tree-node-el .x-tree-node-icon{display:inline-block}.x-tree-node-loading .x-tree-node-icon{background-image:url(../images/modx-theme/tree/loading.gif)!important}.x-tree-node-loading a span{color:#444;font-style:italic}.tree-context:before{content:"\f0ac"}.tree-resource:before{content:"\f15b"}.x-tree-node-el.unpublished .tree-resource:before{font-weight:400}.tree-resource.tree-static-resource:before{content:"\f15c"}.tree-resource.tree-weblink:before{content:"\f0c1"}.x-tree-node-el.unpublished .tree-resource.tree-weblink:before{font-weight:900}.tree-resource.tree-symlink:before{content:"\f0c5"}.tree-resource.icon-folder:before,.tree-resource.parent-resource:before{content:"\f07b"}.x-tree-node-expanded .tree-resource.icon-folder:before,.x-tree-node-expanded .tree-resource.parent-resource:before{content:"\f07c"}.tree-resource.locked-resource:before{content:"\f023"!important}.x-tree-node-el.unpublished .tree-resource.locked-resource:before{font-weight:900}.ext-ie .x-tree-node-el input{height:15px;width:15px}.x-tree-root-ct{border-radius:0;overflow:hidden;padding:0!important}.x-tree-root-node{margin:0}.x-dd-drag-ghost a,.x-dd-drag-ghost a span,.x-tree-node,.x-tree-node a,.x-tree-node a span{color:#383838}.x-tree-node .x-tree-node-disabled a span{color:#b7b7b7}.x-tree-node div.x-tree-drag-insert-below{border-bottom-color:#686868}.x-tree-node div.x-tree-drag-insert-above{border-top-color:#686868}.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below a{border-bottom-color:#686868}.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above a{border-top-color:#686868}.x-tree-node .x-tree-drag-append a span{background-color:#dfdfdf;border-color:#e4e4e4}.x-tree-drop-ok-append .x-dd-drop-icon{background-image:url(../images/modx-theme/tree/drop-add.gif)}.x-tree-drop-ok-above .x-dd-drop-icon{background-image:url(../images/modx-theme/tree/drop-over.gif)}.x-tree-drop-ok-below .x-dd-drop-icon{background-image:url(../images/modx-theme/tree/drop-under.gif)}.x-tree-drop-ok-between .x-dd-drop-icon{background-image:url(../images/modx-theme/tree/drop-between.gif)}#modx-leftbar-header{align-items:center;box-sizing:border-box;color:#53595f;display:flex;height:57px;justify-content:left;padding:.67rem 1rem}#modx-leftbar-header img{max-height:100%;max-width:33%}#modx-leftbar-header a{color:#53595f;font:normal 25px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:16px;text-decoration:none}#modx-leftbar-header a:focus,#modx-leftbar-header a:hover{color:#234368}#modx-leftbar-header a:after{content:"\f06e";font-size:14px;opacity:.5;padding:5px}#modx-leftbar-header img+a{padding-left:.67rem}#modx-leftbar-tabpanel .x-tab-panel-header .x-tab-strip-wrap{margin:0;padding:0}#modx-leftbar-tabpanel .x-tab-panel-header .x-tab-strip{display:flex;width:100%}#modx-leftbar-tabpanel .x-tab-panel-header .x-tab-strip li{box-sizing:border-box;flex-grow:1;float:none;margin-left:0;text-align:center}#modx-leftbar-tabpanel .x-tab-panel-header .x-tab-strip li#modx-leftbar-tabpanel__modx-trash-link{border-right:none}#modx-leftbar-tabpanel .x-tab-panel-header .x-tab-strip li:hover{color:#234368}#modx-leftbar-tabpanel .x-tab-panel-header .x-tab-strip li.x-tab-strip-active{background:#f1f1f1}#modx-leftbar-tabpanel .x-tab-panel-header .x-tab-strip li.x-tab-strip-active:after{box-shadow:none}#modx-leftbar-tabpanel .x-tab-panel-header .x-tab-strip li.x-tab-strip-active:before{background:#0000}#modx-leftbar-tabpanel .x-tab-panel-header .x-tab-strip .x-clear,#modx-leftbar-tabpanel .x-tab-panel-header .x-tab-strip .x-tab-edge{display:none}#modx-leftbar-tabpanel__modx-trash-link .icon{opacity:.5}#modx-leftbar-tabpanel__modx-trash-link.active .icon{opacity:1}#modx-leftbar-tabpanel__modx-trash-link.active:hover .icon{color:#cf1124}.modx-browser-rte{background:#fff}.modx-browser-tree{background:#fff;border-radius:3px}.modx-browser-rte .modx-browser-tree,.x-window .modx-browser-tree{border-radius:0;border-right:1px solid #e4e4e4;box-shadow:none}.modx-browser-view-ct{background:#fff;border-radius:3px;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.modx-browser-rte .modx-browser-view-ct,.x-window .modx-browser-view-ct{border-radius:0;box-shadow:none}.modx-browser-thumb-wrap{cursor:pointer;float:left;margin:5px;overflow:hidden;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.modx-browser-thumb-wrap.x-view-over .modx-browser-placeholder{color:#515151}.modx-browser-thumb-wrap.x-view-over .modx-browser-thumb{border:1px dotted #515151}.modx-browser-thumb-wrap.x-view-selected .modx-browser-placeholder{color:#234368}.modx-browser-thumb-wrap.x-view-selected .modx-browser-thumb{border:1px solid #234368}.modx-browser-thumb{background:#fff;border:1px solid #e4e4e4;height:100px;line-height:100px;padding:5px;width:100px}.modx-browser-thumb img{background-color:#ccc;background-image:url(../images/modx-theme/transparency-pattern.png);max-width:100%;vertical-align:middle}.modx-browser-placeholder{color:#dcdcdc;font-size:14px}.details .modx-browser-placeholder{align-items:center;display:flex;font-size:24px;font-weight:700;height:100px;justify-content:center;overflow:hidden;width:100%}.modx-browser-list-item{padding:0 5px}.modx-browser-list-item>span{background-position:0!important;border-bottom:1px solid #e4e4e4;clear:both;display:block;min-height:16px;padding:5px 0 5px 20px;position:relative}.modx-browser-list-item>span:before{font-size:14px;left:2px;position:absolute}.modx-browser-list-item>span span{display:inline-block;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.modx-browser-list-item>span span.file-size,.modx-browser-list-item>span span.image-size{float:right;width:13%}.modx-browser-list-item.x-view-over>span{background:#fbfbfb}.modx-browser-list-item.x-view-selected>span{background:#fbfbfb;color:#234368}.modx-browser-view-ct .loading-indicator{background-position:0;background-repeat:no-repeat;font-size:11px;margin:10px;padding-left:20px}.modx-browser-pathbbar table,.modx-browser-pathbbar tbody,.modx-browser-pathbbar td,.modx-browser-pathbbar tr{display:block}.modx-browser-pathbbar .x-toolbar-left .x-toolbar-left-row td.x-toolbar-cell{position:relative}.modx-browser-pathbbar .x-toolbar-left .x-toolbar-left-row td.x-toolbar-cell:before{content:"\f328";filter:alpha(opacity=60);font-size:14px;left:0;opacity:.6;position:absolute;text-align:center;top:50%;width:30px}.modx-browser-pathbbar .x-toolbar-left .x-toolbar-left-row .modx-browser-filepath{background:#0000;border:0;border-radius:0;border-top:1px solid #e4e4e4;box-sizing:border-box;height:32px!important;margin:0!important;padding-left:30px;width:100%}.modx-browser-details-ct{background:#fff;border-radius:3px}.modx-browser-rte .modx-browser-details-ct,.x-window .modx-browser-details-ct{border-left:1px solid #e4e4e4;border-radius:0;box-shadow:none}.modx-browser-detail-thumb{color:#000;cursor:default;padding:5px;position:relative}.modx-browser-detail-thumb.preview{cursor:pointer}.modx-browser-detail-thumb.preview:before{content:"\f002";filter:alpha(opacity=0);font-size:56px;left:0;margin-top:-28px;opacity:0;position:absolute;text-align:center;text-shadow:0 0 10px #0003;top:50%;transition:opacity .25s;width:100%}.modx-browser-detail-thumb.preview:hover:before{filter:alpha(opacity=60);opacity:.6}.modx-browser-detail-thumb img{background-color:#ccc;background-image:url(../images/modx-theme/transparency-pattern.png);display:block;height:auto;margin:0 auto;max-width:100%;width:100%}.modx-browser-details-info{border-top:1px solid #e4e4e4;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;padding:15px;text-align:left}.modx-browser-details-info b{color:#53595f;display:block;margin-bottom:2px}.modx-browser-details-info span{display:block;margin-bottom:10px}.modx-browser-fullview{text-align:center}.modx-browser-fullview img{background-color:#ccc;background-image:url(../images/modx-theme/transparency-pattern.png);display:block;height:auto;margin:0 auto;max-width:100%;width:100%}@media screen and (max-width:960px){.modx-browser{max-height:100%!important;overflow-y:scroll;top:15px!important}.modx-browser-panel{background-color:#fff!important;margin:15px 0!important;min-height:700px;width:100%!important}.modx-browser-tree,.modx-browser-view-ct{max-width:35%!important;width:35%!important}.modx-browser-details-ct,.modx-browser-tree,.modx-browser-view-ct{display:inline-block!important;float:left;left:0!important;padding:0 5px;position:relative!important}.modx-browser-details-ct{max-width:20%!important;width:20%!important}.modx-browser-details-ct *,.modx-browser-tree *,.modx-browser-view-ct *{font-size:12px!important}.modx-browser-details-ct input,.modx-browser-tree input,.modx-browser-view-ct input{padding:5px!important}.modx-browser-tree .x-toolbar-ct tbody tr td{display:table-cell}.modx-browser-view-ct .x-panel-body,.modx-browser-view-ct .x-panel-tbar,.modx-browser-view-ct .x-panel-tbar-noheader,.modx-browser-view-ct .x-panel-tbar .x-toolbar,.modx-browser .x-panel-tbar-noheader,.modx-browser .x-toolbar{width:100%!important}.modx-browser-view-ct .x-panel-tbar .x-toolbar-cell label{line-height:2.2}.modx-browser-thumb-wrap{margin:5px;padding:5px;width:24%}.modx-browser-thumb{height:25px;line-height:25px;max-width:100%;overflow:hidden;padding:0}.modx-browser-thumb img{max-width:100%}.modx-browser-placeholder{height:50px}.modx-browser-details-info{padding:5px}}.x-window{-webkit-backface-visibility:hidden;border-radius:3px;box-shadow:0 0 15px 0 #0003;filter:alpha(opacity=0);opacity:0;overflow:visible;transform:scale(1) translateZ(0);transition:opacity .25s ease-in-out,transform .25s ease-in-out}.x-window.anim-ready{transform:scale(.7) translateZ(0)}.x-window.zoom-in{filter:alpha(opacity=100);opacity:1;transform:scale(1) translateZ(0)}.x-window.zoom-out{filter:alpha(opacity=0);opacity:0;transform:scale(1.3) translateZ(0)}.ext-ie8 .x-window.x-window-dlg{filter:alpha(opacity=100)}.x-window .x-window-tl,.x-window .x-window-tr{padding:0}.x-window .x-window-tc{z-index:1}.x-window .x-window-tc .x-window-header{background-color:#f4f4f4;border-bottom:1px solid #f4f4f4;border-radius:3px 3px 0 0;color:#515151;font:normal 13px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-weight:700;padding:8px;text-align:center}.x-window .x-window-tc .x-window-header-text{padding-left:24px}.x-window.x-panel-collapsed .x-window-tl{border-bottom:1px solid #dcdcdc}.x-window.x-panel-collapsed .x-window-header{border-radius:3px}.x-window .x-window-bwrap{overflow:visible}.x-window .x-window-bwrap .x-window-ml,.x-window .x-window-bwrap .x-window-mr{padding:0}.x-window .x-window-bwrap .x-window-mc{border:0;padding:0}.x-window .x-window-bwrap .x-window-mc .x-panel-bl,.x-window .x-window-bwrap .x-window-mc .x-panel-mc,.x-window .x-window-bwrap .x-window-mc .x-panel-ml,.x-window .x-window-bwrap .x-window-mc .x-panel-mr,.x-window .x-window-bwrap .x-window-mc .x-panel-tl{background:#0000;border:0;padding:0}.x-window .x-window-body{background-color:#fff!important;border:0;overflow-y:auto;padding:15px}.x-window.modx-window .x-window-body{padding-top:0}.x-window.modx-window.modx-alert .x-window-body,.x-window.modx-window.modx-confirm .x-window-body,.x-window.modx-window.modx-console .x-window-body,.x-window.modx-window .x-window-with-tabs .x-window-body{padding-top:15px}.x-window.modx-window .x-window-tc .x-window-header-text{padding-left:64px}.x-window .x-panel-bwrap{background:#fff;padding:0}.x-window .x-panel-bwrap .x-panel-bwrap{background:#0000;box-shadow:none;overflow:visible;padding:0}.x-window .x-window-with-tabs .x-window-body{background-color:#fbfbfb!important;overflow:visible}.x-window .x-window-with-tabs .x-panel-bwrap{background:#0000;box-shadow:none;overflow:visible;padding:0}.x-window form.x-panel-body:first-of-type{overflow:visible!important}.x-window .modx-tabs .x-tab-panel-header .x-tab-strip-wrap{padding-top:3px}.x-window .modx-tabs .x-tab-panel-header .x-tab-strip-wrap .x-tab-strip{border:0}.x-window .x-tab-panel-bwrap{background:#fff;box-shadow:0 4px 6px #00000026;padding:10px}.x-window .x-tab-panel-bwrap .x-tab-panel-body{overflow-y:auto}.x-window .x-tab-panel-bwrap .x-tab-panel-body .modx-panel .x-panel-bwrap,.x-window .x-window-bl,.x-window .x-window-br{padding:0}.x-window .x-window-bc .x-window-footer{background-color:#fff;border-radius:0 0 3px 3px;border-top:1px solid #fff;box-sizing:border-box;padding:5px 15px 15px;width:100%!important}.x-window.x-window-maximized{margin:0}.x-window.x-window-maximized .x-window-mc,.x-window.x-window-maximized .x-window-tc{padding:0}.x-window.modx-console .modx-console-text{background-color:#fff;border:none;font:12px SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;height:auto!important}.x-window.modx-console .debug{color:#515151}.x-window.modx-console .success{color:#6cb24a}.x-window.modx-console .warn{color:#4a90e2}.x-window.modx-console .error{color:#cf1124}.x-progress-wrap{border:1px solid #6cb24a;width:100%!important}.x-progress-wrap .x-progress-inner{background-color:#fdfefd}.x-progress-wrap .x-progress-bar{background-color:#6cb24a;border:0}.x-progress-wrap .x-progress-text{color:#fff;font-size:11px;font-weight:700}.x-progress-wrap .x-progress-text-back{color:#515151}.ext-el-mask{background-color:#fff;filter:alpha(opacity=0);opacity:0;transition:opacity .25s}.ext-el-mask.fade-in,.x-masked .ext-el-mask{filter:alpha(opacity=50);opacity:.5}.x-masked .ext-el-mask{z-index:9}.ext-mb-icon{display:inline-block;float:left;position:relative;width:40px!important}.ext-mb-icon:before{color:#4a90e2;content:"";font-size:32px;position:absolute;right:0;text-align:left;top:50%;transform:translateY(-50%);width:100%}.ext-mb-icon.ext-mb-info:before{color:#4a90e2;content:"\f05a"}.ext-mb-icon.ext-mb-question:before{color:#4a90e2;content:"\f059"}.ext-mb-icon.ext-mb-warning:before{color:#f0b429;content:"\f071"}.ext-mb-icon.ext-mb-error:before{color:#cf1124;content:"\f057"}.ext-mb-content{display:block;margin-left:0!important}.ext-el-mask-msg{background-color:#fff;border:1px solid #dcdcdc;border-radius:3px;box-shadow:0 4px 6px #00000026;padding:5px;z-index:10}.ext-el-mask-msg div{background-color:initial;border:0;color:#515151;cursor:default;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.ext-el-mask-msg .modx-lockmask div{color:#cf1124}.x-mask-loading div{background-image:url(../images/modx-theme/grid/loading.gif)}.dashboard{display:flex;flex-flow:row wrap;margin:-.5rem 0 0 -1rem!important;padding:0 15px}.dashboard .dashboard-button{background:#fff;border:1px solid #0000;border-radius:3px;display:inline-block;padding:5px 20px;text-decoration:none}.dashboard .dashboard-button-green{background:#6cb24a;border-color:#6cb24a;color:#fff}.dashboard .dashboard-button[disabled]{background-color:#e4e4e4}.dashboard .dashboard-button:not([disabled]):hover{border-color:#e4e4e4}.dashboard .dashboard-block{margin:1rem 0 0 1rem}.dashboard .dashboard-block:not(.headless){background-color:#fff;border-radius:3px}.dashboard .dashboard-block.headless .body{max-height:100%;overflow:visible;padding:0}.dashboard .dashboard-block.quarter{width:calc(25% - 1rem)}.dashboard .dashboard-block.one-third{width:calc(33.33332% - 1rem)}.dashboard .dashboard-block.half{width:calc(50% - 1rem)}.dashboard .dashboard-block.two-thirds{width:calc(66.66668% - 1rem)}.dashboard .dashboard-block.three-quarters{width:calc(75% - 1rem)}.dashboard .dashboard-block.full{width:calc(100% - 1rem)}.dashboard .dashboard-block.double{margin-top:2rem;min-height:250px;width:calc(100% - 1rem)}.dashboard .dashboard-block.double .body{height:100%;max-height:100%}.dashboard .dashboard-block.double .dashboard-buttons{height:100%}.dashboard .dashboard-block.double .dashboard-button{align-items:center}.dashboard .dashboard-block h4{color:#515151;font-size:13px;padding-bottom:2px}.dashboard .dashboard-block em{font-style:italic}.dashboard .dashboard-block strong{font-weight:700}.dashboard .dashboard-block ul{list-style:circle outside;padding:0 0 0 15px}.dashboard .dashboard-block img{max-width:100%}.dashboard .dashboard-block .draggable{cursor:move}.dashboard .dashboard-block .action-buttons{margin-left:auto;margin-right:10px}.dashboard .dashboard-block .action-buttons button{background:#0000;border:none;cursor:pointer;opacity:0}.dashboard .dashboard-block .action-buttons button.hidden{display:none}.dashboard .dashboard-block .body{color:#444;font-size:12px;height:auto;max-height:300px;overflow:auto;padding:10px;position:relative}.dashboard .dashboard-block .body .action-buttons{position:absolute;right:-5px;top:20px}.dashboard .dashboard-block .title-wrapper{align-items:center;border-bottom:1px solid #f0f0f0;display:flex;flex-wrap:nowrap}.dashboard .dashboard-block .title-wrapper .title{zoom:1;background:#fff;border-radius:3px;color:#515151;flex-grow:1;font-size:12px;font-weight:700;margin:0;padding:15px 10px}.dashboard .dashboard-block .actions button{height:10px;width:10px}.dashboard .dashboard-block:focus-within .action-buttons button,.dashboard .dashboard-block:hover .action-buttons button{opacity:1}.dashboard ul.configcheck{list-style-type:none;padding:0}.dashboard ul.configcheck li{background-color:#fbfbfb;margin-bottom:.5em;margin-top:.5em;padding:1em 1.618em}.dashboard ul.configcheck li h5{color:#cf1124}.dashboard ul.configcheck li p{color:#515151}.dashboard .news_article{border-bottom:1px solid #dfdfdf;overflow:hidden;padding:15px 0}.dashboard .news_article h2 a{text-decoration:none}.dashboard .news_article h2{font-size:18px}.dashboard .news_article .date_stamp{float:right;font-size:12px;font-style:italic}.dashboard .configcheck a,.dashboard .news_article a{text-decoration:underline}.dashboard .configcheck a:hover,.dashboard .news_article a:hover{text-decoration:none}.dashboard .table-wrapper{overflow:auto;width:100%}.dashboard .table-wrapper table{border:1px solid #ddd;border-radius:5px;width:100%}.dashboard .table-wrapper table th{border-bottom:2px solid #f0f0f0;font-weight:700;padding:10px;text-align:initial}.dashboard .table-wrapper table td{border-bottom:1px solid #f0f0f0;padding:10px;vertical-align:center;white-space:nowrap}.dashboard .table-wrapper table td .unpublished{color:#999;font-style:italic}.dashboard .table-wrapper table td .deleted{color:#af5a62bf!important;text-decoration:line-through}.dashboard .table-wrapper table tr:last-child td,.dashboard .table-wrapper table tr:last-child td tr:last-child td{border:none}.dashboard .table-wrapper table tr:last-child td tr:last-child td:first-child{border-bottom-left-radius:10px}.dashboard .table-wrapper table tr:last-child td tr:last-child td:last-child{border-bottom-right-radius:10px}.dashboard .widget-footer{border-top:1px solid #f0f0f0;padding-top:10px}.dashboard .widget-footer a{display:block;font-size:14px;padding-bottom:5px;padding-top:5px;text-align:center;text-decoration:none}.dashboard .widget-actions a{border:1px solid #e4e4e4;border-radius:3px;display:inline-block;margin-left:5px;padding:3px 5px;text-decoration:none}.dashboard .widget-actions a:first-child{margin-left:0}.dashboard .widget-actions a:hover{background:#f0f0f0}.dashboard .widget-actions a .icon{display:inline-block;height:12px;text-align:center;width:12px}.dashboard .no-results{color:#999;padding:10px;text-align:center}.dashboard .user-with-avatar{align-items:center;display:flex}.dashboard .user-with-avatar .user-avatar{margin:0 10px}.dashboard .user-with-avatar .user-avatar img{border-radius:50%;width:35px}.dashboard .user-with-avatar .user-name{color:#234368;font-weight:500}.dashboard .user-with-avatar .user-group{color:#999}.dashboard .occurred-date,.dashboard .resource .title{color:#234368;font-weight:500}.dashboard .occurred-time{color:#999}#modx-news-feed-container img{max-width:100%}.dashboard-buttons{display:flex;flex-wrap:wrap;justify-content:center;margin:-1rem 0 0 -1rem;width:calc(100% + 1rem)}.dashboard-buttons .dashboard-button{align-items:center;background-color:#fff;border-radius:3px;color:#53595f;display:flex;flex:1;margin:1rem 0 0 1rem;padding:20px;text-decoration:none}.dashboard-buttons .dashboard-button:hover{color:#000}.dashboard-buttons .dashboard-button:hover .icon{opacity:.7}.dashboard-buttons .dashboard-button-icon{background:#6cb24a33;border:1px solid #6cb24a;border-radius:20px;padding:10px;text-align:center}.dashboard-buttons .dashboard-button-icon .icon{color:#6cb24a;display:block;font-size:16px;font-weight:700;height:16px;text-align:center;width:16px}.dashboard-buttons .dashboard-button-wrapper{padding:0 10px}.dashboard-buttons .dashboard-button-title{font-weight:700}::-webkit-scrollbar,::-webkit-scrollbar-thumb{background-color:initial;border:.25rem solid #0000;border-radius:.5rem;height:1rem;width:1rem}::-webkit-scrollbar-thumb{box-shadow:inset 0 0 0 1rem #556c881a}::-webkit-scrollbar-thumb:hover{box-shadow:inset 0 0 0 1rem #556c8833}::-webkit-resizer,::-webkit-scrollbar-corner{background-color:initial}.updates-widget .updates-title{color:#234368;font-weight:500}.updates-widget .updates-updateable{background:#4a90e2;border-radius:20px;color:#fff;display:inline-block;font-weight:700;padding:2px 8px}.updates-widget .updates-available,.updates-widget .updates-ok{border-radius:3px;color:#fff;font-size:10px;padding:3px 8px;text-transform:uppercase}.updates-widget .updates-ok{background:#6cb24a}.updates-widget .updates-available{background:#cf1124}#modx-panel-system-info .x-form-label-left .x-form-item{padding:0 5px}#modx-panel-system-info .x-form-label-left .x-form-item:nth-child(2n){background:#f0f0f0}#modx-panel-system-info .x-form-label-left .x-form-item .x-form-display-field{padding:7px 0}@media screen and (max-width:960px){.dashboard-buttons .dashboard-button{align-items:center;flex-direction:column;flex-wrap:wrap;text-align:center}.dashboard-buttons .dashboard-button-wrapper{margin-left:0;margin-top:5px}.dashboard .dashboard-block.half,.dashboard .dashboard-block.one-third,.dashboard .dashboard-block.quarter,.dashboard .dashboard-block.two-thirds{width:calc(100% - 1rem)}.dashboard-buttons{flex-wrap:wrap}.dashboard-buttons .dashboard-button{padding:10px}.dashboard-buttons .dashboard-button-wrapper{display:none}}.nobg .x-panel-body{background:#0000;padding-right:1.5em}#managerbuttons{margin-bottom:1em;overflow:hidden;width:100%}#managerbuttons ul:after,#managerbuttons ul:before{content:" ";display:table}#managerbuttons ul:after{clear:both}#managerbuttons ul{*zoom:1;margin:0;width:100%}#managerbuttons ul li{box-sizing:border-box;display:table;float:left;margin:0;padding:0 1%;position:relative;width:20%}#managerbuttons ul li:first-child{padding-left:0}#managerbuttons ul li:last-child{padding-right:0}#managerbuttons ul li a{background-color:#fff;border:1px solid #e4e4e4;border-radius:3px;box-shadow:0 1px 0 #e4e4e4;color:#53595f;display:table-cell;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-weight:700;padding:12px;position:relative;text-align:center;text-decoration:none;vertical-align:middle}#managerbuttons ul li a span{display:block;line-height:1.4}#managerbuttons ul li a span.headline{font-size:12px}#managerbuttons ul li a span.subline{font-weight:400}#managerbuttons ul li a span.icon{display:block;margin:0 auto;padding:0 0 10px;width:auto}#managerbuttons ul li a:hover span.icon{color:#234368}#contactus,#helpBanner{background:#fff;border:1px solid #e4e4e4;box-shadow:0 1px 0 #e4e4e4;box-sizing:border-box;margin:.75em 0 1.75em;padding:18px;width:100%}#contactus h3,#helpBanner h3{margin:0 0 1em}#helpBanner{background-attachment:none;background-image:url(../images/modx-logo-color.svg),none;background-position:97%;background-repeat:no-repeat;background-size:200px;margin-top:1.5em;min-height:112px}#helpBanner #helpLogo{float:right;height:76px;margin-right:1em;width:200px}#contactus{box-sizing:border-box;float:left;width:60%}#contactus form{display:inline}#contactus input[type=email]{box-sizing:border-box;font-size:1.1em;margin-right:4px;padding:.4em;width:70%}#contactus input[type=submit]{border:0;cursor:pointer;font-size:1.1em;padding:6px 10px}#contactus p{color:#132539;margin:1em 0}#contactus form+p{margin:2em 0 0}#contactus a{color:#000;text-decoration:none}#contactus a:hover{text-decoration:underline}#contactus a:hover i{text-decoration:none}#contactus a i{margin:0 15px -6px 0}#mcsignup input.x-btn{padding:10px 15px}.icon.icon-2x{text-align:center;vertical-align:text-bottom;width:22px}#aboutMODX{background:#f0f0f0;box-sizing:border-box;float:left;margin:1em 0 0 2%;min-height:300px;padding:1em;width:38%}#aboutMODX p{line-height:1.6;margin:0 0 1em}#aboutMODX a{color:#234368;margin:-2px -4px;padding:2px 4px}#aboutMODX a:hover{background-color:#234368;color:#fff;text-decoration:none}.trashrow{background-color:#ccc!important}.x-btn-purge-all{color:#cf1124}.x-btn-purge-all:hover{background:#cf1124;box-shadow:0 0 0 1px #cf1124;color:#fff}.x-btn-restore-all{color:#6cb24a}.x-btn-restore-all:hover{background:#6cb24a;box-shadow:0 0 0 1px #6cb24a;color:#fff}#changelog-tab p{margin-bottom:.3rem}#changelog-tab h1{color:#595959}#changelog-tab h2{font-weight:700;margin-top:1rem}#changelog-tab ul{margin-bottom:1rem}#modx-package-browser-details-main p{color:#595959;margin-bottom:.3rem}#modx-package-browser-details-main h1,#modx-package-browser-details-main h2,#modx-package-browser-details-main h3,#modx-package-browser-details-main h4,#modx-package-browser-details-main h5,#modx-package-browser-details-main h6{color:#595959;font-weight:700}#modx-package-browser-details-main h1{font-size:1.2em}#modx-package-browser-details-main h2{font-size:1.15em}#modx-package-browser-details-main h3{font-size:1.1em}#modx-package-browser-details-main h4{font-size:1.05em}#modx-package-browser-details-main h5{font-size:1em}#modx-package-browser-details-main h6{font-size:.95em}#modx-package-browser-details-aside h4{text-align:center}#modx-package-browser-details-aside ul li{margin-bottom:.5em}.ext-webkit :focus-visible{outline:auto!important;outline-offset:.1em}.ext-webkit :focus-visible.x-form-focus{outline:none!important}.ext-webkit .x-form-check-wrap:focus-within:has(:focus-visible) label:before{outline:auto!important;outline-offset:.1em}.skiplinks{height:0;left:-100rem;position:fixed;top:-100rem;width:0;z-index:99999}.skiplinks a:active,.skiplinks a:focus{background-color:#fff;left:0;margin:1rem;padding:1rem;position:fixed;top:0}body{-webkit-font-smoothing:antialiased;color:#000;font:normal 13px/1.4 -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;scrollbar-color:#e1e3e6 #0000}body a{color:#234368}body a:hover{color:#162a42}h2,h3{color:#515151;font:normal 25px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;margin:0 0 8px -1px}h3{font:550 15px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}strong{font-weight:700}em{font-style:italic}hr{background-color:#e4e4e4;border:0;color:#e4e4e4;height:1px;margin:20px 0}.aleft{text-align:left}.aright{text-align:right}.right{float:right}.left{float:left}.clear{clear:left}.bold{font-weight:700}.installed{color:#515151}.not-installed{color:#999;font-style:italic}.yellow{color:#fce588!important}.orange{color:#f0b429!important}.error,.red{color:#cf1124!important}.green{color:#6cb24a!important}.blue{color:#4a90e2!important}.primary{color:#6cb24a!important}.centered{text-align:center}.wait{background:#0000 url(../images/style/wait.gif) no-repeat scroll center 55px;color:#53595f;font-size:15px;font-weight:700;padding:20px 10px 60px}.padding{background-color:#fff;padding:11px}.dashed{border-bottom:1px dashed #90b1b9}.x-form-text,textarea.x-form-field{border-color:#e4e4e4}#modx-content,#modx-leftbar{position:absolute;transition:left .2s ease}#modx-leftbar-tabpanel{transition:all .6s ease}#modx-content{left:370px;right:0;width:calc(100% - 370px);z-index:0}.modx-form p{padding-bottom:10px}.x-layout-mini{left:2px}#modx-resource-content .x-panel-header{margin:0;padding:15px}#modx-resource-content .x-panel-bwrap{border:0}#modx-resource-content .modx-tv .modx-tv-label{clear:none;float:none;padding:15px 0 4px;position:static;width:auto}#modx-content-above .x-panel-bwrap,#modx-content-below .x-panel-bwrap{border:0}.x-tab-panel-header,.x-tab-panel-header .x-tab-strip li{box-sizing:border-box}@media screen and (max-width:960px){.x-viewport{overflow-y:auto}.x-viewport body{height:auto}}#modx-container{background:#f1f1f1;height:100%;width:100%}@media screen and (max-width:960px){#modx-container{height:auto}}@media screen and (max-width:1140px){#modx-page-settings-left,#modx-page-settings-right,#modx-resource-main-left,#modx-resource-main-right{box-sizing:border-box;margin:0 auto 15px;width:100%!important}#modx-page-settings-left .x-panel-body,#modx-page-settings-right .x-panel-body,#modx-resource-main-left .x-panel-body,#modx-resource-main-right .x-panel-body{height:auto!important;max-height:100%!important;max-width:100%!important;width:auto!important}}@media screen and (max-width:960px){#modx-chunk-form .main-wrapper,#modx-panel-plugin .main-wrapper,#modx-snippet-form .main-wrapper,#modx-template-form .main-wrapper,#modx-tv-tabs .main-wrapper{padding:0;width:100%!important}#modx-chunk-form .main-wrapper>.x-panel-bwrap,#modx-panel-plugin .main-wrapper>.x-panel-bwrap,#modx-snippet-form .main-wrapper>.x-panel-bwrap,#modx-template-form .main-wrapper>.x-panel-bwrap,#modx-tv-tabs .main-wrapper>.x-panel-bwrap{padding:1em}#modx-resource-main-right{margin:15px auto 0}.x-toolbar-ct,.x-toolbar-ct tbody,.x-toolbar-ct tbody tr{display:block}.x-toolbar-ct tbody tr td{display:block;width:100%}.x-toolbar-ct tbody tr td table{width:100%}.x-toolbar-ct tbody tr td table .x-form-field-wrap{margin-left:0!important;margin-right:0!important;width:100%!important}.x-toolbar-ct tbody tr td table .x-btn,.x-toolbar-ct tbody tr td table .x-form-text{box-sizing:border-box;margin-left:0!important;margin-right:0!important;width:100%!important}.x-column{float:none;margin-left:0!important;margin-right:0!important;width:100%!important}#modx-tree-panel-usergroup .main-wrapper{display:inline-block;float:left;max-width:100%;position:relative;width:100%!important}.x-window{left:.5em!important;max-width:100%!important;right:.5em!important;width:auto!important}.x-window .x-window-body{box-sizing:border-box!important;height:auto!important;width:100%!important}.x-window .x-form-field-wrap{width:auto!important}.x-window input{box-sizing:border-box;height:auto!important;width:100%!important}}#modx-template-form .main-wrapper input{max-width:100%!important}@media screen and (max-width:960px){.x-column-inner>.x-column~.x-column{margin-left:0}#modx-import-base-path,.x-form-item label.x-form-item-label[for=modx-import-allowed-extensions],.x-form-item label.x-form-item-label[for=modx-import-base-path],.x-form-item label.x-form-item-label[for=modx-import-element],.x-form-item label.x-form-item-label[for=modx-import-parent],.x-form-item label.x-form-item-label[for=modx-import-resource-class]{float:none;width:auto!important}}#modx-import-allowed-extensions,#modx-import-base-path,#modx-import-element,#modx-import-resource-class{box-sizing:border-box;height:auto;width:100%!important}@media screen and (max-width:960px){#x-form-el-modx-import-allowed-extensions,#x-form-el-modx-import-base-path,#x-form-el-modx-import-element,#x-form-el-modx-import-resource-class{padding-left:0!important;width:100%!important}}.x-panel.drag-n-drop{z-index:0}.x-panel.drag-n-drop:before{background:#0000 url(../images/restyle/dragndrop.svg) no-repeat 50%;background-size:50% 50%;bottom:0;content:" ";display:block;left:0;opacity:.1;position:absolute;right:0;top:0;z-index:-5}.x-panel.drag-n-drop>.x-panel-bwrap,.x-panel.drag-over .x-form-field{background:#0000}.x-panel.drag-over:after{background:#6cb24a;border:5px solid #6cb24a;bottom:0;content:"";display:block;left:0;opacity:.1;position:absolute;right:0;top:0}#modx-panel-packages.drag-n-drop:before{background:#0000 url(../images/restyle/dragndrop.svg) no-repeat top;background-size:50% 30%;z-index:0}.x-panel-header{background:none;border:none;font-size:16px;margin:0;padding:0 0 10px}#modx-resource-tabs .x-panel-header{border-bottom:1px solid #e4e4e4;color:#515151;display:flex;margin-bottom:5px}#modx-resource-tabs .x-panel-header .x-panel-header-text{flex:1;font-size:14px;order:0}#modx-resource-tabs .x-panel-header .x-tool.x-tool-toggle{margin-left:auto;order:1}#modx-resource-main-left .x-panel-header{border-bottom:0;position:absolute;right:15px;z-index:9}#modx-resource-main-left .x-panel-header .x-panel-header-text{display:none}#modx-resource-main-left .x-panel-animated .x-panel-header,#modx-resource-main-left .x-panel-collapsed .x-panel-header{padding-top:15px!important;position:relative;right:0;width:100%}#modx-resource-main-left .x-panel-animated .x-panel-header .x-panel-header-text,#modx-resource-main-left .x-panel-collapsed .x-panel-header .x-panel-header-text{display:block}#modx-resource-tabs .x-panel-collapsed .x-panel-header{border-color:#0000;margin-bottom:0;padding:0}.x-small-editor .x-form-field{font-size:12px!important}.x-small-editor .x-form-num-field{text-align:left}.grid-row-inactive{color:#999!important}a.x-grid-link{color:#234368;text-decoration:underline}a.x-grid-link:focus,a.x-grid-link:hover{text-decoration:none}.x-editable-column{cursor:default}.x-editable-column:not(.editor-disabled){cursor:pointer}.x-editable-column:not(.editor-disabled):focus,.x-editable-column:not(.editor-disabled):hover{color:#234368}.x-editable-column:not(.editor-disabled):focus>div:after,.x-editable-column:not(.editor-disabled):hover>div:after{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:auto;color:#234368;content:"\f304";display:inline-block;font-family:Font Awesome\ 5 Free,Font Awesome\ 5 Brands;font-style:normal;font-variant:normal;font-weight:900;margin:0 .5em}.x-editable-column.locked{cursor:default}.x-editable-column.locked:focus>div:after,.x-editable-column.locked:hover>div:after{color:#6b7c90;content:"\f023"}.x-grid-buttons{text-align:center}.x-grid-buttons li{cursor:pointer;display:inline-block;font-size:1.1em;line-height:.7;margin-right:10px}.x-grid-buttons li:last-child{margin-right:0}.x-grid-empty .error-with-icon{color:#cf1124;font:normal 12px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;line-height:1.3;padding:1rem}.x-grid-empty .error-with-icon:before{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:auto;content:"\f071";display:inline-block;font-family:Font Awesome\ 5 Free,Font Awesome\ 5 Brands;font-style:normal;font-variant:normal;font-weight:900;margin-right:.5rem}.x-grid-empty .error-with-icon *{color:#09121c;line-height:1.6;text-align:left}.x-grid-empty .error-with-icon .error-status-info{margin:.25rem 0;text-align:center}.x-grid-empty .error-with-icon code{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:11px;white-space:pre-line}.xdebug-error{border:none}.xdebug-error tbody td,.xdebug-error tbody th{border-color:#dcdcdc;border-style:solid none none!important;border-width:thin!important;padding:.1rem .25rem}.xdebug-error tbody th{color:#000!important;font-weight:700}.xdebug-error tbody th:first{border-top:none!important}.xdebug-error tbody th[colspan="5"]{border-color:#fff;border-width:thick!important;padding:.5rem 2rem;text-align:center!important}.xdebug-error tbody th[bgcolor^="#f57"]{background:#fdf0f1;font-weight:400}.xdebug-error tbody th[bgcolor^="#e9b"]{background:#234368;color:#fff!important}.xdebug-error tbody td{background-color:#fff}.xdebug-error tbody tr:nth-child(2n) td{background-color:#f0f0f0}.modx-page-header,.modx-page-header div{background-color:initial!important}#modx-panel-trash .modx-page-header,#modx-panel-trash .modx-page-header div,#modx-panel-welcome .modx-page-header,#modx-panel-welcome .modx-page-header div{margin:1rem!important}@media screen and (min-width:961px){#modx-content>.x-panel-bwrap>.x-panel-body .modx-page-header{box-sizing:border-box;margin-top:1.25rem}html[dir=rtl] #modx-content>.x-panel-bwrap>.x-panel-body .modx-page-header{margin-top:4rem}#modx-content>.x-panel-bwrap>.x-panel-body .modx-page-header+div{margin:1rem}#modx-content>.x-panel-bwrap>.x-panel-body>.x-panel{margin:0}#modx-content>.x-panel-bwrap>.x-panel-body>.x-panel .modx-header-breadcrumbs{box-sizing:border-box;font-size:18px;font-weight:700;margin-top:1.25rem;padding:0 15px}html[dir=rtl] #modx-content>.x-panel-bwrap>.x-panel-body>.x-panel .modx-header-breadcrumbs{margin-top:4rem}#modx-content>.x-panel-bwrap>.x-panel-body>.x-panel .modx-header-breadcrumbs+div{margin:1rem}#modx-content>.x-panel-bwrap>.x-panel-body>.x-panel .modx-header-breadcrumbs{width:100%!important}}#modx-content form.x-panel-body{background-color:initial!important}@media screen and (max-width:960px){#modx-content{left:auto!important;position:relative;top:auto!important;width:auto!important}}#modx-content .modx_error{margin:26px 0 0 15px;width:95%}#modx-content .modx_error h2{margin:0 0 14px}#modx-content .modx_error .error_container{background:#f99;border:2px solid #cf1124;border-bottom-left-radius:3px;border-bottom-right-radius:3px;border-top-left-radius:3px;border-top-right-radius:3px;padding:10px}#modx-content .modx_error .error_container ul{list-style:none;margin-left:0;margin-top:6px}#modx-content .modx_error .error_container ul li{margin-bottom:6px}#modx-content .modx_error .error_container ul li:last-child{margin-bottom:0}#modx-content .modx_error .error_container.multiple p:first-child{font-size:1.4em;font-weight:700}@media screen and (max-width:960px){#modx-content .x-panel-body{height:auto!important;max-height:100%!important;max-width:100%!important;width:auto!important}}#modx-mainpanel{height:100%;position:relative}.x-portal .x-panel-dd-spacer,.x-portlet{margin-bottom:10px}.x-portlet .x-panel-ml{padding-left:2px}.x-portlet .x-panel-mr{padding-right:2px}.x-portlet .x-panel-bl{padding-left:2px}.x-portlet .x-panel-br{padding-right:2px}.x-portlet .x-panel-body{background:#fff}.x-portlet .x-panel-mc{padding-top:2px}.x-portlet .x-panel-bc .x-panel-footer{padding-bottom:2px}.x-portlet .x-panel-nofooter .x-panel-bc{height:2px}.x-portal-space h2{border-bottom:1px solid #d4d4d4;margin:0 0 8px;padding:0 0 2px}.x-column-tree .x-panel-header{border-bottom-width:0;padding:3px 0 0}.x-column-tree .x-panel-header .x-panel-header-text{margin-left:3px}.x-column-tree .x-tree-node,.x-column-tree .x-tree-node-el{zoom:1}.x-column-tree .x-tree-selected{background:#d9e8fb}.x-column-tree .x-tree-node a{line-height:18px;vertical-align:middle}.x-column-tree .x-tree-node .x-tree-selected a span{background:#0000;color:#515151}.x-tree-col{zoom:1;float:left;overflow:hidden;padding:0 1px}.x-tree-col-text,.x-tree-hd-text{color:#515151;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;overflow:hidden;padding:3px 3px 3px 5px;text-overflow:ellipsis;white-space:nowrap}.x-tree-headers{zoom:1;cursor:default;margin-top:3px}.x-tree-hd{border-left:1px solid #eee;border-right:1px solid #d0d0d0;float:left;overflow:hidden}.ux-row-action-cell .x-grid3-cell-inner{padding:1px 0 0}.ext-ie .ux-row-action-item{width:16px}.ext-ie .ux-row-action-text{width:auto}.ux-row-action-item span{background:#0000 url(../images/style/go-next.png) no-repeat scroll 1px 4px;display:inline!important;line-height:24px;margin:0 5px;padding:5px 5px 5px 22px;vertical-align:middle}.icon-uninstall span{background:url(../images/style/delete.png) no-repeat scroll 1px 4px #0000}.package-details span{background:url(../images/style/info.png) no-repeat scroll 1px 4px #0000}.package-download span{background:url(../images/style/download.png) no-repeat scroll 1px 4px #0000}.package-installed span{background:url(../images/style/accept.png) no-repeat scroll 1px 4px #0000}.ext-ie .ux-row-action-item span{width:auto}.x-grid-group-hd div{height:16px;position:relative}.ux-grow-action-item{background-position:0 50%!important;background-repeat:no-repeat;cursor:pointer;float:left;margin:0;min-width:16px;padding:0!important}.ext-ie .ux-grow-action-item{width:16px}.ux-action-right{float:right;margin:0 3px 0 2px;padding:0!important}.ux-grow-action-text{background:#0000 none!important;float:left;margin:0!important;padding:0!important}.ux-row-action-item:hover{background:#dfdfdf;background:linear-gradient(center bottom,#dfdfdf 0,#fff);border:1px solid #9caf78;color:#636f4c!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=$white,endColorstr=$alto,GradientType=0)}.ux-row-action-item:active{background-color:#fff;background-image:none;border-color:#cfcfcf silver #aaa;box-shadow:inset 0 0 3px #aaa;margin:2px 1px 0}.ux-row-action-item:active span{text-shadow:none}.ux-row-action-item{background:linear-gradient(center bottom,#dcdcdc 0,#fcfcfc);background:url(/manager/templates/default/images/modx-theme/form/button-bg.png) repeat-x scroll 0 bottom #dcdcdc;border-collapse:initial;border-color:#cacaca silver #aaa;border-radius:3px;border-style:solid;border-width:1px;box-shadow:0 0 1px #0003;color:#444;cursor:pointer;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#fcfcfc,endColorstr=#dcdcdc,GradientType=0);float:left;font-weight:700;margin:2px 1px 0;overflow:hidden;padding:3px;position:relative;text-shadow:0 1px 0 #fafafa}.x-tree-checkbox{background:url(../../../assets/ext3/resources/images/default/form/checkbox.gif) no-repeat 0 0;height:13px;margin:0 1px;vertical-align:middle;width:13px}.x-tree-checkbox-over .x-tree-checkbox{background-position:-13px 0}.x-tree-checkbox-down .x-tree-checkbox{background-position:-26px 0}.x-tree-node-disabled .x-tree-checkbox{background-position:-39px 0}.x-tree-node-checked{background-position:0 -13px}.x-tree-checkbox-over .x-tree-node-checked{background-position:-13px -13px}.x-tree-checkbox-down .x-tree-node-checked{background-position:-26px -13px}.x-tree-node-disabled .x-tree-node-checked{background-position:-39px -13px}.x-tree-node-grayed{background-position:0 -26px}.x-tree-checkbox-over .x-tree-node-grayed{background-position:-13px -26px}.x-tree-checkbox-down .x-tree-node-grayed{background-position:-26px -26px}.x-tree-node-disabled .x-tree-node-grayed{background-position:-39px -26px}.x-tree-branch-unchecked .x-tree-checkbox,.x-tree-branch-unchecked .x-tree-node-checked,.x-tree-branch-unchecked .x-tree-node-grayed{background-position:0 0}.x-tree-branch-unchecked .x-tree-checkbox-over .x-tree-checkbox,.x-tree-branch-unchecked .x-tree-checkbox-over .x-tree-node-checked,.x-tree-branch-unchecked .x-tree-checkbox-over .x-tree-node-grayed{background-position:-13px 0}.x-tree-branch-unchecked .x-tree-checkbox-down .x-tree-checkbox,.x-tree-branch-unchecked .x-tree-checkbox-down .x-tree-node-checked,.x-tree-branch-unchecked .x-tree-checkbox-down .x-tree-node-grayed{background-position:-26px 0}.x-tree-branch-unchecked .x-tree-node-disabled .x-tree-checkbox,.x-tree-branch-unchecked .x-tree-node-disabled .x-tree-node-checked,.x-tree-branch-unchecked .x-tree-node-disabled .x-tree-node-grayed{background-position:-39px 0}.x-tree-branch-checked .x-tree-checkbox,.x-tree-branch-checked .x-tree-node-checked,.x-tree-branch-checked .x-tree-node-grayed{background-position:0 -13px}.x-tree-branch-checked .x-tree-checkbox-over .x-tree-checkbox,.x-tree-branch-checked .x-tree-checkbox-over .x-tree-node-checked,.x-tree-branch-checked .x-tree-checkbox-over .x-tree-node-grayed{background-position:-13px -13px}.x-tree-branch-checked .x-tree-checkbox-down .x-tree-checkbox,.x-tree-branch-checked .x-tree-checkbox-down .x-tree-node-checked,.x-tree-branch-checked .x-tree-checkbox-down .x-tree-node-grayed{background-position:-26px -13px}.x-tree-branch-checked .x-tree-node-disabled .x-tree-checkbox,.x-tree-branch-checked .x-tree-node-disabled .x-tree-node-checked,.x-tree-branch-checked .x-tree-node-disabled .x-tree-node-grayed{background-position:-39px -13px}.x-rbtn button{background-color:initial;background-position:50%;background-repeat:no-repeat;border:0;cursor:pointer;font-size:1px;height:16px;line-height:1px;margin:0;-moz-outline:0 none;outline:0 none;padding:0;width:24px}.x-rbtn{table-layout:fixed}.x-rbtn td{background-image:url(../images/restyle/icons/rbtn.gif);background-repeat:no-repeat;border:0;height:21px;padding:0;vertical-align:middle;width:24px}.x-rbtn td.x-rbtn-first{background-position:0 0}.x-rbtn td.x-rbtn-item{background-position:0 -42px}.x-rbtn td.x-rbtn-last{background-position:right -21px}.x-rbtn td.x-rbtn-first-active{background-position:0 -63px}.x-rbtn td.x-rbtn-item-active{background-position:0 -105px}.x-rbtn td.x-rbtn-last-active{background-position:right -84px}.ux-up-item{background-color:#f0f0f0;background-image:url(../../../assets/modext/util/filetree/img/white_bg.png);background-repeat:no-repeat;cursor:default;height:17px;line-height:17px;margin-bottom:1px;position:relative}.ux-up-icon-file{float:left;height:16px;margin-right:4px;vertical-align:-3px;width:16px}.ux-up-indicator{background-color:#ff0;filter:alpha(opacity=40);height:17px;opacity:.4;position:absolute;width:40px}.ux-up-icon-state{cursor:pointer;float:right;margin-right:2px;width:16px;z-index:-1}.ux-up-icon-queued{background-image:url(../../../assets/modext/util/filetree/img/silk/icons/page_white_get.png)}.ux-up-icon-uploading{background-image:url(../../../../ext2/resources/images/default/grid/wait.gif)}.ux-up-icon-done{background-image:url(../../../assets/modext/util/filetree/img/silk/icons/accept.png)}.ux-up-icon-failed{background-image:url(../../../assets/modext/util/filetree/img/silk/icons/error.png)}.ux-up-icon-stopped{background-image:url(../../../assets/modext/util/filetree/img/silk/icons/stop.png)}.ux-up-text{float:left}.ux-ftm-nodename{color:#515151;cursor:default!important;font-weight:700}.ux-icon-combo-icon{background-position:0 50%;background-repeat:no-repeat;height:14px;width:18px}.ux-icon-combo-input{padding-left:25px}.x-form-field-wrap .ux-icon-combo-icon{left:5px;top:3px}.ux-icon-combo-item{background-position:3px 50%!important;background-repeat:no-repeat!important;padding-left:24px!important}.modx-status-msg{align-items:center;background:#6cb24a;border-radius:3px;bottom:20px;box-sizing:border-box;color:#fff;-moz-column-gap:12px;column-gap:12px;display:flex;max-width:360px;padding:15px;position:fixed;right:15px;width:25%;z-index:20000}@media screen and (max-width:960px){.modx-status-msg{max-width:100%}}.modx-status-msg:before{background:#fff;border-radius:50%;color:#6cb24a;content:"\f00c";font-size:16px;height:38px;line-height:38px;text-align:center;width:38px}.modx-status-msg h3,.modx-status-msg span{font-size:14px}.modx-status-msg h3{color:#fff;margin:0}.modx-status-msg .has-position-center-center{bottom:auto;left:0;margin-left:auto;margin-right:auto;right:0;top:50%;transform:translateY(-50%)}.modx-status-msg .has-position-center-top{bottom:auto;left:0;margin-left:auto;margin-right:auto;right:0;top:15px}.modx-status-msg .has-position-right-top{bottom:auto;left:auto;right:15px;top:15px}@media screen and (max-width:960px){.modx-status-msg,.modx-status-msg .has-position-center-center,.modx-status-msg .has-position-center-top,.modx-status-msg .has-position-right-top{border-radius:0;bottom:0;left:0;right:0;top:auto;width:100%}}iframe[classname=x-hidden]{visibility:hidden}html[dir=rtl] .x-hide-offsets,html[dir=rtl] .x-hiden{left:unset;right:-9999px}.ext-ux-uploaddialog-addbtn{background:url(../images/restyle/fileup/file-add.gif) no-repeat 0!important}.ext-ux-uploaddialog-removebtn{background:url(../images/restyle/fileup/file-remove.gif) no-repeat 0!important}.ext-ux-uploaddialog-resetbtn{background:url(../images/restyle/fileup/reset.gif) no-repeat 0!important}.ext-ux-uploaddialog-uploadstartbtn{background:url(../images/restyle/fileup/upload-start.gif) no-repeat 0!important}.ext-ux-uploaddialog-uploadstopbtn{background:url(../images/restyle/fileup/upload-stop.gif) no-repeat 0!important}.ext-ux-uploaddialog-indicator-stoped{background:url(../images/restyle/fileup/done.gif) no-repeat 50%;height:16px;width:16px}.ext-ux-uploaddialog-indicator-processing{background:url(../images/restyle/fileup/loading.gif) no-repeat 50%;height:16px;width:16px}.ext-ux-uploaddialog-state{background-position:50%;background-repeat:no-repeat;text-align:center}.ext-ux-uploaddialog-state-0{background-image:url(../images/restyle/fileup/uncheck.gif)}.ext-ux-uploaddialog-state-1{background-image:url(../images/restyle/fileup/check.gif)}.ext-ux-uploaddialog-state-2{background-image:url(../images/restyle/fileup/failed.gif)}.ext-ux-uploaddialog-state-3{background-image:url(../images/restyle/fileup/file-uploading.gif)}.tq-treegrid .tq-treegrid-col{border:none}.tq-treegrid .tq-treegrid-icons{float:left}.tq-treegrid .x-tree-node-el{line-height:13px;padding:1px 3px 1px 5px}.tq-treegrid .tq-treegrid-static .x-tree-ec-icon{display:none}.tq-treegrid .tq-treegrid-static .x-tree-node-el{cursor:default}.modx-tree-load-msg{color:#000;font-size:.9em;line-height:1;padding:3px;white-space:pre-line}#modx-grid-policy-permissions .x-grid3-cell-inner,#modx-grid-policy-permissions .x-grid3-hd-inner,#modx-grid-template-permissions .x-grid3-cell-inner,#modx-grid-template-permissions .x-grid3-hd-inner{white-space:normal}.container{margin:20px 15px}.container,.x-plain-body,.x-plain-bwrap{overflow:visible}.shadowbox,.x-form-label-left{border-radius:3px}.shadowbox .x-form-label-left,.x-form-label-left .x-form-label-left,.x-tab-panel-bwrap .shadowbox,.x-tab-panel-bwrap .x-form-label-left,.x-window .shadowbox,.x-window .x-form-label-left{border-radius:0;box-shadow:none}.panel-desc{border-bottom:1px solid #f0f0f0;border-radius:0;color:#53595f;line-height:1.5;padding:15px!important}.x-window .panel-desc{margin-bottom:15px;margin-top:0}.panel-desc .x-panel-bwrap{background-color:initial!important}.with-title .panel-desc{margin:0}.panel-desc p{padding:0}.main-wrapper{background-color:#fff;padding:15px}.with-title .main-wrapper{padding:0 15px 10px}.left-col{padding-right:15px}.right-col{padding-left:15px}.modx-page-header{color:#53595f;font:normal 20px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;margin:0;order:1;padding:0 15px}@media screen and (max-width:960px){.modx-page-header{font-size:2em;text-align:center;width:100%}}.modx-header-breadcrumbs .breadcrumbs{align-items:baseline;display:flex;flex-wrap:wrap}.modx-header-breadcrumbs .breadcrumbs h2{color:#53595f;font:normal 20px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;margin:0!important;order:1;padding-left:0}@media screen and (max-width:960px){.modx-header-breadcrumbs .breadcrumbs h2{font-size:2em;text-align:center;width:100%}}.modx-header-breadcrumbs ul{align-items:center;display:flex;flex-wrap:wrap;order:0}.modx-header-breadcrumbs ul li{color:#53595f}.modx-header-breadcrumbs ul li,.modx-header-breadcrumbs ul li a{font:normal 18px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.modx-header-breadcrumbs ul li a{text-decoration:none}.modx-header-breadcrumbs ul li a.menu_hidden{font-style:italic}.modx-header-breadcrumbs ul li a.menu_hidden:hover{color:#162a42}.modx-header-breadcrumbs ul li a.not_published{color:#9c9c9c!important}.modx-header-breadcrumbs ul li a.not_published:hover{color:#162a42}.modx-header-breadcrumbs ul li a.deleted{color:#af5a62bf!important;text-decoration:line-through}.modx-header-breadcrumbs ul li a.deleted:hover{color:#162a42}.modx-header-breadcrumbs ul li:after{color:#999;content:"\f054";font-size:12px;padding:0 10px}#modx-abtn-delete{color:#cf1124}#modx-abtn-undelete{color:#6cb24a}#modx-abtn-purge{background-color:#cf1124;color:#fff}#modx-abtn-purge:hover{background-color:#a00d1c}#modx-abtn-help{color:#234368}#modx-resource-tabs .x-tab-panel-bwrap{box-shadow:none}#modx-resource-tabs .x-tab-panel-body,#modx-resource-tabs .x-tab-panel-bwrap{overflow:visible!important}#modx-resource-settings{background:#f1f1f1}#modx-resource-settings #modx-resource-main-left{background:#fff;border-bottom-left-radius:3px;border-bottom-right-radius:3px;border-top-right-radius:3px;padding:15px;position:relative}#modx-resource-settings .x-panel-collapsed{min-height:18px}#modx-resource-settings #modx-resource-main-right .modx-resource-panel{background:#fff;border-radius:3px;padding:15px}#modx-resource-settings #modx-resource-main-right .modx-resource-panel:not(:last-child){margin-bottom:15px}#modx-resource-settings .main-wrapper{background:#0000;padding:0}#modx-resource-settings .x-datetime-wrap table{width:100%}#modx-resource-settings .x-datetime-wrap table td{max-width:50%!important;width:50%!important}#modx-resource-settings .x-datetime-wrap table td input{width:calc(100% - 30px)}#modx-resource-settings .x-datetime-wrap table td:first-child{padding-right:5px!important}#modx-resource-settings .x-datetime-wrap table td:last-child{padding-left:5px!important}#modx-resource-settings .x-datetime-wrap table .x-form-field-trigger-wrap{width:100%!important}.tvs-wrapper{padding:0}#modx-resource-tvs-div{border-top-width:0;visibility:hidden}.modx-permissions-list{color:#777;font-size:12px}.modx-permissions-list-textarea{background-color:initial!important;border:0!important}.info-list.hide-list{display:none}.info-list .header{color:#626262;font:normal 12px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-weight:600}.info-list .header:before{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:auto;color:#517196;content:"\f09c";display:inline-block;font-family:Font Awesome\ 5 Free,Font Awesome\ 5 Brands;font-style:normal;font-variant:normal;font-weight:900;margin:0 .25rem}.info-list .header span{font-weight:400}.info-list ul{border:1px dashed #e4e4e4;border-radius:3px;margin-top:.5rem;padding:.5rem}.info-list ul li{color:#6b6b6b;font:normal 12px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;line-height:1;padding:.15rem 0;word-break:break-word}@media screen and (min-width:641px){.info-list ul{-moz-columns:2;column-count:2;-moz-column-gap:2rem;column-gap:2rem}}.x-window .info-list{margin-top:1rem}.x-grid3 .info-list ul{background-color:#fcfbfb;padding-left:1rem;position:relative}.x-grid3-row-alt .x-grid3 .info-list ul{background-color:#f9faff}.x-grid3 .info-list ul:before{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:auto;background-color:#fff;border-radius:100%;box-shadow:-1px 1px 3px #888;color:#517196;content:"\f09c";display:inline-block;font-family:Font Awesome\ 5 Free,Font Awesome\ 5 Brands;font-size:11px;font-style:normal;font-variant:normal;font-weight:900;height:14px;left:-7px;padding-top:2px;position:absolute;text-align:center;top:-7px;width:14px}.x-grid3 .info-list ul li{font-style:italic}@media screen and (min-width:769px){.x-grid3 .info-list ul{-moz-columns:3;column-count:3}}@media screen and (min-width:1141px){.x-grid3 .info-list ul{-moz-columns:4;column-count:4}}@media screen and (min-width:1401px){.x-grid3 .info-list ul{-moz-columns:5;column-count:5}}.x-selectable,.x-selectable *{-webkit-user-select:text!important;-moz-user-select:text!important;-ms-user-select:text!important;user-select:text!important}#ux-lightbox{left:0;line-height:0;position:absolute;text-align:center;width:100%;z-index:15000}#ux-lightbox img{height:auto;width:auto}#ux-lightbox a img{border:none}#ux-lightbox-outerImageContainer{background-color:#fff;height:250px;margin:0 auto;position:relative;width:250px}#ux-lightbox-imageContainer{padding:10px}#ux-lightbox-loading{background:url(../images/style/loading.gif) no-repeat scroll center 15% #0000;height:25%;left:0;line-height:0;position:absolute;text-align:center;top:40%;width:100%}#ux-lightbox-hoverNav{height:100%;left:0;position:absolute;top:0;width:100%;z-index:10}#ux-lightbox-hoverNav a{outline:medium none}#ux-lightbox-imageContainer>#ux-lightbox-hoverNav{left:0}#ux-lightbox-navNext,#ux-lightbox-navPrev{display:block;height:100%;width:49%}#ux-lightbox-navPrev{float:left;left:0}#ux-lightbox-navPrev:hover,#ux-lightbox-navPrev:visited:hover{background:#0000 url(images/lb-prev.png) no-repeat scroll left 33%}#ux-lightbox-navNext{float:right;right:0}#ux-lightbox-navNext:hover,#ux-lightbox-navNext:visited:hover{background:#0000 url(images/lb-next.png) no-repeat scroll right 33%}#ux-lightbox-outerDataContainer{margin:0 auto;width:100%}#ux-lightbox-dataContainer{background-color:#fff;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:10px;overflow:auto}#ux-lightbox-data{color:#666;padding:0 10px}#ux-lightbox-data #ux-lightbox-details{float:left;text-align:left;width:80%}#ux-lightbox-data #ux-lightbox-caption{font-weight:700}#ux-lightbox-data #ux-lightbox-imageNumber{clear:left;display:block;padding-bottom:1em}#ux-lightbox-data #ux-lightbox-navClose{background:#0000 url(../images/style/close.png) no-repeat scroll 0 0;float:right;height:16px;outline:medium none;padding-bottom:.7em;width:16px}#ux-lightbox-overlay,#ux-lightbox-shim{background-color:#515151;border:0;height:500px;left:0;margin:0;padding:0;position:absolute;top:0;width:100%;z-index:14999}#ux-lightbox-shim{background-color:initial;z-index:89}.x-panel-body-noheader .x-grid3-row{position:relative}.x-grid3-col-main{padding:10px 5px 35px}.x-grid3-cell-inner .x-grid3-col-main h3{color:#555;font:normal 13px/1.4 -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:20px;line-height:1;margin:0 0 5px}.package-installed{color:#515151;filter:alpha(opacity=50);opacity:.5}#modx-grid-package .green{text-align:center}#modx-grid-package .green a{color:#cf1124!important}#modx-grid-package .red{color:#6cb24a!important;text-align:center}.grid-with-buttons .x-grid3-row-expanded .x-grid3-row-body{margin:-45px 2px 0 -20px;padding:18px 25px 40px}.x-grid3-row-expanded .x-grid3-row-body .manager-user-message{border-top:1px dashed #868b8f80;display:flex;flex-direction:column-reverse;gap:1rem;padding:.5rem .25rem 0}.x-grid3-row-expanded .x-grid3-row-body .manager-user-message .meta{-moz-column-gap:.5rem;column-gap:.5rem;display:flex;flex-direction:row;font-style:italic;line-height:1.4;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;justify-content:space-between;row-gap:.25rem}.x-grid3-row-expanded .x-grid3-row-body .manager-user-message .meta span{display:block}.x-grid3-row-expanded .x-grid3-row-body .manager-user-message .body{flex-grow:1}.x-grid3-row-expanded .x-grid3-row-body .manager-user-message .body p{font:normal 12px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}@media screen and (min-width:641px){.x-grid3-row-expanded .x-grid3-row-body .manager-user-message{flex-direction:row-reverse}.x-grid3-row-expanded .x-grid3-row-body .manager-user-message .meta{flex-direction:column;justify-content:normal}.x-grid3-row-expanded .x-grid3-row-body .manager-user-message .meta span{display:inline}}.home-panel ol{border-top:1px solid #cacaca}.home-panel ol li{border-bottom:1px solid #e0e0e0}.home-panel ol li:first-child{border-top-color:0 none}.home-panel ol li:last-child{border-bottom:0}.home-panel ol li button{background-color:initial;border:0;color:#53595f;cursor:pointer;display:block;font-size:15px;font-weight:700;padding:12px 20px 12px 6px;position:relative;text-decoration:none}.home-panel ol li:hover button{color:#234368}.home-panel ol li:hover button:before{content:"\f002";filter:alpha(opacity=60);font-size:14px;margin-top:-7px;opacity:.6;position:absolute;right:0;text-align:center;top:50%;transition:opacity .25s;width:20px}.home-panel ol li .highlighted{color:#909090;float:right;font-size:10px;padding:13px 10px 0}.home-panel ol li button .ct{color:#aaa;margin-right:10px}.home-panel .one_half{overflow:hidden}.home-panel .desc-wrapper{margin-top:38px}.home-panel .text-wrapper{font-style:normal;max-height:none}.home-panel .provider_name{background-color:#9bb3bf;line-height:1.8}.home-panel .pnl_instructions{margin:20px 0}.home-panel .stats{clear:both;display:inline-block;margin-top:15px}.home-panel .stats p{color:#777;font-size:12px;font-style:italic;line-height:1.5}.pbr-provider-box{float:left;margin-top:10px;width:250px}.pbr-provider-home,.pbr-repository-view,.pbr-tag-view{padding:10px}.pbr-details-right{float:right!important;text-align:right!important}.pbr-thumb-downloaded{filter:alpha(opacity=50);opacity:.5}.one_half{float:left;margin-right:3%;position:relative;width:48%}.last{clear:right;margin-right:0!important}.package-readme{padding:8px 11px 0}#modx-package-browser-home{margin-top:5px;min-height:560px}.empty-text-wrapper{color:#888;font-weight:700;line-height:1.4;padding:12px}.aside-details{background-color:initial;border:1px solid #e4e4e4;border-radius:3px;margin-right:0}.aside-details .selected h5{color:#53595f;font-size:14px;margin:10px 0}.aside-details .selected img{border:1px solid #e4e4e4;border-radius:3px;height:80px;width:90px}.aside-details .item{margin-bottom:25px}.aside-details .item li,.aside-details .item p{color:#888;line-height:1.4}.aside-details .item a{color:#53595f;font-style:italic}.aside-details h4{color:#53595f;font-size:14px;margin:10px 0;text-transform:uppercase}.aside-details .aside-details h4{font-size:12px;margin-top:0}.aside-details .selected{border-bottom:1px solid #e4e4e4;color:#000;padding:15px;text-align:center}.aside-details .description,.aside-details .instructions{background-color:#fbfbfb}.aside-details .description,.aside-details .infos,.aside-details .instructions{color:#53595f;font-size:12px;line-height:1.2;padding:15px}.aside-details .infos ul li{font-size:12px}.aside-details .infos ul li .infoname{color:#999;font-weight:700;width:50%}.aside-details .infos ul li .infovalue{word-wrap:break-word;max-width:50%;padding:0 8px}.aside-details .infos ul li span{display:inline-block;padding:0}.thumb-wrapper{background-color:#f5f5f5;border:1px solid #ccc;border-radius:3px;cursor:pointer;float:left;margin:0 15px 15px 0;overflow:hidden;padding:0 0 12px;position:relative;width:250px}.thumb-wrapper,.thumb-wrapper *{box-sizing:border-box}.thumb-wrapper .thumb{background-color:#fff;border-bottom:1px solid #ccc;height:170px;margin:0 auto;position:relative;text-align:center;width:100%}.thumb-wrapper .thumb img{max-height:100%;max-width:100%}.thumb-wrapper .thumb .no-preview{color:#888;display:inline-block;font-size:9px;font-weight:700;padding:31px 15px;text-align:center;text-transform:uppercase}.thumb-wrapper span.downloaded,.thumb-wrapper span.featured{background-color:#6cb24a;color:#fff;font-weight:700;padding:5px 0;position:absolute;text-align:center;text-shadow:none;top:68px;width:100%}.thumb-wrapper span.featured{background-color:#234368;bottom:0;color:#fff;top:auto}.thumb-wrapper span{display:block;margin:0;overflow:hidden;text-align:left;text-overflow:ellipsis;text-shadow:0 1px 0 #fff;white-space:nowrap}.thumb-wrapper .name{color:#53595f;float:left;font-size:12px;font-weight:700;padding:12px 8px 12px 12px;width:55%}.thumb-wrapper .downloads{color:#999;float:right;font-size:9px;padding:8px 12px 8px 8px;text-align:right;text-transform:uppercase;width:45%}.thumb-wrapper .thumb-description{clear:both;font-size:12px;height:50px;overflow:hidden;padding:0 12px}.thumb-wrapper .thumb-footer{color:#999;font-size:9px;padding:8px 12px 0;text-align:center;text-transform:uppercase}.thumb-wrapper.selected{background-color:#fff;border-color:#234368;padding:0 0 12px}.thumb-wrapper.selected img{border:0}.pbr-thumb{background:#dfdfdf;padding:3px}.pbr-thumb,.pbr-thumb img{height:80px;width:100px}.x-grid3-hd-info-col,.x-grid3-hd-meta-col,.x-grid3-hd-text-col{text-align:center}.x-grid3-col-text-col{font-size:11px;text-align:center}.x-grid3-col-info-col,.x-grid3-col-meta-col{font-size:11px;font-weight:700;text-align:center}.x-grid3-col-meta-col{color:#53595f}.x-grid3-col-info-col{color:#6cb24a}.not-installed .x-grid3-col-info-col{color:#cf1124}.inline-button{-webkit-box-align:center;display:inline;margin:0 auto;padding:8px;text-align:center}.meta-wrapper{word-wrap:break-word;color:grey;max-height:400px;overflow:auto;padding:15px}.meta-wrapper ul{list-style:disc inside;padding-left:15px}.meta-wrapper h1{font-size:1.2em}.meta-wrapper h2{font-size:1.15em}.meta-wrapper h3{font-size:1.1em}.meta-wrapper h4{font-size:1.05em}.meta-wrapper h5{font-size:1em}.meta-wrapper h6{font-size:.95em}.window-no-padding .x-panel-mc,.window-no-padding .x-panel-ml,.window-no-padding .x-panel-mr{padding:0!important}.window-no-padding .x-tab-panel-noborder{margin:0!important}.upload-error{color:#cf1124}.upload-success{color:#6cb24a}.upload-status-text{white-space:normal}.upload-thumb{float:right}.auto-width{width:auto!important}.auto-height{height:auto!important}.x-datetime-inline-editor .x-datetime-wrap{margin-top:0!important} + /* !important prevents hover / active styles */opacity:.6}#modx-leftbar .x-toolbar-ct .x-toolbar-right .x-btn#emptifier .x-item-disabled button{color:inherit}.tree-new-resource>em>button:before{content:"\f15b"}.tree-new-weblink>em>button:before{content:"\f0c1"}.tree-new-symlink>em>button:before{content:"\f0c5";font-weight:400}.tree-new-static-resource>em>button:before{content:"\f15c";font-weight:400}#modx-leftbar .x-toolbar-ct .x-btn .tree-new-symlink>em>button{left:2px;top:4px}#modx-leftbar .x-toolbar-ct .x-btn .tree-new-weblink>em>button{left:2px}.tree-new-template>em>button:before{content:"\f0db"}.tree-new-tv>em>button:before{content:"\f022";font-weight:400}.tree-new-chunk>em>button:before{content:"\f009";font-weight:900}.tree-new-snippet>em>button:before{content:"\f121"}.tree-new-plugin>em>button:before{content:"\f085"}.tree-new-category>em>button:before{content:"\f07b"}.modx-tv .resizable:hover:after,.modx-tv .resizable:hover:before{background-color:#99999940;color:#999}.modx-tv .resizable:after,.modx-tv .resizable:before{background-color:#99999926;color:#adadad;font-size:smaller;margin-right:.25%;pointer-events:none;position:absolute;right:0;text-align:center;width:15px;z-index:2}.modx-tv .resizable:before{bottom:12px;content:"\f106";height:7px;line-height:.9}.modx-tv .resizable:after{border-bottom-right-radius:3px;bottom:4px;content:"\f107";height:8px;line-height:.6}.modx-tv .resizable textarea{resize:vertical}.modx-tv .x-form-textarea:not(div){font-family:inherit}textarea{overflow:auto}.x-form-textarea,textarea.x-form-field{display:block;padding:5px}.modx-code-content,.x-form-textarea,textarea.x-form-field{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.modx-text-content,textarea[name=description],textarea[name=introtext]{font:normal 13px/1.4 -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.x-form-text,.x-form-textarea,textarea.x-form-field{background-color:#fff;background-image:none;border:1px solid #e4e4e4;border-radius:3px;max-width:100%;position:relative;transition:border-color .25s}.x-viewport .x-form-textarea .x-form-focus,.x-viewport .x-trigger-wrap-focus,.x-viewport input.x-form-focus,.x-viewport textarea.x-form-focus{border-color:#999}.x-viewport .x-trigger-wrap-open{border-radius:3px 3px 0 0}.x-form-invalid,textarea.x-form-invalid{border-color:#cf1124!important}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}#modx-input-props,#modx-widget-props{padding:15px 0 0}.x-form-item{display:block;margin:0;outline:0 none;position:relative;z-index:1}.x-form-item label.x-form-item-label{color:#515151;font-size:13px;font-weight:700;position:relative}.x-form-item label.x-form-item-label .modx-tv-label-title{display:inline-block}.x-form-item label.x-form-item-label .modx-tv-label-description{display:inline-block;font-style:italic;font-weight:400}.x-form-item label.x-form-item-label .modx-field-utils,.x-form-item label.x-form-item-label .modx-tv-reset{cursor:pointer;display:inline-block;filter:alpha(opacity=0);height:16px;opacity:0;padding:0 0 0 3px;position:relative;right:0;top:0;transition:all .25s;width:16px}.x-form-item label.x-form-item-label .modx-field-utils:before,.x-form-item label.x-form-item-label .modx-tv-reset:before{bottom:2px;box-sizing:border-box;color:#a8a8a8;content:"\f2ea";font-size:14px;height:16px;left:0;position:relative;text-align:center;vertical-align:middle;width:16px}.x-form-item label.x-form-item-label .modx-field-utils.modx-field-reset:before,.x-form-item label.x-form-item-label .modx-tv-reset.modx-field-reset:before{content:"\f2ea"}.x-form-item label.x-form-item-label .modx-field-utils.modx-field-reset:hover:before,.x-form-item label.x-form-item-label .modx-tv-reset.modx-field-reset:hover:before{color:#6cb24a}.x-form-item label.x-form-item-label .modx-field-utils.modx-field-clear:before,.x-form-item label.x-form-item-label .modx-tv-reset.modx-field-clear:before{content:"\f12d";font-size:15px;margin-bottom:4px}.x-form-item label.x-form-item-label .modx-field-utils.modx-field-clear:hover:before,.x-form-item label.x-form-item-label .modx-tv-reset.modx-field-clear:hover:before{color:#cf1124}.x-form-item label.x-form-item-label .modx-field-utils:hover:before,.x-form-item label.x-form-item-label .modx-tv-reset:hover:before{color:#6cb24a}.x-form-item label.x-form-item-label .modx-field-utils:active:before,.x-form-item label.x-form-item-label .modx-tv-reset:active:before{color:#1b3451}.x-form-item label.x-form-item-label:hover .modx-field-utils,.x-form-item label.x-form-item-label:hover .modx-tv-reset{filter:alpha(opacity=100);opacity:1}.x-form-item.modx-tv{padding:0!important}.x-form-item .modx-tv-inherited{color:#515151;display:inline-block;font-size:10px;font-style:italic;position:absolute;right:0;top:19px}.x-form-item .modx-tv-image-preview{margin-top:7px}.x-form-item .modx-tv-image-preview img{display:block;max-height:400px;max-width:400px}.x-form-item .modx-tag-list{list-style:none;margin:0;overflow:auto;padding:0}.x-form-item .modx-tag-list .modx-tag-opt{background-color:#e4e4e4;border-radius:0 3px 3px 0;cursor:pointer;display:inline-block;margin:4px 5px 0 10px;padding:1px 5px;position:relative}.x-form-item .modx-tag-list .modx-tag-opt:before{border-color:#0000 #e4e4e4 #0000 #0000;border-style:solid;border-width:10px 10px 10px 0;content:"";height:0;left:-10px;position:absolute;top:0;transform:rotate(1turn);width:0}.x-form-item .modx-tag-list .modx-tag-opt:after{background-color:#fff;border-radius:50%;content:"";height:4px;left:-4px;position:absolute;top:8px;width:4px}.x-form-item .modx-tag-list .modx-tag-opt.modx-tag-checked,.x-form-item .modx-tag-list .modx-tag-opt:hover{background-color:#234368;color:#fff;text-decoration:none}.x-form-item .modx-tag-list .modx-tag-opt.modx-tag-checked:before,.x-form-item .modx-tag-list .modx-tag-opt:hover:before{border-color:#0000 #234368 #0000 #0000}.x-form-item .modx-tag-list .modx-tag-opt.modx-tag-checked:hover,.x-form-item .modx-tag-list .modx-tag-opt:hover:hover{background-color:#1b3451}.x-form-item .modx-tag-list .modx-tag-opt.modx-tag-checked:hover:before,.x-form-item .modx-tag-list .modx-tag-opt:hover:hover:before{border-color:#0000 #1b3451 #0000 #0000}.x-form-item .modx-tv-legacy-select{border:1px solid #e4e4e4;border-radius:3px;padding:5px;transition:all .25s}.x-form-item .modx-tv-legacy-select:focus{border:1px solid #1b3451}.x-form-item .modx-tv-legacy-select option[selected]{background-color:#e4e4e4}.x-form-label-left .x-form-item{padding:15px 0 0}.x-form-label-left .x-form-item:first-of-type{padding:0}.x-form-label-left .x-form-item label.x-form-item-label{display:inline-block;margin:0;padding:7px 0}.x-form-label-top .x-form-item{padding:0}.x-form-label-top .x-form-item label.x-form-item-label{display:inline-block;margin:15px 0 4px;padding:0}.x-window .x-form-item .x-form-item-label{padding:10px 0 4px}.x-form-item.x-hide-label{padding-top:10px!important}#modx-resource-content .x-form-item.x-hide-label{padding-top:0!important}.x-form-item.x-hide-label label.x-form-item-label{display:none}.x-form-item.disabled label{color:#a8a8a8}.x-form-item .x-form-element{font:normal 13px/1.4 -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;padding:0}.x-form-item .x-form-element .x-form-invalid-icon{color:#cf1124}.x-form-item .x-form-element .x-form-invalid-icon:before{content:"\f071";left:3px;position:absolute}.x-form-item .x-column-inner>.x-column~.x-column{margin-left:5px}.x-form-item .x-column-inner>.x-column .x-form-field-wrap{width:auto!important}.x-form-item .container{margin:0}.x-form-item .x-btn{padding:7px 10px}.desc-under{color:#999;display:block;font-size:12px;font-style:italic;margin:.4em 0 0;transition:color .25s}.desc-under:hover{color:#4d4d4d}.desc-under.toggle-slider-above{margin:.3em 0;padding-left:3.9em}.desc-under .warning{color:#cf1124;overflow:hidden;padding:0}.desc-under .example-list ul{margin:.4em 0}.desc-under .example-list ul li{margin-bottom:.25em;padding-left:1.25em;position:relative}.desc-under .example-list ul li:before{color:#adadad;content:"\f101";left:.2em;position:absolute;top:0}.desc-under .copy-this,.desc-under .example-input{border-radius:2px;padding:0 .3em;transition:width 1s}.desc-under .example-input{background-color:#f6faf5;color:#6e935d}.desc-under .example-input:hover{background-color:#eff6ec;color:#578c3d;cursor:pointer}.desc-under .copy-this{background-color:#f1f6fc;color:#5e8bbf;position:relative}.desc-under .copy-this:hover{background-color:#e7f1fb;color:#1b5ca8;cursor:pointer}.desc-under .copy-this:hover:after{color:#6892c4;content:"\f0c5";cursor:default;margin-left:.5em;position:absolute}.desc-under .copy-this:active,.desc-under .copy-this:active:after,.desc-under .copy-this:hover:active,.desc-under .copy-this:hover:active:after{color:#515151}.desc-under .feedback{color:#1b5ca8;font-style:normal;margin-left:1.4rem}.desc-under .feedback.item-copied{opacity:1;transition:opacity 1.5s}.desc-under a{border-bottom:1px dotted #999;color:#999;text-decoration:none}.desc-under a:hover{color:#515151}.desc-under .deemphasize{font-style:normal}.fs-toggle{border-top:1px dashed #e4e4e4;margin-bottom:.5em;margin-top:2em;padding-top:1em}.x-fieldset{border:1px solid #e4e4e4;border-radius:3px!important; + /* !important ensures the border radius, also when the fieldset has a class that sets it to 0 */margin:15px 0 0;overflow:visible;padding:0;position:relative}.x-fieldset .x-fieldset-header{color:#515151;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-weight:700;margin:0 0 0 10px;padding:0 5px 0 3px;position:relative}.x-fieldset .x-fieldset-header .x-fieldset-header-text{line-height:18px}.x-fieldset .x-fieldset-bwrap .x-fieldset-body{overflow-x:hidden!important;padding:0 10px 10px}.x-fieldset.form-row-wrapper .x-fieldset-bwrap .x-fieldset-body{padding:0 15px 15px}.x-fieldset#tv-input-opts-fs,.x-fieldset#tv-output-opts-fs{border:0;margin:0}.x-fieldset#tv-input-opts-fs .x-fieldset-bwrap .x-fieldset-body,.x-fieldset#tv-output-opts-fs .x-fieldset-bwrap .x-fieldset-body{padding:0}.x-fieldset#tv-input-opts-fs .x-fieldset .x-fieldset-bwrap .x-fieldset-body,.x-fieldset#tv-output-opts-fs .x-fieldset .x-fieldset-bwrap .x-fieldset-body{padding:0 15px 15px}.x-form-field{font:inherit}.x-form-field.x-form-composite{margin-bottom:0!important}.x-form-field.x-form-composite .x-btn{top:1px!important}.x-static-text-field{color:inherit;font-size:inherit}.x-static-text-field.x-form-focus{border-color:#e4e4e4!important}.x-form-text{line-height:20px;min-height:20px;padding:5px}.x-form-field-wrap{background:#fff;border:1px solid #e4e4e4;border-radius:3px;max-width:100%}.x-form-field-wrap .x-form-text:not(.x-form-invalid){border:0}.x-form-field-wrap .x-form-trigger{border:0;border-radius:0 2px 2px 0;box-shadow:none;height:100%!important;padding:0;position:absolute;right:0;top:0;width:30px}.x-form-field-wrap .x-form-trigger:before{box-sizing:border-box;content:"\f078";filter:alpha(opacity=60);font-size:14px;left:50%;opacity:.8;position:absolute;text-align:center;top:50%;transform:translate(-50%,-50%);transition:opacity .25s;width:30px}.x-form-field-wrap .x-form-trigger.x-form-trigger-click:before,.x-form-field-wrap .x-form-trigger.x-form-trigger-over:before,.x-form-field-wrap .x-form-trigger:active:before,.x-form-field-wrap .x-form-trigger:hover:before{filter:alpha(opacity=100);opacity:1}.x-form-field-wrap .x-form-trigger.x-form-date-trigger:before{content:"\f133";font-weight:400}.x-form-field-wrap .x-form-trigger.x-form-time-trigger:before{content:"\f017";font-weight:400}.x-form-field-wrap .x-form-trigger.x-form-file-trigger:before{content:"\f15b";font-weight:400}.x-form-field-wrap .x-form-trigger.x-form-image-trigger:before{content:"\f1c5";font-weight:400}.x-form-field-wrap .x-form-trigger.x-form-code-trigger:before{content:"\f1c9";font-weight:400}.x-form-field-wrap.x-datetime-wrap{background:none;border:0}.x-form-field-wrap.x-datetime-wrap .ux-datetime-date,.x-form-field-wrap.x-datetime-wrap .ux-datetime-time{vertical-align:top}.x-form-field-wrap.x-datetime-wrap .ux-datetime-date .x-form-invalid-msg,.x-form-field-wrap.x-datetime-wrap .ux-datetime-time .x-form-invalid-msg{white-space:normal}.x-form-field-wrap.x-datetime-wrap .ux-datetime-date .x-form-trigger:before{content:"\f133"}.x-form-field-wrap.x-datetime-wrap .ux-datetime-time .x-form-trigger:before{content:"\f017"}.x-form-field-wrap.x-form-fileupload-wrap{overflow:visible;position:relative}.x-form-field-wrap.x-form-fileupload-wrap .x-form-file{filter:alpha(opacity=0);min-height:20px;opacity:0;padding:5px;position:absolute;right:0;top:0;z-index:2}.x-form-field-wrap.x-form-fileupload-wrap .x-form-file-btn{border-left:1px solid #e4e4e4;border-radius:0 3px 3px 0;box-shadow:none;line-height:0;padding:7px;position:absolute;right:0;top:0;z-index:1}.x-form-field-wrap.x-form-fileupload-wrap .x-form-file-text{position:relative;z-index:3}.modx-tv-type-listbox-multiple .x-form-field-wrap{border-color:#fff}.modx-tv-type-listbox-multiple .x-form-field-wrap .x-form-text{border:1px solid #e4e4e4;margin:-1px}.modx-tv-type-listbox-multiple .x-form-field-wrap .x-form-text.x-form-focus{border-color:#999}#x-form-el-modx-user-photo .x-form-file-trigger:before{content:"\f1c5"}.x-fieldset-checkbox-toggle legend,.x-form-check-wrap{height:auto!important;line-height:18px}.x-form-label-left .x-fieldset-checkbox-toggle legend,.x-form-label-left .x-form-check-wrap{padding:7px 0}.x-form-label-top .x-fieldset-checkbox-toggle legend,.x-form-label-top .x-form-check-wrap{padding:0}.x-toolbar .x-toolbar-cell .x-fieldset-checkbox-toggle legend .x-form-cb-label,.x-toolbar .x-toolbar-cell .x-form-check-wrap .x-form-cb-label{padding-left:1.9em}.x-toolbar .x-toolbar-cell .x-fieldset-checkbox-toggle legend .x-form-cb-label:before,.x-toolbar .x-toolbar-cell .x-form-check-wrap .x-form-cb-label:before{color:#ccc}.x-toolbar .x-toolbar-cell .x-fieldset-checkbox-toggle legend .x-form-cb-label:active:before,.x-toolbar .x-toolbar-cell .x-fieldset-checkbox-toggle legend .x-form-cb-label:focus:before,.x-toolbar .x-toolbar-cell .x-fieldset-checkbox-toggle legend .x-form-cb-label:hover:before,.x-toolbar .x-toolbar-cell .x-form-check-wrap .x-form-cb-label:active:before,.x-toolbar .x-toolbar-cell .x-form-check-wrap .x-form-cb-label:focus:before,.x-toolbar .x-toolbar-cell .x-form-check-wrap .x-form-cb-label:hover:before{color:#999}.x-fieldset-checkbox-toggle legend .x-fieldset-header-text,.x-fieldset-checkbox-toggle legend .x-form-cb-label,.x-form-check-wrap .x-fieldset-header-text,.x-form-check-wrap .x-form-cb-label{color:#515151;cursor:pointer;display:inline-block;font-weight:400;margin:0;padding-left:1.9em;position:relative;top:0}.ext-ie8 .x-fieldset-checkbox-toggle legend .x-fieldset-header-text,.ext-ie8 .x-fieldset-checkbox-toggle legend .x-form-cb-label,.ext-ie8 .x-form-check-wrap .x-fieldset-header-text,.ext-ie8 .x-form-check-wrap .x-form-cb-label{padding-left:3px}.ext-ie8 .x-fieldset-checkbox-toggle legend .x-fieldset-header-text:before,.ext-ie8 .x-fieldset-checkbox-toggle legend .x-form-cb-label:before,.ext-ie8 .x-form-check-wrap .x-fieldset-header-text:before,.ext-ie8 .x-form-check-wrap .x-form-cb-label:before{content:""}.x-fieldset-checkbox-toggle legend .x-fieldset-header-text:before,.x-fieldset-checkbox-toggle legend .x-form-cb-label:before,.x-form-check-wrap .x-fieldset-header-text:before,.x-form-check-wrap .x-form-cb-label:before{box-sizing:border-box;content:"";font-size:18px;height:18px;left:0;padding-right:3px;position:absolute;text-align:center;top:0;vertical-align:middle;width:18px}.x-fieldset-checkbox-toggle legend .x-fieldset-header-text:focus:before,.x-fieldset-checkbox-toggle legend .x-fieldset-header-text:hover:before,.x-fieldset-checkbox-toggle legend .x-form-cb-label:focus:before,.x-fieldset-checkbox-toggle legend .x-form-cb-label:hover:before,.x-form-check-wrap .x-fieldset-header-text:focus:before,.x-form-check-wrap .x-fieldset-header-text:hover:before,.x-form-check-wrap .x-form-cb-label:focus:before,.x-form-check-wrap .x-form-cb-label:hover:before{color:#234368}.x-fieldset-checkbox-toggle legend .x-fieldset-header-text:active:before,.x-fieldset-checkbox-toggle legend .x-form-cb-label:active:before,.x-form-check-wrap .x-fieldset-header-text:active:before,.x-form-check-wrap .x-form-cb-label:active:before{color:#1b3451}.x-fieldset-checkbox-toggle legend .x-form-checkbox,.x-fieldset-checkbox-toggle legend .x-form-radio,.x-fieldset-checkbox-toggle legend input[type=checkbox],.x-form-check-wrap .x-form-checkbox,.x-form-check-wrap .x-form-radio,.x-form-check-wrap input[type=checkbox]{cursor:pointer;height:18px;left:0;opacity:0;position:absolute;top:0;width:18px;z-index:1}.ext-ie8 .x-fieldset-checkbox-toggle legend .x-form-checkbox,.ext-ie8 .x-fieldset-checkbox-toggle legend .x-form-radio,.ext-ie8 .x-fieldset-checkbox-toggle legend input[type=checkbox],.ext-ie8 .x-form-check-wrap .x-form-checkbox,.ext-ie8 .x-form-check-wrap .x-form-radio,.ext-ie8 .x-form-check-wrap input[type=checkbox]{height:13px;left:auto;position:relative;top:auto;width:13px}.x-fieldset-checkbox-toggle legend .x-form-checkbox:focus+.x-fieldset-header-text:before,.x-fieldset-checkbox-toggle legend .x-form-checkbox:focus+.x-form-cb-label:before,.x-fieldset-checkbox-toggle legend .x-form-checkbox:hover+.x-fieldset-header-text:before,.x-fieldset-checkbox-toggle legend .x-form-checkbox:hover+.x-form-cb-label:before,.x-fieldset-checkbox-toggle legend .x-form-radio:focus+.x-fieldset-header-text:before,.x-fieldset-checkbox-toggle legend .x-form-radio:focus+.x-form-cb-label:before,.x-fieldset-checkbox-toggle legend .x-form-radio:hover+.x-fieldset-header-text:before,.x-fieldset-checkbox-toggle legend .x-form-radio:hover+.x-form-cb-label:before,.x-fieldset-checkbox-toggle legend input[type=checkbox]:focus+.x-fieldset-header-text:before,.x-fieldset-checkbox-toggle legend input[type=checkbox]:focus+.x-form-cb-label:before,.x-fieldset-checkbox-toggle legend input[type=checkbox]:hover+.x-fieldset-header-text:before,.x-fieldset-checkbox-toggle legend input[type=checkbox]:hover+.x-form-cb-label:before,.x-form-check-wrap .x-form-checkbox:focus+.x-fieldset-header-text:before,.x-form-check-wrap .x-form-checkbox:focus+.x-form-cb-label:before,.x-form-check-wrap .x-form-checkbox:hover+.x-fieldset-header-text:before,.x-form-check-wrap .x-form-checkbox:hover+.x-form-cb-label:before,.x-form-check-wrap .x-form-radio:focus+.x-fieldset-header-text:before,.x-form-check-wrap .x-form-radio:focus+.x-form-cb-label:before,.x-form-check-wrap .x-form-radio:hover+.x-fieldset-header-text:before,.x-form-check-wrap .x-form-radio:hover+.x-form-cb-label:before,.x-form-check-wrap input[type=checkbox]:focus+.x-fieldset-header-text:before,.x-form-check-wrap input[type=checkbox]:focus+.x-form-cb-label:before,.x-form-check-wrap input[type=checkbox]:hover+.x-fieldset-header-text:before,.x-form-check-wrap input[type=checkbox]:hover+.x-form-cb-label:before{color:#234368}.x-fieldset-checkbox-toggle legend .x-form-checkbox:active+.x-fieldset-header-text:before,.x-fieldset-checkbox-toggle legend .x-form-checkbox:active+.x-form-cb-label:before,.x-fieldset-checkbox-toggle legend .x-form-radio:active+.x-fieldset-header-text:before,.x-fieldset-checkbox-toggle legend .x-form-radio:active+.x-form-cb-label:before,.x-fieldset-checkbox-toggle legend input[type=checkbox]:active+.x-fieldset-header-text:before,.x-fieldset-checkbox-toggle legend input[type=checkbox]:active+.x-form-cb-label:before,.x-form-check-wrap .x-form-checkbox:active+.x-fieldset-header-text:before,.x-form-check-wrap .x-form-checkbox:active+.x-form-cb-label:before,.x-form-check-wrap .x-form-radio:active+.x-fieldset-header-text:before,.x-form-check-wrap .x-form-radio:active+.x-form-cb-label:before,.x-form-check-wrap input[type=checkbox]:active+.x-fieldset-header-text:before,.x-form-check-wrap input[type=checkbox]:active+.x-form-cb-label:before{color:#1b3451}.x-fieldset-checkbox-toggle legend .x-form-checkbox+.x-form-cb-label:before,.x-fieldset-checkbox-toggle legend input[type=checkbox]+.x-fieldset-header-text:before,.x-form-check-wrap .x-form-checkbox+.x-form-cb-label:before,.x-form-check-wrap input[type=checkbox]+.x-fieldset-header-text:before{content:"\f0c8";font-weight:400}.x-fieldset-checkbox-toggle legend .x-form-checkbox:checked+.x-form-cb-label:before,.x-fieldset-checkbox-toggle legend input[type=checkbox]:checked+.x-fieldset-header-text:before,.x-form-check-wrap .x-form-checkbox:checked+.x-form-cb-label:before,.x-form-check-wrap input[type=checkbox]:checked+.x-fieldset-header-text:before{content:"\f14a";font-weight:400}.x-fieldset-checkbox-toggle legend .x-form-radio+.x-form-cb-label:before,.x-form-check-wrap .x-form-radio+.x-form-cb-label:before{content:"\f111";font-weight:400}.x-fieldset-checkbox-toggle legend .x-form-radio:checked+.x-form-cb-label:before,.x-form-check-wrap .x-form-radio:checked+.x-form-cb-label:before{content:"\f192";font-weight:400}#modx-chunk-tabs.space-before,#modx-plugin-tabs.space-before,#modx-resource-tabs .display-switch.space-before,#modx-snippet-tabs.space-before,#modx-template-tabs.space-before,#modx-tv-editor-tabs.space-before,#modx-tv-tabs .display-switch.space-before,.display-switch.space-before{margin-top:.75rem}#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox],#modx-chunk-tabs .x-fieldset legend [type=checkbox],#modx-chunk-tabs .x-form-check-wrap [type=checkbox],#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox],#modx-plugin-tabs .x-fieldset legend [type=checkbox],#modx-plugin-tabs .x-form-check-wrap [type=checkbox],#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox],#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox],#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox],#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox],#modx-snippet-tabs .x-fieldset legend [type=checkbox],#modx-snippet-tabs .x-form-check-wrap [type=checkbox],#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox],#modx-template-tabs .x-fieldset legend [type=checkbox],#modx-template-tabs .x-form-check-wrap [type=checkbox],#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox],#modx-tv-editor-tabs .x-fieldset legend [type=checkbox],#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox],#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox],#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox],#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox],.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox],.display-switch .x-fieldset legend [type=checkbox],.display-switch .x-form-check-wrap [type=checkbox]{left:-9999px;position:absolute}html[dir=rtl] #modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox],html[dir=rtl] #modx-chunk-tabs .x-fieldset legend [type=checkbox],html[dir=rtl] #modx-chunk-tabs .x-form-check-wrap [type=checkbox],html[dir=rtl] #modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox],html[dir=rtl] #modx-plugin-tabs .x-fieldset legend [type=checkbox],html[dir=rtl] #modx-plugin-tabs .x-form-check-wrap [type=checkbox],html[dir=rtl] #modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox],html[dir=rtl] #modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox],html[dir=rtl] #modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox],html[dir=rtl] #modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox],html[dir=rtl] #modx-snippet-tabs .x-fieldset legend [type=checkbox],html[dir=rtl] #modx-snippet-tabs .x-form-check-wrap [type=checkbox],html[dir=rtl] #modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox],html[dir=rtl] #modx-template-tabs .x-fieldset legend [type=checkbox],html[dir=rtl] #modx-template-tabs .x-form-check-wrap [type=checkbox],html[dir=rtl] #modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox],html[dir=rtl] #modx-tv-editor-tabs .x-fieldset legend [type=checkbox],html[dir=rtl] #modx-tv-editor-tabs .x-form-check-wrap [type=checkbox],html[dir=rtl] #modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox],html[dir=rtl] #modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox],html[dir=rtl] #modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox],html[dir=rtl] .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox],html[dir=rtl] .display-switch .x-fieldset legend [type=checkbox],html[dir=rtl] .display-switch .x-form-check-wrap [type=checkbox]{left:unset;right:-9999px}#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text,#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label,#modx-chunk-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text,#modx-chunk-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label,#modx-plugin-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text,#modx-plugin-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label,#modx-snippet-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text,#modx-snippet-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label,#modx-template-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text,#modx-template-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label,#modx-template-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text,#modx-template-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label,.display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text,.display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label,.display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text,.display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label{box-sizing:border-box;cursor:pointer;line-height:1;margin-left:0;padding-left:3.6em;padding-top:.2em;position:relative}#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-chunk-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-chunk-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-chunk-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-chunk-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-plugin-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-plugin-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-plugin-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-plugin-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-snippet-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-snippet-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-snippet-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-snippet-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-template-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-template-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-template-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-template-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-template-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-template-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-template-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-template-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,.display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,.display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,.display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,.display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,.display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,.display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,.display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,.display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before{content:"";font-size:inherit;position:absolute;transition:all .2s ease}#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-chunk-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-chunk-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-plugin-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-plugin-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-snippet-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-snippet-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-template-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-template-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-template-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-template-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:before,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:before,.display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:before,.display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:before,.display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:before,.display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:before{background:#e4e4e4;border-radius:1.2em;height:1.6em;left:0;top:0;width:3em;z-index:10}#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-chunk-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-chunk-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-plugin-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-plugin-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-snippet-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-snippet-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-template-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-template-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-template-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-template-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-fieldset-header-text:after,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]+.x-form-cb-label:after,.display-switch .x-fieldset legend [type=checkbox]+.x-fieldset-header-text:after,.display-switch .x-fieldset legend [type=checkbox]+.x-form-cb-label:after,.display-switch .x-form-check-wrap [type=checkbox]+.x-fieldset-header-text:after,.display-switch .x-form-check-wrap [type=checkbox]+.x-form-cb-label:after{background-color:#fff;border-radius:50%;height:1.3em;left:.1em;margin-top:-.65em;top:.8em;width:1.3em;z-index:11}#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-chunk-tabs .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-chunk-tabs .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:after,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-plugin-tabs .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-plugin-tabs .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:after,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:after,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-snippet-tabs .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-snippet-tabs .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:after,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-template-tabs .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-template-tabs .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-template-tabs .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-template-tabs .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:after,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:after,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:after,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:after,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:after,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:after,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:after,.display-switch .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:after,.display-switch .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:after,.display-switch .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:after,.display-switch .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:after{left:1.6em;top:.8em}#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-chunk-tabs .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-chunk-tabs .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-chunk-tabs .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:before,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-plugin-tabs .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-plugin-tabs .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-plugin-tabs .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:before,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-snippet-tabs .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-snippet-tabs .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-snippet-tabs .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:before,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-template-tabs .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-template-tabs .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-template-tabs .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-template-tabs .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:before,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:before,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-fieldset-header-text:before,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox]:checked+.x-form-cb-label:before,.display-switch .x-fieldset legend [type=checkbox]:checked+.x-fieldset-header-text:before,.display-switch .x-fieldset legend [type=checkbox]:checked+.x-form-cb-label:before,.display-switch .x-form-check-wrap [type=checkbox]:checked+.x-fieldset-header-text:before,.display-switch .x-form-check-wrap [type=checkbox]:checked+.x-form-cb-label:before{background-color:#6cb24a;border-color:#6cb24a}#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-chunk-tabs .x-fieldset legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-chunk-tabs .x-fieldset legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-chunk-tabs .x-form-check-wrap [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-chunk-tabs .x-form-check-wrap [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-plugin-tabs .x-fieldset legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-plugin-tabs .x-fieldset legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-plugin-tabs .x-form-check-wrap [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-plugin-tabs .x-form-check-wrap [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-snippet-tabs .x-fieldset legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-snippet-tabs .x-fieldset legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-snippet-tabs .x-form-check-wrap [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-snippet-tabs .x-form-check-wrap [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-template-tabs .x-fieldset legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-template-tabs .x-fieldset legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-template-tabs .x-form-check-wrap [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-template-tabs .x-form-check-wrap [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox].danger:checked+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox].danger:checked+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox].danger:checked+.x-form-cb-label:before,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].danger:checked+.x-form-cb-label:before,.display-switch .x-fieldset legend [type=checkbox].danger:checked+.x-fieldset-header-text:before,.display-switch .x-fieldset legend [type=checkbox].danger:checked+.x-form-cb-label:before,.display-switch .x-form-check-wrap [type=checkbox].danger:checked+.x-fieldset-header-text:before,.display-switch .x-form-check-wrap [type=checkbox].danger:checked+.x-form-cb-label:before{background-color:#cf1124;border-color:#cf1124}#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-chunk-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-chunk-tabs .x-fieldset legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-chunk-tabs .x-fieldset legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-chunk-tabs .x-form-check-wrap [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-chunk-tabs .x-form-check-wrap [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-plugin-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-plugin-tabs .x-fieldset legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-plugin-tabs .x-fieldset legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-plugin-tabs .x-form-check-wrap [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-plugin-tabs .x-form-check-wrap [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-fieldset legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-resource-tabs .display-switch .x-form-check-wrap [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-snippet-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-snippet-tabs .x-fieldset legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-snippet-tabs .x-fieldset legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-snippet-tabs .x-form-check-wrap [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-snippet-tabs .x-form-check-wrap [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-template-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-template-tabs .x-fieldset legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-template-tabs .x-fieldset legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-template-tabs .x-form-check-wrap [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-template-tabs .x-form-check-wrap [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-fieldset legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-tv-editor-tabs .x-form-check-wrap [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-fieldset legend [type=checkbox].warning:checked+.x-form-cb-label:before,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox].warning:checked+.x-fieldset-header-text:before,#modx-tv-tabs .display-switch .x-form-check-wrap [type=checkbox].warning:checked+.x-form-cb-label:before,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,.display-switch .x-fieldset-checkbox-toggle legend [type=checkbox].warning:checked+.x-form-cb-label:before,.display-switch .x-fieldset legend [type=checkbox].warning:checked+.x-fieldset-header-text:before,.display-switch .x-fieldset legend [type=checkbox].warning:checked+.x-form-cb-label:before,.display-switch .x-form-check-wrap [type=checkbox].warning:checked+.x-fieldset-header-text:before,.display-switch .x-form-check-wrap [type=checkbox].warning:checked+.x-form-cb-label:before{background-color:#f0b429;border-color:#f0b429}.switch-container{padding-top:1.6rem}.x-form-check-group,.x-form-radio-group{overflow:hidden;padding-bottom:.5em}.x-form-check-group .x-column .x-form-item:first-child,.x-form-radio-group .x-column .x-form-item:first-child{padding:4px 0 0}.x-form-check-group.aggregated-group,.x-form-radio-group.aggregated-group{padding-left:1em;padding-right:1em}.x-superboxselect{margin:0;outline:0;padding:0 5px 5px;position:relative;white-space:normal;width:auto!important}.ext-strict .x-toolbar .x-small-editor .x-superboxselect,.x-superboxselect{height:auto!important}.x-superboxselect ul{cursor:text;min-height:20px;overflow:visible;padding-right:61px;white-space:normal;width:auto!important}.x-toolbar .x-superboxselect ul{margin:-5px 0 0 -5px}.x-superboxselect ul li{margin:5px 5px 0 0;padding:0}.x-superboxselect ul li.x-superboxselect-item{cursor:default;font-size:12px;padding:4px 18px 4px 4px!important;position:relative}.x-superboxselect ul li.x-superboxselect-item.x-superboxselect-item-focus{background-color:#234368;box-shadow:0 0 0 1px #234368;color:#fff}.x-superboxselect ul li.x-superboxselect-item .x-superboxselect-item-close{border:0;color:inherit;cursor:pointer;display:inline-block;filter:alpha(opacity=60);height:100%;opacity:.6;outline:0;padding:0;position:absolute;right:0;top:0;transition:opacity .25s;width:16px}.x-superboxselect ul li.x-superboxselect-item .x-superboxselect-item-close:before{box-sizing:border-box;color:inherit;content:"\f00d";font-size:14px;margin-top:-7px;position:absolute;right:0;text-align:center;top:50%;vertical-align:middle;width:16px}.x-superboxselect ul li.x-superboxselect-item .x-superboxselect-item-close:focus,.x-superboxselect ul li.x-superboxselect-item .x-superboxselect-item-close:hover{filter:alpha(opacity=100);opacity:1}.x-superboxselect ul li.x-superboxselect-input{display:inline-block}.x-superboxselect ul li.x-superboxselect-input input{background:none;border:0;line-height:20px;outline:0}.x-superboxselect.x-superboxselect-stacked li{box-sizing:border-box;margin:5px 0 0;width:100%}.x-superboxselect .x-superboxselect-btns{height:100%;overflow:visible;position:absolute;right:0;top:0;width:61px}.x-superboxselect .x-superboxselect-btns .x-superboxselect-btn-expand{border-radius:0;right:31px}.x-superboxselect .x-superboxselect-btns .x-superboxselect-btn-clear{border-left:1px solid #e4e4e4}.x-superboxselect .x-superboxselect-btns .x-superboxselect-btn-clear:before{content:"\f00d"}.inline-form{border:0;padding:15px 15px 0}.inline-form label{color:#777;display:block;font-weight:700;margin-bottom:2px}.inline-form input[type=text],.inline-form textarea{background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:3px;position:relative;width:97%}.inline-form input[type=text]{font-size:13px;height:20px!important;padding:5px}.modx-tv-description{color:#515151;font-size:10px;line-height:1.2;margin-top:2px!important}.modx-tv-reload-btn{float:right;position:absolute;right:19px;z-index:10}.modx-tv-reload-btn div{z-index:10}.modx-tv-th label{cursor:pointer}.modx-tv-th .tv-description{color:#515151;font-size:11px;font-weight:400}.x-editor .x-form-check-wrap{background-color:#fff}.x-grid-editor{z-index:9002!important}.x-grid-editor .x-form-field-wrap{background:#f6f2f7 url(../images/modx-theme/form/combo-bck.png) repeat-x scroll 0 100%}.x-grid-editor .x-form-field-wrap input{background-color:initial!important}.x-grid-editor .x-form-field-wrap img{background-color:#fff;background-image:url(../images/modx-theme/form/trigger.png)}.x-form-grow-sizer,.x-form-invalid-msg{font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.x-form-invalid-msg{color:#cf1124;margin-top:2px;min-width:95%;position:relative}.x-form-invalid-msg:before{color:inherit;content:"\f071";left:3px;position:absolute;top:3px}.x-form-empty-field{color:#515151}.x-grid3 .x-small-editor .x-form-field-wrap,.x-grid3 .x-small-editor .x-form-text{font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;margin-top:7px;padding:2px 5px}.x-grid3 .x-small-editor .x-form-field-wrap .x-form-text,.x-grid3 .x-small-editor .x-form-text .x-form-text{margin:0;padding:0}.x-grid3 .x-small-editor .x-form-field-wrap{overflow:hidden}.x-combo-list{border:0;border-radius:3px;overflow:visible}.x-combo-list .x-combo-list-inner{background-color:#fff;border:1px solid #999;border-radius:3px;margin-left:-1px;width:100%!important}.x-combo-list .x-combo-list-item{border:0!important;border-bottom:1px solid #e4e4e4!important;color:#515151;min-height:18.2px;padding:6px 8px}.x-combo-list .x-combo-list-item:last-child{border-bottom-color:#fff!important}.x-combo-list .x-combo-list-item.x-combo-selected{background-color:#e4e4e4;border:0!important;border-bottom:1px solid #e4e4e4!important;color:#1b3451}.x-combo-list .x-combo-list-item.x-combo-list-item-grouped{padding:6px 14px}.x-combo-list .x-combo-list-item .x-combo-list-title{display:block;font-weight:700;margin:0 0 5px}.x-combo-list .x-combo-list-group{border-bottom:1px solid #e4e4e4;color:#515151;font-weight:700;padding:6px 8px}.x-combo-list .x-toolbar{border:0;border-radius:0 0 3px 3px;box-shadow:0 0 0 1px #234368;margin-top:-1px;position:relative}.x-combo-list .x-toolbar .x-toolbar-ct{padding:5px 0 15px}.x-combo-list .x-toolbar .x-toolbar-left table{margin:0 auto}.x-combo-list .x-toolbar .x-toolbar-cell{display:inline-block}.x-combo-list .x-toolbar .x-toolbar-cell .x-btn,.x-combo-list .x-toolbar .x-toolbar-cell .x-form-text{background:#0000;box-shadow:none;font-size:10px;line-height:16px;margin-right:2px;min-height:16px;padding:2px}.x-combo-list .x-toolbar .x-toolbar-cell .x-btn{padding:1px;transition:color .25s}.x-combo-list .x-toolbar .x-toolbar-cell .x-btn.x-btn-over,.x-combo-list .x-toolbar .x-toolbar-cell .x-btn:focus,.x-combo-list .x-toolbar .x-toolbar-cell .x-btn:hover{color:#234368}.x-combo-list .x-toolbar .x-toolbar-cell .x-btn.x-btn-click,.x-combo-list .x-toolbar .x-toolbar-cell .x-btn:active{color:#1b3451}.x-combo-list .x-toolbar .x-toolbar-cell .x-btn.x-item-disabled{color:#515151;opacity:.4}.x-combo-list .x-toolbar .x-toolbar-cell .x-btn button:before{left:0;line-height:20px;right:0;top:0}.x-combo-list .x-toolbar .x-toolbar-cell .x-form-text{background:#fbfbfb;width:23px}.x-combo-list .x-toolbar .xtb-text{font-size:10px;line-height:1;margin:0 auto;padding:0;text-align:center}.x-combo-list .x-toolbar .x-toolbar-cell:first-child .x-btn{margin-left:1px}.x-combo-list .x-toolbar .x-toolbar-cell+.x-toolbar-cell+.x-toolbar-cell .xtb-text{display:none;left:0;position:absolute;right:0;top:2px}.x-combo-list .x-toolbar .x-toolbar-cell+.x-toolbar-cell+.x-toolbar-cell+.x-toolbar-cell+.x-toolbar-cell .xtb-text{bottom:4px;display:inline-block;left:0;position:absolute;right:0;top:auto}.x-combo-list .x-toolbar .x-toolbar-cell+.x-toolbar-cell+.x-toolbar-cell+.x-toolbar-cell+.x-toolbar-cell+.x-toolbar-cell+.x-toolbar-cell+.x-toolbar-cell+.x-toolbar-cell .x-btn{margin-right:0}.x-combo-list .x-toolbar .x-toolbar-cell:last-child{opacity:0;transition:opacity .25s}.x-combo-list .x-toolbar .x-toolbar-cell:last-child .x-btn{bottom:2px;font-size:12px;line-height:1;margin:0;opacity:.4;padding:0;position:absolute;right:1px}.x-combo-list .x-toolbar .x-toolbar-cell:last-child .x-btn:hover{opacity:1}.x-combo-list .x-toolbar .x-toolbar-cell:last-child .x-btn button{height:16px;width:16px}.x-combo-list .x-toolbar .x-toolbar-cell:last-child .x-btn button:before{font-size:12px}.x-combo-list .x-toolbar:hover .x-toolbar-cell:last-child{opacity:1}.x-combo-list .x-resizable-handle-southeast{bottom:1px;right:3px}.x-combo-list.modx-superboxselect .x-combo-list-inner{margin-left:0}.x-combo-list-hd{background-image:url(../images/modx-theme/layout/panel-title-light-bg.gif);border-bottom-color:#bcbcbc;color:#464646}.x-combo-list-small{font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.x-date-mp,.x-date-picker{background-color:#fbfbfb}.x-date-mp .x-btn,.x-date-mp .x-date-mp-cancel,.x-date-mp .x-date-mp-ok,.x-date-picker .x-btn,.x-date-picker .x-date-mp-cancel,.x-date-picker .x-date-mp-ok{border:0;margin:0 0 0 7px;padding:5px 10px}.x-date-mp .x-btn:first-child,.x-date-mp .x-date-mp-cancel:first-child,.x-date-mp .x-date-mp-ok:first-child,.x-date-picker .x-btn:first-child,.x-date-picker .x-date-mp-cancel:first-child,.x-date-picker .x-date-mp-ok:first-child{margin:0}.x-date-mp .x-btn button,.x-date-mp .x-date-mp-cancel button,.x-date-mp .x-date-mp-ok button,.x-date-picker .x-btn button,.x-date-picker .x-date-mp-cancel button,.x-date-picker .x-date-mp-ok button{font-size:11px;font-style:normal;margin:0}.x-date-mp .x-date-mp-cancel,.x-date-mp .x-date-mp-ok,.x-date-picker .x-date-mp-cancel,.x-date-picker .x-date-mp-ok{height:16px}.x-date-middle{padding:5px 3px}.x-date-left a,.x-date-mp-ybtn a.x-date-mp-next,.x-date-mp-ybtn a.x-date-mp-prev,.x-date-right a{display:inline-block;filter:alpha(opacity=60);margin:0 auto;opacity:.6;position:relative;transition:opacity .25s}.x-date-left a:before,.x-date-mp-ybtn a.x-date-mp-next:before,.x-date-mp-ybtn a.x-date-mp-prev:before,.x-date-right a:before{box-sizing:border-box;color:#234368;content:"";font-size:18px;height:18px;left:0;position:absolute;text-align:center;top:0;vertical-align:middle;width:18px}.x-date-left a:hover,.x-date-mp-ybtn a.x-date-mp-next:hover,.x-date-mp-ybtn a.x-date-mp-prev:hover,.x-date-right a:hover{filter:alpha(opacity=100);opacity:1}.x-date-mp-ybtn a.x-date-mp-next:before,.x-date-right a:before{content:"\f0da";left:auto;right:0}.x-date-left a:before,.x-date-mp-ybtn a.x-date-mp-prev:before{content:"\f0d9"}.x-date-inner{margin:0 auto}.x-date-inner th{border-bottom-color:#e4e4e4;color:#515151;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-weight:700}.x-date-inner td,.x-date-mp td{background-color:#fff;border:0;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;padding:1px}.x-date-inner a,td.x-date-mp-month a,td.x-date-mp-year a{border-radius:3px;color:#999;font:inherit;font-weight:700}td.x-date-mp-month a,td.x-date-mp-year a{margin:0 3px}.x-date-inner .x-date-disabled a:hover,.x-date-inner .x-date-nextday a:hover,.x-date-inner .x-date-prevday a:hover,.x-date-inner a:hover,td.x-date-mp-month a:hover,td.x-date-mp-year a:hover{background-color:#dcdcdc;color:#515151}.x-date-inner .x-date-disabled a{background-color:#e4e4e4;color:#999}.x-date-inner .x-date-active{color:#000}.x-date-inner .x-date-today a{border-color:#234368}.x-date-inner span{font-style:normal}.x-date-inner .x-date-active span,.x-date-inner .x-date-selected span{font-weight:700}.x-date-inner .x-date-selected a,td.x-date-mp-sel a{background-color:#234368;border-color:#fff;color:#fff}.x-date-inner .x-date-nextday a,.x-date-inner .x-date-prevday a{color:#dcdcdc}.x-date-bottom,.x-date-mp-btns{border-top:1px solid #e4e4e4;padding:5px}.x-date-bottom td,.x-date-mp-btns td{background-color:initial;border-top:1px solid #e4e4e4}td.x-date-mp-sep{border-right:1px solid #e4e4e4}.x-date-mmenu{background-color:#eee!important}.x-date-mmenu .x-menu-item{color:#000;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.radio-version .x-form-check-wrap .x-form-cb-label{display:block}.radio-version .x-form-check-wrap .x-form-cb-label .changelog{float:right}.x-form-template-picker .x-form-template-picker-search{padding:0!important}.x-form-template-picker .x-form-template-picker-templates .x-form-radio-group{background-color:#fff;border:1px solid #e4e4e4;border-radius:3px;height:194px;overflow:auto}.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-category,.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-item{border-bottom:1px solid #e4e4e4}.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-category:last-child,.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-item:last-child{border-bottom:0}.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-category .x-form-check-wrap .x-form-cb-label,.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-item .x-form-check-wrap .x-form-cb-label{display:block}.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-category .x-form-check-wrap .x-form-cb-label:before,.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-item .x-form-check-wrap .x-form-cb-label:before{display:none}.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-category .x-form-check-wrap .x-form-radio:checked+.x-form-cb-label,.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-category .x-form-check-wrap:not(.x-item-disabled) .x-form-cb-label:hover,.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-item .x-form-check-wrap .x-form-radio:checked+.x-form-cb-label,.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-item .x-form-check-wrap:not(.x-item-disabled) .x-form-cb-label:hover{background-color:#e4e4e4;color:#1b3451}.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-item{padding:0!important}.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-item .x-form-cb-label{padding:10px 14px}.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-category{padding:0!important}.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-category .x-form-cb-label{font-weight:700!important;padding:10px 8px}.x-form-template-picker .x-form-template-picker-templates .x-form-template-picker-category .x-item-disabled{filter:alpha(opacity=100);opacity:1;-moz-opacity:1}.x-form-template-preview{background-color:#fff;background:url(../images/tp-no-preview.png) no-repeat 50%;border:1px solid #e4e4e4;border-radius:3px;height:236px;overflow:hidden}.x-form-template-preview .x-panel-body,.x-form-template-preview .x-panel-bwrap{height:100%;position:relative}.x-form-template-preview .x-form-template-preview-image{height:100%;-o-object-fit:cover;object-fit:cover}.x-form-template-preview .x-form-template-preview-desc{background-color:#000c;bottom:0;color:#fff;left:0;padding:10px 20px;position:absolute;right:0}#modx-tv-tabs{width:100%}.x-tab-panel-noborder{border:1px solid #e2e3de;margin:20px 0;overflow:visible}.x-tab-panel-noborder .x-tab-panel-body-noborder{background-color:#fff;border-radius:3px}.x-tab-panel-footer,.x-tab-panel-header{border:0;position:relative}.x-tab-panel-header ul.x-tab-strip{background-color:initial!important;border:0;margin:0;position:relative;top:1px}.x-tab-panel-footer-plain .x-tab-strip-spacer,.x-tab-panel-header-plain .x-tab-strip-spacer{border:none;height:0}.x-tab-panel .x-tab-panel{padding-top:18px}.x-tab-panel .x-tab-panel.vertical-tabs-panel{padding-top:0}.x-tab-panel .x-tab-panel .x-tab-strip-wrap .x-tab-strip{background-color:#fbfbfb!important}.x-tab-panel-header,.x-tab-strip{padding-left:0}.x-tab-panel-bwrap{border-radius:3px;overflow:visible}.x-tab-panel-bwrap .x-tab-panel-bwrap{box-shadow:none}ul.x-tab-strip li{background-color:initial;border-top-left-radius:3px;border-top-right-radius:3px;color:#53595f;cursor:pointer;font:14px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;line-height:2.2;margin-left:0;padding:0 12px;position:relative;z-index:1}html[dir=rtl] ul.x-tab-strip li{float:right}ul.x-tab-strip li:hover{background-color:#e4e4e4;color:#000}ul.x-tab-strip li.x-tab-strip-active{background-color:#fff;color:#234368;cursor:default}.vertical-tabs-header ul.x-tab-strip li.x-tab-strip-active{border-radius:0}ul.x-tab-strip li.x-tab-strip-active:hover{background-color:#fff}ul.x-tab-strip li.x-tab-edge{height:0;visibility:hidden}.x-tab-panel,.x-tab-panel-header,.x-tab-strip-wrap{border:none;overflow:visible}.x-tab-strip-wrap{margin:0;overflow:hidden;padding:2px 0 0}.x-tab-strip-closable{padding-right:15px!important}.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close{background-image:url(../images/modx-theme/tabs/tab-close.gif);right:2px}ul.x-tab-strip-top li:first-child{margin-left:0}ul.x-tab-strip-bottom{background-color:#f4f4f4;border-top-color:#dfdfdf}ul.x-tab-strip-bottom .x-tab-right{background-image:url(../images/modx-theme/tabs/tab-btm-inactive-right-bg.gif)}ul.x-tab-strip-bottom .x-tab-right .x-tab-right{background-image:url(../images/modx-theme/tabs/tab-btm-right-bg.gif)}ul.x-tab-strip-bottom .x-tab-right .x-tab-left{background-image:url(../images/modx-theme/tabs/tab-btm-left-bg.gif)}ul.x-tab-strip-bottom .x-tab-left{background-image:url(../images/modx-theme/tabs/tab-btm-inactive-left-bg.gif)}.x-tab-panel-body{background-color:#fff;border:0;overflow:visible}.x-tab-scroller-left,.x-tab-scroller-right{border:0}.x-tab-scroller-left:before,.x-tab-scroller-right:before{box-sizing:border-box;color:#383838;content:"";filter:alpha(opacity=100);font-size:28px;margin-top:-20px;opacity:1;position:absolute;right:0;text-align:center;top:50%;transition:opacity .25s;width:18px}.x-tab-scroller-left-over:before,.x-tab-scroller-right-over:before{color:#234368}.x-tab-scroller-left-disabled,.x-tab-scroller-right-disabled{cursor:default}.x-tab-scroller-left-disabled:before,.x-tab-scroller-right-disabled:before{color:#383838;filter:alpha(opacity=100);opacity:.4}.x-tab-scroller-left:before{content:"\f0d9"}.x-tab-scroller-right:before{content:"\f0da"}.x-tab-panel-bbar .x-toolbar,.x-tab-panel-tbar .x-toolbar{border-color:#dfdfdf}.x-tab-panel-body-noborder .x-panel-body-noheader:first-child{border-top:0}.x-tab-panel-bbar-noborder .x-toolbar{border-top-color:#0000}.x-tab-panel-tbar-noborder .x-toolbar{border-bottom-color:#0000}.vertical-tabs-panel{background-color:#fff;margin:0;overflow:hidden}.vertical-tabs-panel.wrapped{border:1px solid #e4e4e4}.vertical-tabs-panel .vertical-tabs-header{background:#fff!important;border-right:1px solid #e4e4e4!important;float:left;margin-bottom:-10000px;padding-bottom:10000px!important;width:168px!important}@media screen and (max-width:960px){.vertical-tabs-panel .vertical-tabs-header{width:80px!important}}.vertical-tabs-panel .vertical-tabs-header .x-tab-strip-wrap{background-color:initial;display:inline-block;line-height:0;margin:0;padding:0;width:auto!important}.vertical-tabs-panel .vertical-tabs-header .x-tab-strip-wrap ul.x-tab-strip{border:0;display:inline-block;top:0;width:auto}.vertical-tabs-panel .vertical-tabs-header .x-tab-strip-wrap ul.x-tab-strip>li{border-bottom:1px solid #e4e4e4;border-right:1px solid #e4e4e4;color:#515151;float:none;line-height:1;margin:0;overflow:hidden;padding:10px 15px;transition:background-color .25s,color .25s}@media screen and (max-width:960px){.vertical-tabs-panel .vertical-tabs-header .x-tab-strip-wrap ul.x-tab-strip>li{font-size:12px;padding:8px}}.vertical-tabs-panel .vertical-tabs-header .x-tab-strip-wrap ul.x-tab-strip>li:hover{background:#fff}.vertical-tabs-panel .vertical-tabs-header .x-tab-strip-wrap ul.x-tab-strip>li.x-tab-strip-active{background:#fff;border-color:#234368 #fff #234368 #234368;box-shadow:none;color:#234368;width:168px}@media screen and (max-width:960px){.vertical-tabs-panel .vertical-tabs-header .x-tab-strip-wrap ul.x-tab-strip>li.x-tab-strip-active{width:80px!important}}.vertical-tabs-panel .vertical-tabs-header .x-tab-strip-wrap ul.x-tab-strip>li.x-tab-edge{height:0;visibility:hidden}.vertical-tabs-panel .vertical-tabs-header .x-tab-strip-wrap ul.x-tab-strip>li.x-tab-edge .x-tab-strip-text{display:none}.vertical-tabs-panel .vertical-tabs-header .x-tab-strip-wrap ul.x-tab-strip>li .x-tab-strip-text{line-height:1.4;padding:2px 0;white-space:pre-wrap}.vertical-tabs-panel .vertical-tabs-header h4{background:#fff;border-bottom:1px solid #e4e4e4;color:#53595f;font-size:16px;padding:15px 0 15px 15px}.vertical-tabs-panel .vertical-tabs-header .x-tab-strip-spacer{display:none}.vertical-tabs-panel .x-tab-panel-bwrap{box-shadow:none}.vertical-tabs-panel .x-tab-panel-bwrap .x-tab-panel-body{border-top:0;width:auto!important}.vertical-tabs-panel .x-tab-panel-bwrap .vertical-tabs-body{border:0;padding:15px 20px 15px 15px}.tvs-wrapper.below-content{border-radius:3px;margin:1rem}.tvs-wrapper.below-content .vertical-tabs-panel{border-radius:3px}@media screen and (max-width:960px){.tvs-wrapper.below-content{margin:0}}.window-vtabs .x-panel-mr{padding-right:0}.window-vtabs .vertical-tabs-panel{margin:0;width:100%!important}#modx-split-wrapper .x-border-layout-ct{background:#0000}#modx-leftbar-tabs-xcollapsed{display:none!important}#modx-leftbar{background-color:#fff;min-width:288px;z-index:0}@media screen and (min-width:961px){#modx-leftbar{max-width:50%}}#modx-leftbar .x-toolbar{border:0;padding:0!important}#modx-header{background:#234368;height:100%;max-width:70px;position:absolute;z-index:2}#modx-navbar{display:flex;flex-direction:column;font-weight:700;font:normal 13px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;height:100%;padding:0 5px}#modx-navbar .icon{color:#fff;font-size:20px;line-height:20px;vertical-align:middle}#modx-navbar a,#modx-navbar li{background:#0000;margin:0;padding:0;position:relative;text-align:center;width:100%}#modx-navbar a{color:#fff;cursor:pointer;display:block;font-size:10px;line-height:12px;text-decoration:none}#modx-navbar a .description{font-size:9px;opacity:.7}#modx-navbar a .description,#modx-navbar a .icon,#modx-navbar a .label{display:block;width:100%}#modx-navbar li a:hover{opacity:.7}#modx-navbar #modx-user-menu a .description,#modx-navbar #modx-user-menu a .label{display:none}#modx-navbar #modx-user-menu a #user-username{align-self:center;max-width:7ch;overflow:hidden;padding-top:.25rem;text-overflow:ellipsis;white-space:nowrap}#modx-navbar #modx-leftbar-trigger a,#modx-navbar #modx-manager-search-icon a,#modx-navbar #modx-user-menu a{padding:12px 0}#modx-navbar #modx-topnav{list-style:none;margin:0;padding:0}#modx-navbar #modx-topnav>li{border-top:1px solid #ffffff1a}#modx-navbar #modx-topnav>li:not(#modx-home-dashboard):not(#modx-manager-search-icon):not(#modx-leftbar-trigger)>a{display:block;padding:12px 0;position:relative}#modx-navbar #modx-user-menu{margin-top:auto}#modx-navbar #modx-user-menu #user-avatar img{border-radius:20px;display:block;height:40px;margin:auto;width:40px}#modx-navbar #modx-user-menu #limenu-user a{display:flex;flex-direction:column;justify-content:center}#modx-navbar #modx-home-dashboard{border-radius:3px;height:40px;line-height:40px;padding:10px;width:40px}#modx-navbar #modx-site-info{font-size:10px}#modx-navbar #modx-site-info .full_appname,#modx-navbar #modx-site-info .site_name{color:#fff}#modx-navbar #modx-site-info>.info-item{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#modx-leftbar-trigger{transition:all .2s ease}#modx-leftbar-trigger .icon:before{content:"\f060"}#modx-leftbar-trigger.collapsed .icon:before{content:"\f061"!important}#modx-footer .modx-subnav,#modx-header .modx-subnav{background:#fff;border:1px solid #ffffff1a;border-radius:3px;box-shadow:0 0 15px 0 #0003;box-sizing:border-box;display:block;list-style:none;opacity:0;position:absolute;transition:all .15s ease;visibility:hidden}#modx-footer .modx-subnav li,#modx-header .modx-subnav li{background:#fff;border-radius:3px;display:block;margin:0;padding:0;position:relative}#modx-footer .modx-subnav li:not(:first-child),#modx-header .modx-subnav li:not(:first-child){border-top:1px solid #e4e4e4}#modx-footer .modx-subnav li:hover:after,#modx-header .modx-subnav li:hover:after{border-right-color:#e4e4e4}#modx-footer .modx-subnav li.sub:after,#modx-header .modx-subnav li.sub:after{color:#999;content:"\f0da";font-size:14px;margin-top:0;position:absolute;right:10px;top:50%;transform:translateY(-50%)}#modx-footer .modx-subnav li a,#modx-header .modx-subnav li a{background-color:#fff;border-radius:3px;color:#515151;cursor:pointer;display:block;font-size:13px;font-weight:700;line-height:1.5;margin:0;padding:8px 15px;text-align:left;text-decoration:none;text-shadow:none;width:270px}#modx-footer .modx-subnav li a .icon,#modx-header .modx-subnav li a .icon{display:inline-block;font-size:18px;opacity:.07;padding-left:5px}#modx-footer .modx-subnav li a span,#modx-header .modx-subnav li a span{color:#999;display:block;float:none;font-size:12px;font-weight:400;line-height:1.3;margin-top:6px;width:100%}#modx-footer .modx-subnav li a:hover,#modx-header .modx-subnav li a:hover{background:#e4e4e4;border-bottom-color:#e4e4e4;border-top-color:#e4e4e4;color:#53595f}#modx-footer .modx-subnav li a:hover .description,#modx-header .modx-subnav li a:hover .description{color:#707070}#modx-footer .modx-subnav.active,#modx-header .modx-subnav.active{opacity:1;visibility:visible}#modx-footer .modx-subnav .modx-subsubnav,#modx-header .modx-subnav .modx-subsubnav{background:#fff;border:1px solid #ffffff1a;border-radius:3px;box-shadow:0 0 15px 0 #0003;list-style:none;position:absolute}#modx-footer .modx-subnav .modx-subsubnav-arrow,#modx-header .modx-subnav .modx-subsubnav-arrow{border:8px solid #0000;border-right-color:#fff;content:" ";display:none;pointer-events:none;position:absolute;right:0;top:50%;transform:translateY(-50%)}#modx-footer .modx-subnav .modx-subsubnav.active+.modx-subsubnav-arrow,#modx-header .modx-subnav .modx-subsubnav.active+.modx-subsubnav-arrow{display:block}@media screen and (min-width:961px){#modx-footer .modx-subnav .modx-subsubnav,#modx-header .modx-subnav .modx-subsubnav{opacity:0;visibility:hidden}#modx-footer .modx-subnav .modx-subsubnav.active,#modx-header .modx-subnav .modx-subsubnav.active{opacity:1;visibility:visible}}#modx-footer .modx-subnav-arrow,#modx-header .modx-subnav-arrow{border:12px solid #0000;border-right-color:#fff;content:" ";margin-top:-6px;pointer-events:none;position:absolute;right:100%}#modx-footer #language .modx-subsubnav,#modx-header #language .modx-subsubnav{max-height:calc(100vh - 12px);overflow-x:hidden;overflow-y:auto}@media screen and (max-width:960px){#modx-header{height:auto!important;min-width:100%;position:relative}#modx-navbar{flex-direction:row;flex-wrap:wrap}#modx-navbar #modx-headnav{order:1;width:50%}#modx-navbar #modx-headnav a{line-height:normal!important}#modx-navbar #modx-headnav img{max-width:35px}#modx-navbar #modx-topnav{order:0;width:100%}#modx-navbar #modx-user-menu{flex-direction:row-reverse;flex-wrap:nowrap;margin-top:0;order:2;width:50%}#modx-navbar>ul{align-items:center;display:flex;flex-wrap:wrap;justify-content:center}#modx-navbar>ul>li{flex-basis:50px}#modx-navbar #modx-site-info{display:none}#modx-navbar #modx-home-dashboard{margin:0;padding:5px}#modx-leftbar-trigger .icon{padding:3px 4px}#modx-leftbar-trigger .icon:before{content:"\f062"}#modx-leftbar-trigger.collapsed .icon:before{content:"\f063"!important}#modx-footer .modx-subnav,#modx-header .modx-subnav{min-width:300px}#modx-footer .modx-subnav .description,#modx-header .modx-subnav .description{display:none}#modx-footer .modx-subnav li,#modx-header .modx-subnav li{border-radius:0}#modx-footer .modx-subnav li.sub:after,#modx-header .modx-subnav li.sub:after{display:none}#modx-footer .modx-subnav li a,#modx-header .modx-subnav li a{white-space:nowrap;width:auto}#modx-footer .modx-subnav .modx-subsubnav,#modx-header .modx-subnav .modx-subsubnav{box-shadow:none;display:block;left:auto;max-height:none!important;overflow-y:initial!important;position:static}#modx-footer .modx-subnav .modx-subsubnav li>a,#modx-header .modx-subnav .modx-subsubnav li>a{margin-left:1rem}#modx-footer .modx-subnav-arrow,#modx-header .modx-subnav-arrow{display:none}#modx-footer .modx-subnav,#modx-header .modx-subnav{max-height:calc(100vh - 109px);overflow-x:hidden;overflow-y:auto}}@media (max-height:520px){#modx-footer .modx-subnav .description,#modx-header .modx-subnav .description{display:none}}#modx-manager-search{background:#fff;border-radius:3px 3px 0 0;height:38px;min-width:100px;padding:10px 10px 5px}#modx-manager-search .x-form-text{background:none}#modx-manager-search .x-form-field-wrap{background-image:none;color:#565353;font-size:12px;outline:none!important}#modx-manager-search .x-form-field-wrap .x-form-text{color:#515151;font-weight:400;letter-spacing:0;text-shadow:none}#modx-manager-search .x-form-field-wrap .x-form-empty-field{color:#6a747a}#modx-manager-search .x-form-field-wrap .x-form-trigger{display:none}.modx-manager-search-results{background:#e4e4e4;border:1px solid #e4e4e4;border-radius:0 0 3px 3px;box-shadow:0 4px 10px 0 #0003;box-sizing:border-box;height:auto!important;position:relative;width:402px!important}.modx-manager-search-results .loading-indicator{background:none;color:#515151;font-size:14px;margin:10px 0;text-align:center}.modx-manager-search-results .loading-indicator:before{content:"\f110";margin-right:5px}.modx-manager-search-results .x-combo-list-inner{background:#fff;border:0;margin:0;overflow:auto;width:100%!important}@media screen and (max-width:960px){.modx-manager-search-results .x-combo-list-inner{height:auto!important;line-height:4em}.modx-manager-search-results .x-combo-list-inner .section>*{padding-bottom:.5em;padding-top:.5em}}.modx-manager-search-results .section{border-left:1px solid #ededed;font-size:12px;line-height:12px;margin-left:100px;position:relative;width:auto}.modx-manager-search-results .x-combo-list-item,.modx-manager-search-results h3{color:#515151;line-height:18px;margin:0;padding:4px 6px}.modx-manager-search-results h3{color:#53595f;font-size:11px;font-weight:400;left:-108px;line-height:11px;position:absolute;text-align:right;top:0;width:95px}.modx-manager-search-results a{color:inherit;cursor:pointer;display:inline-block;padding-left:20px;position:relative;text-decoration:none}.modx-manager-search-results i{color:#234368;left:0;position:absolute;top:4px}.modx-manager-search-results em{font-style:normal;opacity:.7}.modx-manager-search-results .x-combo-list-item{overflow:visible;white-space:normal}.modx-manager-search-results .x-combo-list-item a{display:block}.modx-manager-search-results .x-combo-list-item.x-combo-selected,.modx-manager-search-results .x-combo-list-item:hover{background-color:#e4e4e4;border:0;margin-left:0;z-index:10}.modx-manager-search-results .x-combo-list-item.x-combo-selected h3,.modx-manager-search-results .x-combo-list-item:hover h3{left:0}.modx-manager-search-results .x-combo-list-item.x-combo-selected p,.modx-manager-search-results .x-combo-list-item:hover p{border-left-color:#0000}.modx-manager-search-results .x-combo-list-item.x-combo-selected a,.modx-manager-search-results .x-combo-list-item:hover a{color:#515151}.modx-manager-search-results .icon-user{background-image:none!important}.breadcrumbs .panel-desc{margin-top:0}.crumb_wrapper{background:#fbfbfb;border-bottom:1px solid #e4e4e4;border-top:1px solid #e4e4e4;margin-top:15px}.crumb_wrapper .crumbs{height:34px;overflow:hidden}.crumb_wrapper .crumbs li{color:#53595f;float:left;font-size:12px;font-weight:400;line-height:12px;padding:0 0 0 20px;position:relative;z-index:1}.crumb_wrapper .crumbs li.first{padding:0}.crumb_wrapper .crumbs li.first:before{content:"\f015";display:inline-block;font-size:20px;left:0;line-height:34px;position:absolute;text-align:center;text-indent:0;top:0;z-index:2}#packages-breadcrumbs .crumb_wrapper .crumbs li.first:before{content:"\f1b2"}.crumb_wrapper .crumbs li.first:hover:before{color:#fff}.crumb_wrapper .crumbs li.first:hover{background-color:#515151}.crumb_wrapper .crumbs li.first .root{background-color:initial;box-sizing:initial;display:inline-block;line-height:12px;margin:0;padding:12px;text-indent:-999em;width:35px;z-index:3}.crumb_wrapper .crumbs li.first .root:before{display:none}.crumb_wrapper .crumbs li.first .root:hover{background-color:initial}.crumb_wrapper .crumbs li:hover button,.crumb_wrapper .crumbs li:hover span,.crumb_wrapper .crumbs li:hover span:after{background-color:#515151;color:#fff}.crumb_wrapper .crumbs li:hover button:after,.crumb_wrapper .crumbs li:hover span:after{border-color:#fbfbfb #fbfbfb #515151 #515151;border-style:solid;border-width:1px}.crumb_wrapper .crumbs li:hover button:before,.crumb_wrapper .crumbs li:hover span:before{background-color:#515151}.crumb_wrapper .crumbs li:hover+li button:before,.crumb_wrapper .crumbs li:hover+li span:before{border-left-color:#515151}.crumb_wrapper .crumbs li button{background-color:initial;border:0;color:#53595f;cursor:pointer;font:normal 12px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-weight:700;line-height:1;text-decoration:none}.crumb_wrapper .crumbs li span{background-color:#fbfbfb}.crumb_wrapper .crumbs li button,.crumb_wrapper .crumbs li span{display:inline-block;margin:0 0 0 1px;padding:11px 13px 11px 15px;position:relative}.crumb_wrapper .crumbs li button:before,.crumb_wrapper .crumbs li span:before{background-color:initial;border-bottom:50px solid #0000;border-left:30px solid #fbfbfb;border-top:50px solid #0000;content:"";display:inline-block;height:0;left:-33px;margin-top:-50px;padding-right:3px;position:absolute;top:50%;transform:scale(.99999);width:0;z-index:-1}.crumb_wrapper .crumbs li button:after,.crumb_wrapper .crumbs li span:after{background-color:#fbfbfb;border:1px solid #dcdcdc;border-bottom:0;border-left:0;border-radius:3px;content:"";display:inline-block;height:34px;position:absolute;right:-22px;top:0;transform:scaleX(.6) rotate(45deg);width:34px;z-index:-1}.x-toolbar{background-color:#f7f7f7;background-image:none;border-color:#dfdfdf}.x-toolbar .x-toolbar-cell label,.x-toolbar .xtb-text{margin:0 5px 0 7px;padding:0}.x-toolbar .x-item-disabled{filter:alpha(opacity=60);opacity:.6}.x-toolbar td.x-toolbar-cell:first-of-type .xtb-text{margin-left:0}.x-toolbar div,.x-toolbar input,.x-toolbar label,.x-toolbar select,.x-toolbar span,.x-toolbar td{font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;line-height:0}.x-toolbar .x-btn-group-header{line-height:1}.x-toolbar em.x-btn-split-bottom{background-image:url(../images/modx-theme/button/s-arrow-b-noline.gif)}.x-toolbar .x-btn-click em.x-btn-split-bottom,.x-toolbar .x-btn-menu-active em.x-btn-split-bottom,.x-toolbar .x-btn-over em.x-btn-split-bottom,.x-toolbar .x-btn-pressed em.x-btn-split-bottom{background-image:url(../images/modx-theme/button/s-arrow-bo.gif)}.ext-ie .x-toolbar-cell .x-form-field-wrap{height:30px}.x-tbar-page-first{background-image:url(../images/modx-theme/grid/page-first.png)!important}.x-tbar-loading{background-image:url(../images/modx-theme/grid/refresh.png)!important}.x-tbar-page-last{background:none!important;position:relative}.x-tbar-page-last:before{content:"\f04e";left:1px;right:auto;top:1px}.x-tbar-page-next{background:none!important;position:relative}.x-tbar-page-next:before{content:"\f0da";font-size:18px;left:1px;line-height:110%;right:auto}.x-tbar-page-prev{background:none!important;position:relative}.x-tbar-page-prev:before{content:"\f0d9";font-size:18px;left:auto;line-height:110%;right:1px}.x-tbar-loading{background:none!important;position:relative}.x-tbar-loading:before{bottom:auto;content:"\f01e";top:1px}.x-tbar-page-first{background:none!important;position:relative}.x-tbar-page-first:before{content:"\f04a";left:auto;right:1px;top:1px}.x-paging-info{color:#444}.x-toolbar-more-icon{background-image:url(../images/modx-theme/toolbar/more.gif)!important}.x-panel-bbar{padding-top:10px}.modx-browser-rte-buttons .x-panel-bbar{background-color:#fff;border-top:1px solid #fff;padding:5px}.modx-browser-rte-buttons .x-panel-bbar .x-toolbar-layout-ct{width:auto!important}.x-panel-bbar .x-toolbar{background-color:initial;border:0;overflow:hidden;padding:2px 0}.x-panel-bbar .x-toolbar .x-form-text{padding:5px 10px}.x-panel-bbar .x-toolbar .x-form-text.x-tbar-page-number,.x-panel-bbar .x-toolbar .x-form-text.x-tbar-page-size{width:32px}.x-panel-bbar .x-toolbar .x-form-text.x-tbar-page-number{margin-right:3px}.x-panel-bbar .x-toolbar .x-btn{margin-right:10px;padding:8px 13px}.modx-browser-rte .x-panel-bbar .x-toolbar .x-btn{margin-right:0;padding:10px 15px}.x-panel-bbar .x-toolbar .xtb-text{margin:0 3px 0 0}.x-panel-tbar{overflow:visible;padding-bottom:4px}.x-panel-tbar .x-toolbar{border:0;overflow:visible;padding:5px 0}.x-panel-tbar .x-toolbar td{vertical-align:bottom}.x-panel-tbar .x-toolbar input.filter-query{bottom:-1px;position:relative}.x-panel-mc .x-panel-tbar .x-toolbar{background-image:none;border:0;padding:15px 0 7px}.x-panel-tbar-noheader .x-toolbar{background-color:initial;background-image:none;border:0;padding:5px 0}.x-toolbar div,.x-toolbar input,.x-toolbar label,.x-toolbar select,.x-toolbar span,.x-toolbar td{border-radius:3px}.x-html-editor-tb .x-btn-text{background-image:url(../images/modx-theme/editor/tb-sprite.gif)}.x-panel-noborder .x-panel-tbar-noborder .x-toolbar{background-color:initial;border-bottom-color:#0000}.x-panel-noborder .x-panel-bbar-noborder .x-toolbar{border-top-color:#0000}#modx-leftbar .x-tab-panel-noborder{margin:0 8px}#modx-leftbar .x-tab-panel-bwrap{border-radius:0 0 3px 3px;position:relative;z-index:1}#modx-leftbar .x-tab-panel-bwrap .x-tab-panel-body-noborder{background:#f1f1f1;border-radius:0 0 3px 3px}@media screen and (max-width:960px){#modx-leftbar #modx-leftbar-tabpanel{margin:0 auto;padding:.5em;width:auto!important}#modx-leftbar{box-shadow:none;height:auto!important;left:auto!important;margin:0 auto 10px;position:relative!important;top:auto!important;width:100%!important}#modx-leftbar #modx-leftbar-header{display:none}#modx-leftbar .x-plain-body{height:auto!important;width:100%!important}}#modx-leftbar .x-panel-tbar{padding:0}#modx-leftbar .x-toolbar{padding:4px 5px 2px 0}#modx-leftbar .x-tree-root-ct{padding:6px}#modx-leftbar .x-tree .x-panel-body{background:#fff;border-radius:0}#modx-tree-usergroup .x-toolbar-left-row{display:flex;flex-wrap:wrap}#modx-resource-tree-tbar .x-toolbar-left .x-btn .tree-new-resource,#modx-tree-element .x-toolbar-left .x-btn .tree-new-template{margin-left:16px}#modx-split-wrapper #modx-leftbar-tabs-xcollapsed,#modx-split-wrapper .x-layout-split{margin-left:-70px}.x-layout-split{overflow:visible;width:8px;z-index:2}.x-layout-split:hover{background:#999}#modx-leftbar-tabs-xcollapsed .x-layout-mini{left:0}#modx-leftbar-tabs-xcollapsed .x-layout-mini:after{border-left:5px solid #383838;border-right:0}@media screen and (max-width:960px){#modx-leftbar-tabs-xcollapsed .x-layout-mini:after{border:none}}#modx-leftbar-tabs-xcollapsed .x-layout-mini:hover:after{border-left-color:#234368}.modx-tree{padding:0}#modx-file-tree .modx-tree:first-child{padding-top:4px}.x-tree-arrows .x-tree-elbow-end-minus,.x-tree-arrows .x-tree-elbow-end-plus,.x-tree-arrows .x-tree-elbow-minus,.x-tree-arrows .x-tree-elbow-plus{background:none}.x-tree-arrows .x-tree-elbow-end-minus:hover,.x-tree-arrows .x-tree-elbow-end-plus:hover,.x-tree-arrows .x-tree-elbow-minus:hover,.x-tree-arrows .x-tree-elbow-plus:hover{background:#d9d9d9;border-radius:50%}.x-tree-arrows .x-tree-elbow-end-minus:before,.x-tree-arrows .x-tree-elbow-end-plus:before,.x-tree-arrows .x-tree-elbow-minus:before,.x-tree-arrows .x-tree-elbow-plus:before{background:#0000 0 0;content:"\f0da";display:inline-block;margin:0;padding-left:4px;padding-right:4px;text-align:center;width:10px}.x-tree-arrows .x-tree-elbow-end-minus:before,.x-tree-arrows .x-tree-elbow-minus:before{content:"\f0d7"}.x-tree-node-el{background-position:5px;background-repeat:no-repeat;color:#383838;font:normal 14px/2.25 -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;padding:0 8px}.x-tree-node-el.is_folder{background:#0000}.x-tree-node-el .x-btn{box-shadow:none}.x-tree-node-el .icon{display:inline-block;font-size:1.15em;line-height:.75em;vertical-align:-15%;width:1em}.x-tree-node-el a span{padding-left:7px}.x-tree-node-el a span span{padding-left:0}i.icon,i.icon-large{font-style:normal}.deleted i.icon-large.fa-address-book:before,.deleted i.icon-large.fa-address-card:before,.deleted i.icon-large.fa-angry:before,.deleted i.icon-large.fa-arrow-alt-circle-down:before,.deleted i.icon-large.fa-arrow-alt-circle-left:before,.deleted i.icon-large.fa-arrow-alt-circle-right:before,.deleted i.icon-large.fa-arrow-alt-circle-up:before,.deleted i.icon-large.fa-bell-slash:before,.deleted i.icon-large.fa-bell:before,.deleted i.icon-large.fa-bookmark:before,.deleted i.icon-large.fa-building:before,.deleted i.icon-large.fa-calendar-alt:before,.deleted i.icon-large.fa-calendar-check:before,.deleted i.icon-large.fa-calendar-minus:before,.deleted i.icon-large.fa-calendar-plus:before,.deleted i.icon-large.fa-calendar-times:before,.deleted i.icon-large.fa-calendar:before,.deleted i.icon-large.fa-caret-square-down:before,.deleted i.icon-large.fa-caret-square-left:before,.deleted i.icon-large.fa-caret-square-right:before,.deleted i.icon-large.fa-caret-square-up:before,.deleted i.icon-large.fa-chart-bar:before,.deleted i.icon-large.fa-check-circle:before,.deleted i.icon-large.fa-check-square:before,.deleted i.icon-large.fa-circle:before,.deleted i.icon-large.fa-clipboard:before,.deleted i.icon-large.fa-clock:before,.deleted i.icon-large.fa-clone:before,.deleted i.icon-large.fa-closed-captioning:before,.deleted i.icon-large.fa-comment-alt:before,.deleted i.icon-large.fa-comment-dots:before,.deleted i.icon-large.fa-comment:before,.deleted i.icon-large.fa-comments:before,.deleted i.icon-large.fa-compass:before,.deleted i.icon-large.fa-copy:before,.deleted i.icon-large.fa-copyright:before,.deleted i.icon-large.fa-credit-card:before,.deleted i.icon-large.fa-dizzy:before,.deleted i.icon-large.fa-dot-circle:before,.deleted i.icon-large.fa-edit:before,.deleted i.icon-large.fa-envelope-open:before,.deleted i.icon-large.fa-envelope:before,.deleted i.icon-large.fa-eye-slash:before,.deleted i.icon-large.fa-eye:before,.deleted i.icon-large.fa-file-alt:before,.deleted i.icon-large.fa-file-archive:before,.deleted i.icon-large.fa-file-audio:before,.deleted i.icon-large.fa-file-code:before,.deleted i.icon-large.fa-file-excel:before,.deleted i.icon-large.fa-file-image:before,.deleted i.icon-large.fa-file-pdf:before,.deleted i.icon-large.fa-file-powerpoint:before,.deleted i.icon-large.fa-file-video:before,.deleted i.icon-large.fa-file-word:before,.deleted i.icon-large.fa-file:before,.deleted i.icon-large.fa-flag:before,.deleted i.icon-large.fa-flushed:before,.deleted i.icon-large.fa-folder-open:before,.deleted i.icon-large.fa-folder:before,.deleted i.icon-large.fa-frown-open:before,.deleted i.icon-large.fa-frown:before,.deleted i.icon-large.fa-futbol:before,.deleted i.icon-large.fa-gem:before,.deleted i.icon-large.fa-grimace:before,.deleted i.icon-large.fa-grin-alt:before,.deleted i.icon-large.fa-grin-beam-sweat:before,.deleted i.icon-large.fa-grin-beam:before,.deleted i.icon-large.fa-grin-hearts:before,.deleted i.icon-large.fa-grin-squint-tears:before,.deleted i.icon-large.fa-grin-squint:before,.deleted i.icon-large.fa-grin-stars:before,.deleted i.icon-large.fa-grin-tears:before,.deleted i.icon-large.fa-grin-tongue-squint:before,.deleted i.icon-large.fa-grin-tongue-wink:before,.deleted i.icon-large.fa-grin-tongue:before,.deleted i.icon-large.fa-grin-wink:before,.deleted i.icon-large.fa-grin:before,.deleted i.icon-large.fa-hand-lizard:before,.deleted i.icon-large.fa-hand-paper:before,.deleted i.icon-large.fa-hand-peace:before,.deleted i.icon-large.fa-hand-point-down:before,.deleted i.icon-large.fa-hand-point-left:before,.deleted i.icon-large.fa-hand-point-right:before,.deleted i.icon-large.fa-hand-point-up:before,.deleted i.icon-large.fa-hand-pointer:before,.deleted i.icon-large.fa-hand-rock:before,.deleted i.icon-large.fa-hand-scissors:before,.deleted i.icon-large.fa-hand-spock:before,.deleted i.icon-large.fa-handshake:before,.deleted i.icon-large.fa-hdd:before,.deleted i.icon-large.fa-heart:before,.deleted i.icon-large.fa-hospital:before,.deleted i.icon-large.fa-hourglass:before,.deleted i.icon-large.fa-id-badge:before,.deleted i.icon-large.fa-id-card:before,.deleted i.icon-large.fa-image:before,.deleted i.icon-large.fa-images:before,.deleted i.icon-large.fa-keyboard:before,.deleted i.icon-large.fa-kiss-beam:before,.deleted i.icon-large.fa-kiss-wink-heart:before,.deleted i.icon-large.fa-kiss:before,.deleted i.icon-large.fa-laugh-beam:before,.deleted i.icon-large.fa-laugh-squint:before,.deleted i.icon-large.fa-laugh-wink:before,.deleted i.icon-large.fa-laugh:before,.deleted i.icon-large.fa-lemon:before,.deleted i.icon-large.fa-life-ring:before,.deleted i.icon-large.fa-lightbulb:before,.deleted i.icon-large.fa-list-alt:before,.deleted i.icon-large.fa-map:before,.deleted i.icon-large.fa-meh-blank:before,.deleted i.icon-large.fa-meh-rolling-eyes:before,.deleted i.icon-large.fa-meh:before,.deleted i.icon-large.fa-minus-square:before,.deleted i.icon-large.fa-money-bill-alt:before,.deleted i.icon-large.fa-moon:before,.deleted i.icon-large.fa-newspaper:before,.deleted i.icon-large.fa-object-group:before,.deleted i.icon-large.fa-object-ungroup:before,.deleted i.icon-large.fa-paper-plane:before,.deleted i.icon-large.fa-pause-circle:before,.deleted i.icon-large.fa-play-circle:before,.deleted i.icon-large.fa-plus-square:before,.deleted i.icon-large.fa-question-circle:before,.deleted i.icon-large.fa-registered:before,.deleted i.icon-large.fa-sad-cry:before,.deleted i.icon-large.fa-sad-tear:before,.deleted i.icon-large.fa-save:before,.deleted i.icon-large.fa-share-square:before,.deleted i.icon-large.fa-smile-beam:before,.deleted i.icon-large.fa-smile-wink:before,.deleted i.icon-large.fa-smile:before,.deleted i.icon-large.fa-snowflake:before,.deleted i.icon-large.fa-square:before,.deleted i.icon-large.fa-star-half:before,.deleted i.icon-large.fa-star:before,.deleted i.icon-large.fa-sticky-note:before,.deleted i.icon-large.fa-stop-circle:before,.deleted i.icon-large.fa-sun:before,.deleted i.icon-large.fa-surprise:before,.deleted i.icon-large.fa-thumbs-down:before,.deleted i.icon-large.fa-thumbs-up:before,.deleted i.icon-large.fa-times-circle:before,.deleted i.icon-large.fa-tired:before,.deleted i.icon-large.fa-trash-alt:before,.deleted i.icon-large.fa-user-circle:before,.deleted i.icon-large.fa-user:before,.deleted i.icon-large.fa-window-close:before,.deleted i.icon-large.fa-window-maximize:before,.deleted i.icon-large.fa-window-minimize:before,.deleted i.icon-large.fa-window-restore:before,.deleted i.icon-large.icon-address-book:before,.deleted i.icon-large.icon-address-card:before,.deleted i.icon-large.icon-angry:before,.deleted i.icon-large.icon-arrow-alt-circle-down:before,.deleted i.icon-large.icon-arrow-alt-circle-left:before,.deleted i.icon-large.icon-arrow-alt-circle-right:before,.deleted i.icon-large.icon-arrow-alt-circle-up:before,.deleted i.icon-large.icon-bell-slash:before,.deleted i.icon-large.icon-bell:before,.deleted i.icon-large.icon-bookmark:before,.deleted i.icon-large.icon-building:before,.deleted i.icon-large.icon-calendar-alt:before,.deleted i.icon-large.icon-calendar-check:before,.deleted i.icon-large.icon-calendar-minus:before,.deleted i.icon-large.icon-calendar-plus:before,.deleted i.icon-large.icon-calendar-times:before,.deleted i.icon-large.icon-calendar:before,.deleted i.icon-large.icon-caret-square-down:before,.deleted i.icon-large.icon-caret-square-left:before,.deleted i.icon-large.icon-caret-square-right:before,.deleted i.icon-large.icon-caret-square-up:before,.deleted i.icon-large.icon-chart-bar:before,.deleted i.icon-large.icon-check-circle:before,.deleted i.icon-large.icon-check-square:before,.deleted i.icon-large.icon-circle:before,.deleted i.icon-large.icon-clipboard:before,.deleted i.icon-large.icon-clock:before,.deleted i.icon-large.icon-clone:before,.deleted i.icon-large.icon-closed-captioning:before,.deleted i.icon-large.icon-comment-alt:before,.deleted i.icon-large.icon-comment-dots:before,.deleted i.icon-large.icon-comment:before,.deleted i.icon-large.icon-comments:before,.deleted i.icon-large.icon-compass:before,.deleted i.icon-large.icon-copy:before,.deleted i.icon-large.icon-copyright:before,.deleted i.icon-large.icon-credit-card:before,.deleted i.icon-large.icon-dizzy:before,.deleted i.icon-large.icon-dot-circle:before,.deleted i.icon-large.icon-edit:before,.deleted i.icon-large.icon-envelope-open:before,.deleted i.icon-large.icon-envelope:before,.deleted i.icon-large.icon-eye-slash:before,.deleted i.icon-large.icon-eye:before,.deleted i.icon-large.icon-file-alt:before,.deleted i.icon-large.icon-file-archive:before,.deleted i.icon-large.icon-file-audio:before,.deleted i.icon-large.icon-file-code:before,.deleted i.icon-large.icon-file-excel:before,.deleted i.icon-large.icon-file-image:before,.deleted i.icon-large.icon-file-pdf:before,.deleted i.icon-large.icon-file-powerpoint:before,.deleted i.icon-large.icon-file-video:before,.deleted i.icon-large.icon-file-word:before,.deleted i.icon-large.icon-file:before,.deleted i.icon-large.icon-flag:before,.deleted i.icon-large.icon-flushed:before,.deleted i.icon-large.icon-folder-open:before,.deleted i.icon-large.icon-folder:before,.deleted i.icon-large.icon-frown-open:before,.deleted i.icon-large.icon-frown:before,.deleted i.icon-large.icon-futbol:before,.deleted i.icon-large.icon-gem:before,.deleted i.icon-large.icon-grimace:before,.deleted i.icon-large.icon-grin-alt:before,.deleted i.icon-large.icon-grin-beam-sweat:before,.deleted i.icon-large.icon-grin-beam:before,.deleted i.icon-large.icon-grin-hearts:before,.deleted i.icon-large.icon-grin-squint-tears:before,.deleted i.icon-large.icon-grin-squint:before,.deleted i.icon-large.icon-grin-stars:before,.deleted i.icon-large.icon-grin-tears:before,.deleted i.icon-large.icon-grin-tongue-squint:before,.deleted i.icon-large.icon-grin-tongue-wink:before,.deleted i.icon-large.icon-grin-tongue:before,.deleted i.icon-large.icon-grin-wink:before,.deleted i.icon-large.icon-grin:before,.deleted i.icon-large.icon-hand-lizard:before,.deleted i.icon-large.icon-hand-paper:before,.deleted i.icon-large.icon-hand-peace:before,.deleted i.icon-large.icon-hand-point-down:before,.deleted i.icon-large.icon-hand-point-left:before,.deleted i.icon-large.icon-hand-point-right:before,.deleted i.icon-large.icon-hand-point-up:before,.deleted i.icon-large.icon-hand-pointer:before,.deleted i.icon-large.icon-hand-rock:before,.deleted i.icon-large.icon-hand-scissors:before,.deleted i.icon-large.icon-hand-spock:before,.deleted i.icon-large.icon-handshake:before,.deleted i.icon-large.icon-hdd:before,.deleted i.icon-large.icon-heart:before,.deleted i.icon-large.icon-hospital:before,.deleted i.icon-large.icon-hourglass:before,.deleted i.icon-large.icon-id-badge:before,.deleted i.icon-large.icon-id-card:before,.deleted i.icon-large.icon-image:before,.deleted i.icon-large.icon-images:before,.deleted i.icon-large.icon-keyboard:before,.deleted i.icon-large.icon-kiss-beam:before,.deleted i.icon-large.icon-kiss-wink-heart:before,.deleted i.icon-large.icon-kiss:before,.deleted i.icon-large.icon-laugh-beam:before,.deleted i.icon-large.icon-laugh-squint:before,.deleted i.icon-large.icon-laugh-wink:before,.deleted i.icon-large.icon-laugh:before,.deleted i.icon-large.icon-lemon:before,.deleted i.icon-large.icon-life-ring:before,.deleted i.icon-large.icon-lightbulb:before,.deleted i.icon-large.icon-list-alt:before,.deleted i.icon-large.icon-map:before,.deleted i.icon-large.icon-meh-blank:before,.deleted i.icon-large.icon-meh-rolling-eyes:before,.deleted i.icon-large.icon-meh:before,.deleted i.icon-large.icon-minus-square:before,.deleted i.icon-large.icon-money-bill-alt:before,.deleted i.icon-large.icon-moon:before,.deleted i.icon-large.icon-newspaper:before,.deleted i.icon-large.icon-object-group:before,.deleted i.icon-large.icon-object-ungroup:before,.deleted i.icon-large.icon-paper-plane:before,.deleted i.icon-large.icon-pause-circle:before,.deleted i.icon-large.icon-play-circle:before,.deleted i.icon-large.icon-plus-square:before,.deleted i.icon-large.icon-question-circle:before,.deleted i.icon-large.icon-registered:before,.deleted i.icon-large.icon-sad-cry:before,.deleted i.icon-large.icon-sad-tear:before,.deleted i.icon-large.icon-save:before,.deleted i.icon-large.icon-share-square:before,.deleted i.icon-large.icon-smile-beam:before,.deleted i.icon-large.icon-smile-wink:before,.deleted i.icon-large.icon-smile:before,.deleted i.icon-large.icon-snowflake:before,.deleted i.icon-large.icon-square:before,.deleted i.icon-large.icon-star-half:before,.deleted i.icon-large.icon-star:before,.deleted i.icon-large.icon-sticky-note:before,.deleted i.icon-large.icon-stop-circle:before,.deleted i.icon-large.icon-sun:before,.deleted i.icon-large.icon-surprise:before,.deleted i.icon-large.icon-thumbs-down:before,.deleted i.icon-large.icon-thumbs-up:before,.deleted i.icon-large.icon-times-circle:before,.deleted i.icon-large.icon-tired:before,.deleted i.icon-large.icon-trash-alt:before,.deleted i.icon-large.icon-user-circle:before,.deleted i.icon-large.icon-user:before,.deleted i.icon-large.icon-window-close:before,.deleted i.icon-large.icon-window-maximize:before,.deleted i.icon-large.icon-window-minimize:before,.deleted i.icon-large.icon-window-restore:before,.deleted i.icon.fa-address-book:before,.deleted i.icon.fa-address-card:before,.deleted i.icon.fa-angry:before,.deleted i.icon.fa-arrow-alt-circle-down:before,.deleted i.icon.fa-arrow-alt-circle-left:before,.deleted i.icon.fa-arrow-alt-circle-right:before,.deleted i.icon.fa-arrow-alt-circle-up:before,.deleted i.icon.fa-bell-slash:before,.deleted i.icon.fa-bell:before,.deleted i.icon.fa-bookmark:before,.deleted i.icon.fa-building:before,.deleted i.icon.fa-calendar-alt:before,.deleted i.icon.fa-calendar-check:before,.deleted i.icon.fa-calendar-minus:before,.deleted i.icon.fa-calendar-plus:before,.deleted i.icon.fa-calendar-times:before,.deleted i.icon.fa-calendar:before,.deleted i.icon.fa-caret-square-down:before,.deleted i.icon.fa-caret-square-left:before,.deleted i.icon.fa-caret-square-right:before,.deleted i.icon.fa-caret-square-up:before,.deleted i.icon.fa-chart-bar:before,.deleted i.icon.fa-check-circle:before,.deleted i.icon.fa-check-square:before,.deleted i.icon.fa-circle:before,.deleted i.icon.fa-clipboard:before,.deleted i.icon.fa-clock:before,.deleted i.icon.fa-clone:before,.deleted i.icon.fa-closed-captioning:before,.deleted i.icon.fa-comment-alt:before,.deleted i.icon.fa-comment-dots:before,.deleted i.icon.fa-comment:before,.deleted i.icon.fa-comments:before,.deleted i.icon.fa-compass:before,.deleted i.icon.fa-copy:before,.deleted i.icon.fa-copyright:before,.deleted i.icon.fa-credit-card:before,.deleted i.icon.fa-dizzy:before,.deleted i.icon.fa-dot-circle:before,.deleted i.icon.fa-edit:before,.deleted i.icon.fa-envelope-open:before,.deleted i.icon.fa-envelope:before,.deleted i.icon.fa-eye-slash:before,.deleted i.icon.fa-eye:before,.deleted i.icon.fa-file-alt:before,.deleted i.icon.fa-file-archive:before,.deleted i.icon.fa-file-audio:before,.deleted i.icon.fa-file-code:before,.deleted i.icon.fa-file-excel:before,.deleted i.icon.fa-file-image:before,.deleted i.icon.fa-file-pdf:before,.deleted i.icon.fa-file-powerpoint:before,.deleted i.icon.fa-file-video:before,.deleted i.icon.fa-file-word:before,.deleted i.icon.fa-file:before,.deleted i.icon.fa-flag:before,.deleted i.icon.fa-flushed:before,.deleted i.icon.fa-folder-open:before,.deleted i.icon.fa-folder:before,.deleted i.icon.fa-frown-open:before,.deleted i.icon.fa-frown:before,.deleted i.icon.fa-futbol:before,.deleted i.icon.fa-gem:before,.deleted i.icon.fa-grimace:before,.deleted i.icon.fa-grin-alt:before,.deleted i.icon.fa-grin-beam-sweat:before,.deleted i.icon.fa-grin-beam:before,.deleted i.icon.fa-grin-hearts:before,.deleted i.icon.fa-grin-squint-tears:before,.deleted i.icon.fa-grin-squint:before,.deleted i.icon.fa-grin-stars:before,.deleted i.icon.fa-grin-tears:before,.deleted i.icon.fa-grin-tongue-squint:before,.deleted i.icon.fa-grin-tongue-wink:before,.deleted i.icon.fa-grin-tongue:before,.deleted i.icon.fa-grin-wink:before,.deleted i.icon.fa-grin:before,.deleted i.icon.fa-hand-lizard:before,.deleted i.icon.fa-hand-paper:before,.deleted i.icon.fa-hand-peace:before,.deleted i.icon.fa-hand-point-down:before,.deleted i.icon.fa-hand-point-left:before,.deleted i.icon.fa-hand-point-right:before,.deleted i.icon.fa-hand-point-up:before,.deleted i.icon.fa-hand-pointer:before,.deleted i.icon.fa-hand-rock:before,.deleted i.icon.fa-hand-scissors:before,.deleted i.icon.fa-hand-spock:before,.deleted i.icon.fa-handshake:before,.deleted i.icon.fa-hdd:before,.deleted i.icon.fa-heart:before,.deleted i.icon.fa-hospital:before,.deleted i.icon.fa-hourglass:before,.deleted i.icon.fa-id-badge:before,.deleted i.icon.fa-id-card:before,.deleted i.icon.fa-image:before,.deleted i.icon.fa-images:before,.deleted i.icon.fa-keyboard:before,.deleted i.icon.fa-kiss-beam:before,.deleted i.icon.fa-kiss-wink-heart:before,.deleted i.icon.fa-kiss:before,.deleted i.icon.fa-laugh-beam:before,.deleted i.icon.fa-laugh-squint:before,.deleted i.icon.fa-laugh-wink:before,.deleted i.icon.fa-laugh:before,.deleted i.icon.fa-lemon:before,.deleted i.icon.fa-life-ring:before,.deleted i.icon.fa-lightbulb:before,.deleted i.icon.fa-list-alt:before,.deleted i.icon.fa-map:before,.deleted i.icon.fa-meh-blank:before,.deleted i.icon.fa-meh-rolling-eyes:before,.deleted i.icon.fa-meh:before,.deleted i.icon.fa-minus-square:before,.deleted i.icon.fa-money-bill-alt:before,.deleted i.icon.fa-moon:before,.deleted i.icon.fa-newspaper:before,.deleted i.icon.fa-object-group:before,.deleted i.icon.fa-object-ungroup:before,.deleted i.icon.fa-paper-plane:before,.deleted i.icon.fa-pause-circle:before,.deleted i.icon.fa-play-circle:before,.deleted i.icon.fa-plus-square:before,.deleted i.icon.fa-question-circle:before,.deleted i.icon.fa-registered:before,.deleted i.icon.fa-sad-cry:before,.deleted i.icon.fa-sad-tear:before,.deleted i.icon.fa-save:before,.deleted i.icon.fa-share-square:before,.deleted i.icon.fa-smile-beam:before,.deleted i.icon.fa-smile-wink:before,.deleted i.icon.fa-smile:before,.deleted i.icon.fa-snowflake:before,.deleted i.icon.fa-square:before,.deleted i.icon.fa-star-half:before,.deleted i.icon.fa-star:before,.deleted i.icon.fa-sticky-note:before,.deleted i.icon.fa-stop-circle:before,.deleted i.icon.fa-sun:before,.deleted i.icon.fa-surprise:before,.deleted i.icon.fa-thumbs-down:before,.deleted i.icon.fa-thumbs-up:before,.deleted i.icon.fa-times-circle:before,.deleted i.icon.fa-tired:before,.deleted i.icon.fa-trash-alt:before,.deleted i.icon.fa-user-circle:before,.deleted i.icon.fa-user:before,.deleted i.icon.fa-window-close:before,.deleted i.icon.fa-window-maximize:before,.deleted i.icon.fa-window-minimize:before,.deleted i.icon.fa-window-restore:before,.deleted i.icon.icon-address-book:before,.deleted i.icon.icon-address-card:before,.deleted i.icon.icon-angry:before,.deleted i.icon.icon-arrow-alt-circle-down:before,.deleted i.icon.icon-arrow-alt-circle-left:before,.deleted i.icon.icon-arrow-alt-circle-right:before,.deleted i.icon.icon-arrow-alt-circle-up:before,.deleted i.icon.icon-bell-slash:before,.deleted i.icon.icon-bell:before,.deleted i.icon.icon-bookmark:before,.deleted i.icon.icon-building:before,.deleted i.icon.icon-calendar-alt:before,.deleted i.icon.icon-calendar-check:before,.deleted i.icon.icon-calendar-minus:before,.deleted i.icon.icon-calendar-plus:before,.deleted i.icon.icon-calendar-times:before,.deleted i.icon.icon-calendar:before,.deleted i.icon.icon-caret-square-down:before,.deleted i.icon.icon-caret-square-left:before,.deleted i.icon.icon-caret-square-right:before,.deleted i.icon.icon-caret-square-up:before,.deleted i.icon.icon-chart-bar:before,.deleted i.icon.icon-check-circle:before,.deleted i.icon.icon-check-square:before,.deleted i.icon.icon-circle:before,.deleted i.icon.icon-clipboard:before,.deleted i.icon.icon-clock:before,.deleted i.icon.icon-clone:before,.deleted i.icon.icon-closed-captioning:before,.deleted i.icon.icon-comment-alt:before,.deleted i.icon.icon-comment-dots:before,.deleted i.icon.icon-comment:before,.deleted i.icon.icon-comments:before,.deleted i.icon.icon-compass:before,.deleted i.icon.icon-copy:before,.deleted i.icon.icon-copyright:before,.deleted i.icon.icon-credit-card:before,.deleted i.icon.icon-dizzy:before,.deleted i.icon.icon-dot-circle:before,.deleted i.icon.icon-edit:before,.deleted i.icon.icon-envelope-open:before,.deleted i.icon.icon-envelope:before,.deleted i.icon.icon-eye-slash:before,.deleted i.icon.icon-eye:before,.deleted i.icon.icon-file-alt:before,.deleted i.icon.icon-file-archive:before,.deleted i.icon.icon-file-audio:before,.deleted i.icon.icon-file-code:before,.deleted i.icon.icon-file-excel:before,.deleted i.icon.icon-file-image:before,.deleted i.icon.icon-file-pdf:before,.deleted i.icon.icon-file-powerpoint:before,.deleted i.icon.icon-file-video:before,.deleted i.icon.icon-file-word:before,.deleted i.icon.icon-file:before,.deleted i.icon.icon-flag:before,.deleted i.icon.icon-flushed:before,.deleted i.icon.icon-folder-open:before,.deleted i.icon.icon-folder:before,.deleted i.icon.icon-frown-open:before,.deleted i.icon.icon-frown:before,.deleted i.icon.icon-futbol:before,.deleted i.icon.icon-gem:before,.deleted i.icon.icon-grimace:before,.deleted i.icon.icon-grin-alt:before,.deleted i.icon.icon-grin-beam-sweat:before,.deleted i.icon.icon-grin-beam:before,.deleted i.icon.icon-grin-hearts:before,.deleted i.icon.icon-grin-squint-tears:before,.deleted i.icon.icon-grin-squint:before,.deleted i.icon.icon-grin-stars:before,.deleted i.icon.icon-grin-tears:before,.deleted i.icon.icon-grin-tongue-squint:before,.deleted i.icon.icon-grin-tongue-wink:before,.deleted i.icon.icon-grin-tongue:before,.deleted i.icon.icon-grin-wink:before,.deleted i.icon.icon-grin:before,.deleted i.icon.icon-hand-lizard:before,.deleted i.icon.icon-hand-paper:before,.deleted i.icon.icon-hand-peace:before,.deleted i.icon.icon-hand-point-down:before,.deleted i.icon.icon-hand-point-left:before,.deleted i.icon.icon-hand-point-right:before,.deleted i.icon.icon-hand-point-up:before,.deleted i.icon.icon-hand-pointer:before,.deleted i.icon.icon-hand-rock:before,.deleted i.icon.icon-hand-scissors:before,.deleted i.icon.icon-hand-spock:before,.deleted i.icon.icon-handshake:before,.deleted i.icon.icon-hdd:before,.deleted i.icon.icon-heart:before,.deleted i.icon.icon-hospital:before,.deleted i.icon.icon-hourglass:before,.deleted i.icon.icon-id-badge:before,.deleted i.icon.icon-id-card:before,.deleted i.icon.icon-image:before,.deleted i.icon.icon-images:before,.deleted i.icon.icon-keyboard:before,.deleted i.icon.icon-kiss-beam:before,.deleted i.icon.icon-kiss-wink-heart:before,.deleted i.icon.icon-kiss:before,.deleted i.icon.icon-laugh-beam:before,.deleted i.icon.icon-laugh-squint:before,.deleted i.icon.icon-laugh-wink:before,.deleted i.icon.icon-laugh:before,.deleted i.icon.icon-lemon:before,.deleted i.icon.icon-life-ring:before,.deleted i.icon.icon-lightbulb:before,.deleted i.icon.icon-list-alt:before,.deleted i.icon.icon-map:before,.deleted i.icon.icon-meh-blank:before,.deleted i.icon.icon-meh-rolling-eyes:before,.deleted i.icon.icon-meh:before,.deleted i.icon.icon-minus-square:before,.deleted i.icon.icon-money-bill-alt:before,.deleted i.icon.icon-moon:before,.deleted i.icon.icon-newspaper:before,.deleted i.icon.icon-object-group:before,.deleted i.icon.icon-object-ungroup:before,.deleted i.icon.icon-paper-plane:before,.deleted i.icon.icon-pause-circle:before,.deleted i.icon.icon-play-circle:before,.deleted i.icon.icon-plus-square:before,.deleted i.icon.icon-question-circle:before,.deleted i.icon.icon-registered:before,.deleted i.icon.icon-sad-cry:before,.deleted i.icon.icon-sad-tear:before,.deleted i.icon.icon-save:before,.deleted i.icon.icon-share-square:before,.deleted i.icon.icon-smile-beam:before,.deleted i.icon.icon-smile-wink:before,.deleted i.icon.icon-smile:before,.deleted i.icon.icon-snowflake:before,.deleted i.icon.icon-square:before,.deleted i.icon.icon-star-half:before,.deleted i.icon.icon-star:before,.deleted i.icon.icon-sticky-note:before,.deleted i.icon.icon-stop-circle:before,.deleted i.icon.icon-sun:before,.deleted i.icon.icon-surprise:before,.deleted i.icon.icon-thumbs-down:before,.deleted i.icon.icon-thumbs-up:before,.deleted i.icon.icon-times-circle:before,.deleted i.icon.icon-tired:before,.deleted i.icon.icon-trash-alt:before,.deleted i.icon.icon-user-circle:before,.deleted i.icon.icon-user:before,.deleted i.icon.icon-window-close:before,.deleted i.icon.icon-window-maximize:before,.deleted i.icon.icon-window-minimize:before,.deleted i.icon.icon-window-restore:before,.unpublished i.icon-large.fa-address-book:before,.unpublished i.icon-large.fa-address-card:before,.unpublished i.icon-large.fa-angry:before,.unpublished i.icon-large.fa-arrow-alt-circle-down:before,.unpublished i.icon-large.fa-arrow-alt-circle-left:before,.unpublished i.icon-large.fa-arrow-alt-circle-right:before,.unpublished i.icon-large.fa-arrow-alt-circle-up:before,.unpublished i.icon-large.fa-bell-slash:before,.unpublished i.icon-large.fa-bell:before,.unpublished i.icon-large.fa-bookmark:before,.unpublished i.icon-large.fa-building:before,.unpublished i.icon-large.fa-calendar-alt:before,.unpublished i.icon-large.fa-calendar-check:before,.unpublished i.icon-large.fa-calendar-minus:before,.unpublished i.icon-large.fa-calendar-plus:before,.unpublished i.icon-large.fa-calendar-times:before,.unpublished i.icon-large.fa-calendar:before,.unpublished i.icon-large.fa-caret-square-down:before,.unpublished i.icon-large.fa-caret-square-left:before,.unpublished i.icon-large.fa-caret-square-right:before,.unpublished i.icon-large.fa-caret-square-up:before,.unpublished i.icon-large.fa-chart-bar:before,.unpublished i.icon-large.fa-check-circle:before,.unpublished i.icon-large.fa-check-square:before,.unpublished i.icon-large.fa-circle:before,.unpublished i.icon-large.fa-clipboard:before,.unpublished i.icon-large.fa-clock:before,.unpublished i.icon-large.fa-clone:before,.unpublished i.icon-large.fa-closed-captioning:before,.unpublished i.icon-large.fa-comment-alt:before,.unpublished i.icon-large.fa-comment-dots:before,.unpublished i.icon-large.fa-comment:before,.unpublished i.icon-large.fa-comments:before,.unpublished i.icon-large.fa-compass:before,.unpublished i.icon-large.fa-copy:before,.unpublished i.icon-large.fa-copyright:before,.unpublished i.icon-large.fa-credit-card:before,.unpublished i.icon-large.fa-dizzy:before,.unpublished i.icon-large.fa-dot-circle:before,.unpublished i.icon-large.fa-edit:before,.unpublished i.icon-large.fa-envelope-open:before,.unpublished i.icon-large.fa-envelope:before,.unpublished i.icon-large.fa-eye-slash:before,.unpublished i.icon-large.fa-eye:before,.unpublished i.icon-large.fa-file-alt:before,.unpublished i.icon-large.fa-file-archive:before,.unpublished i.icon-large.fa-file-audio:before,.unpublished i.icon-large.fa-file-code:before,.unpublished i.icon-large.fa-file-excel:before,.unpublished i.icon-large.fa-file-image:before,.unpublished i.icon-large.fa-file-pdf:before,.unpublished i.icon-large.fa-file-powerpoint:before,.unpublished i.icon-large.fa-file-video:before,.unpublished i.icon-large.fa-file-word:before,.unpublished i.icon-large.fa-file:before,.unpublished i.icon-large.fa-flag:before,.unpublished i.icon-large.fa-flushed:before,.unpublished i.icon-large.fa-folder-open:before,.unpublished i.icon-large.fa-folder:before,.unpublished i.icon-large.fa-frown-open:before,.unpublished i.icon-large.fa-frown:before,.unpublished i.icon-large.fa-futbol:before,.unpublished i.icon-large.fa-gem:before,.unpublished i.icon-large.fa-grimace:before,.unpublished i.icon-large.fa-grin-alt:before,.unpublished i.icon-large.fa-grin-beam-sweat:before,.unpublished i.icon-large.fa-grin-beam:before,.unpublished i.icon-large.fa-grin-hearts:before,.unpublished i.icon-large.fa-grin-squint-tears:before,.unpublished i.icon-large.fa-grin-squint:before,.unpublished i.icon-large.fa-grin-stars:before,.unpublished i.icon-large.fa-grin-tears:before,.unpublished i.icon-large.fa-grin-tongue-squint:before,.unpublished i.icon-large.fa-grin-tongue-wink:before,.unpublished i.icon-large.fa-grin-tongue:before,.unpublished i.icon-large.fa-grin-wink:before,.unpublished i.icon-large.fa-grin:before,.unpublished i.icon-large.fa-hand-lizard:before,.unpublished i.icon-large.fa-hand-paper:before,.unpublished i.icon-large.fa-hand-peace:before,.unpublished i.icon-large.fa-hand-point-down:before,.unpublished i.icon-large.fa-hand-point-left:before,.unpublished i.icon-large.fa-hand-point-right:before,.unpublished i.icon-large.fa-hand-point-up:before,.unpublished i.icon-large.fa-hand-pointer:before,.unpublished i.icon-large.fa-hand-rock:before,.unpublished i.icon-large.fa-hand-scissors:before,.unpublished i.icon-large.fa-hand-spock:before,.unpublished i.icon-large.fa-handshake:before,.unpublished i.icon-large.fa-hdd:before,.unpublished i.icon-large.fa-heart:before,.unpublished i.icon-large.fa-hospital:before,.unpublished i.icon-large.fa-hourglass:before,.unpublished i.icon-large.fa-id-badge:before,.unpublished i.icon-large.fa-id-card:before,.unpublished i.icon-large.fa-image:before,.unpublished i.icon-large.fa-images:before,.unpublished i.icon-large.fa-keyboard:before,.unpublished i.icon-large.fa-kiss-beam:before,.unpublished i.icon-large.fa-kiss-wink-heart:before,.unpublished i.icon-large.fa-kiss:before,.unpublished i.icon-large.fa-laugh-beam:before,.unpublished i.icon-large.fa-laugh-squint:before,.unpublished i.icon-large.fa-laugh-wink:before,.unpublished i.icon-large.fa-laugh:before,.unpublished i.icon-large.fa-lemon:before,.unpublished i.icon-large.fa-life-ring:before,.unpublished i.icon-large.fa-lightbulb:before,.unpublished i.icon-large.fa-list-alt:before,.unpublished i.icon-large.fa-map:before,.unpublished i.icon-large.fa-meh-blank:before,.unpublished i.icon-large.fa-meh-rolling-eyes:before,.unpublished i.icon-large.fa-meh:before,.unpublished i.icon-large.fa-minus-square:before,.unpublished i.icon-large.fa-money-bill-alt:before,.unpublished i.icon-large.fa-moon:before,.unpublished i.icon-large.fa-newspaper:before,.unpublished i.icon-large.fa-object-group:before,.unpublished i.icon-large.fa-object-ungroup:before,.unpublished i.icon-large.fa-paper-plane:before,.unpublished i.icon-large.fa-pause-circle:before,.unpublished i.icon-large.fa-play-circle:before,.unpublished i.icon-large.fa-plus-square:before,.unpublished i.icon-large.fa-question-circle:before,.unpublished i.icon-large.fa-registered:before,.unpublished i.icon-large.fa-sad-cry:before,.unpublished i.icon-large.fa-sad-tear:before,.unpublished i.icon-large.fa-save:before,.unpublished i.icon-large.fa-share-square:before,.unpublished i.icon-large.fa-smile-beam:before,.unpublished i.icon-large.fa-smile-wink:before,.unpublished i.icon-large.fa-smile:before,.unpublished i.icon-large.fa-snowflake:before,.unpublished i.icon-large.fa-square:before,.unpublished i.icon-large.fa-star-half:before,.unpublished i.icon-large.fa-star:before,.unpublished i.icon-large.fa-sticky-note:before,.unpublished i.icon-large.fa-stop-circle:before,.unpublished i.icon-large.fa-sun:before,.unpublished i.icon-large.fa-surprise:before,.unpublished i.icon-large.fa-thumbs-down:before,.unpublished i.icon-large.fa-thumbs-up:before,.unpublished i.icon-large.fa-times-circle:before,.unpublished i.icon-large.fa-tired:before,.unpublished i.icon-large.fa-trash-alt:before,.unpublished i.icon-large.fa-user-circle:before,.unpublished i.icon-large.fa-user:before,.unpublished i.icon-large.fa-window-close:before,.unpublished i.icon-large.fa-window-maximize:before,.unpublished i.icon-large.fa-window-minimize:before,.unpublished i.icon-large.fa-window-restore:before,.unpublished i.icon-large.icon-address-book:before,.unpublished i.icon-large.icon-address-card:before,.unpublished i.icon-large.icon-angry:before,.unpublished i.icon-large.icon-arrow-alt-circle-down:before,.unpublished i.icon-large.icon-arrow-alt-circle-left:before,.unpublished i.icon-large.icon-arrow-alt-circle-right:before,.unpublished i.icon-large.icon-arrow-alt-circle-up:before,.unpublished i.icon-large.icon-bell-slash:before,.unpublished i.icon-large.icon-bell:before,.unpublished i.icon-large.icon-bookmark:before,.unpublished i.icon-large.icon-building:before,.unpublished i.icon-large.icon-calendar-alt:before,.unpublished i.icon-large.icon-calendar-check:before,.unpublished i.icon-large.icon-calendar-minus:before,.unpublished i.icon-large.icon-calendar-plus:before,.unpublished i.icon-large.icon-calendar-times:before,.unpublished i.icon-large.icon-calendar:before,.unpublished i.icon-large.icon-caret-square-down:before,.unpublished i.icon-large.icon-caret-square-left:before,.unpublished i.icon-large.icon-caret-square-right:before,.unpublished i.icon-large.icon-caret-square-up:before,.unpublished i.icon-large.icon-chart-bar:before,.unpublished i.icon-large.icon-check-circle:before,.unpublished i.icon-large.icon-check-square:before,.unpublished i.icon-large.icon-circle:before,.unpublished i.icon-large.icon-clipboard:before,.unpublished i.icon-large.icon-clock:before,.unpublished i.icon-large.icon-clone:before,.unpublished i.icon-large.icon-closed-captioning:before,.unpublished i.icon-large.icon-comment-alt:before,.unpublished i.icon-large.icon-comment-dots:before,.unpublished i.icon-large.icon-comment:before,.unpublished i.icon-large.icon-comments:before,.unpublished i.icon-large.icon-compass:before,.unpublished i.icon-large.icon-copy:before,.unpublished i.icon-large.icon-copyright:before,.unpublished i.icon-large.icon-credit-card:before,.unpublished i.icon-large.icon-dizzy:before,.unpublished i.icon-large.icon-dot-circle:before,.unpublished i.icon-large.icon-edit:before,.unpublished i.icon-large.icon-envelope-open:before,.unpublished i.icon-large.icon-envelope:before,.unpublished i.icon-large.icon-eye-slash:before,.unpublished i.icon-large.icon-eye:before,.unpublished i.icon-large.icon-file-alt:before,.unpublished i.icon-large.icon-file-archive:before,.unpublished i.icon-large.icon-file-audio:before,.unpublished i.icon-large.icon-file-code:before,.unpublished i.icon-large.icon-file-excel:before,.unpublished i.icon-large.icon-file-image:before,.unpublished i.icon-large.icon-file-pdf:before,.unpublished i.icon-large.icon-file-powerpoint:before,.unpublished i.icon-large.icon-file-video:before,.unpublished i.icon-large.icon-file-word:before,.unpublished i.icon-large.icon-file:before,.unpublished i.icon-large.icon-flag:before,.unpublished i.icon-large.icon-flushed:before,.unpublished i.icon-large.icon-folder-open:before,.unpublished i.icon-large.icon-folder:before,.unpublished i.icon-large.icon-frown-open:before,.unpublished i.icon-large.icon-frown:before,.unpublished i.icon-large.icon-futbol:before,.unpublished i.icon-large.icon-gem:before,.unpublished i.icon-large.icon-grimace:before,.unpublished i.icon-large.icon-grin-alt:before,.unpublished i.icon-large.icon-grin-beam-sweat:before,.unpublished i.icon-large.icon-grin-beam:before,.unpublished i.icon-large.icon-grin-hearts:before,.unpublished i.icon-large.icon-grin-squint-tears:before,.unpublished i.icon-large.icon-grin-squint:before,.unpublished i.icon-large.icon-grin-stars:before,.unpublished i.icon-large.icon-grin-tears:before,.unpublished i.icon-large.icon-grin-tongue-squint:before,.unpublished i.icon-large.icon-grin-tongue-wink:before,.unpublished i.icon-large.icon-grin-tongue:before,.unpublished i.icon-large.icon-grin-wink:before,.unpublished i.icon-large.icon-grin:before,.unpublished i.icon-large.icon-hand-lizard:before,.unpublished i.icon-large.icon-hand-paper:before,.unpublished i.icon-large.icon-hand-peace:before,.unpublished i.icon-large.icon-hand-point-down:before,.unpublished i.icon-large.icon-hand-point-left:before,.unpublished i.icon-large.icon-hand-point-right:before,.unpublished i.icon-large.icon-hand-point-up:before,.unpublished i.icon-large.icon-hand-pointer:before,.unpublished i.icon-large.icon-hand-rock:before,.unpublished i.icon-large.icon-hand-scissors:before,.unpublished i.icon-large.icon-hand-spock:before,.unpublished i.icon-large.icon-handshake:before,.unpublished i.icon-large.icon-hdd:before,.unpublished i.icon-large.icon-heart:before,.unpublished i.icon-large.icon-hospital:before,.unpublished i.icon-large.icon-hourglass:before,.unpublished i.icon-large.icon-id-badge:before,.unpublished i.icon-large.icon-id-card:before,.unpublished i.icon-large.icon-image:before,.unpublished i.icon-large.icon-images:before,.unpublished i.icon-large.icon-keyboard:before,.unpublished i.icon-large.icon-kiss-beam:before,.unpublished i.icon-large.icon-kiss-wink-heart:before,.unpublished i.icon-large.icon-kiss:before,.unpublished i.icon-large.icon-laugh-beam:before,.unpublished i.icon-large.icon-laugh-squint:before,.unpublished i.icon-large.icon-laugh-wink:before,.unpublished i.icon-large.icon-laugh:before,.unpublished i.icon-large.icon-lemon:before,.unpublished i.icon-large.icon-life-ring:before,.unpublished i.icon-large.icon-lightbulb:before,.unpublished i.icon-large.icon-list-alt:before,.unpublished i.icon-large.icon-map:before,.unpublished i.icon-large.icon-meh-blank:before,.unpublished i.icon-large.icon-meh-rolling-eyes:before,.unpublished i.icon-large.icon-meh:before,.unpublished i.icon-large.icon-minus-square:before,.unpublished i.icon-large.icon-money-bill-alt:before,.unpublished i.icon-large.icon-moon:before,.unpublished i.icon-large.icon-newspaper:before,.unpublished i.icon-large.icon-object-group:before,.unpublished i.icon-large.icon-object-ungroup:before,.unpublished i.icon-large.icon-paper-plane:before,.unpublished i.icon-large.icon-pause-circle:before,.unpublished i.icon-large.icon-play-circle:before,.unpublished i.icon-large.icon-plus-square:before,.unpublished i.icon-large.icon-question-circle:before,.unpublished i.icon-large.icon-registered:before,.unpublished i.icon-large.icon-sad-cry:before,.unpublished i.icon-large.icon-sad-tear:before,.unpublished i.icon-large.icon-save:before,.unpublished i.icon-large.icon-share-square:before,.unpublished i.icon-large.icon-smile-beam:before,.unpublished i.icon-large.icon-smile-wink:before,.unpublished i.icon-large.icon-smile:before,.unpublished i.icon-large.icon-snowflake:before,.unpublished i.icon-large.icon-square:before,.unpublished i.icon-large.icon-star-half:before,.unpublished i.icon-large.icon-star:before,.unpublished i.icon-large.icon-sticky-note:before,.unpublished i.icon-large.icon-stop-circle:before,.unpublished i.icon-large.icon-sun:before,.unpublished i.icon-large.icon-surprise:before,.unpublished i.icon-large.icon-thumbs-down:before,.unpublished i.icon-large.icon-thumbs-up:before,.unpublished i.icon-large.icon-times-circle:before,.unpublished i.icon-large.icon-tired:before,.unpublished i.icon-large.icon-trash-alt:before,.unpublished i.icon-large.icon-user-circle:before,.unpublished i.icon-large.icon-user:before,.unpublished i.icon-large.icon-window-close:before,.unpublished i.icon-large.icon-window-maximize:before,.unpublished i.icon-large.icon-window-minimize:before,.unpublished i.icon-large.icon-window-restore:before,.unpublished i.icon.fa-address-book:before,.unpublished i.icon.fa-address-card:before,.unpublished i.icon.fa-angry:before,.unpublished i.icon.fa-arrow-alt-circle-down:before,.unpublished i.icon.fa-arrow-alt-circle-left:before,.unpublished i.icon.fa-arrow-alt-circle-right:before,.unpublished i.icon.fa-arrow-alt-circle-up:before,.unpublished i.icon.fa-bell-slash:before,.unpublished i.icon.fa-bell:before,.unpublished i.icon.fa-bookmark:before,.unpublished i.icon.fa-building:before,.unpublished i.icon.fa-calendar-alt:before,.unpublished i.icon.fa-calendar-check:before,.unpublished i.icon.fa-calendar-minus:before,.unpublished i.icon.fa-calendar-plus:before,.unpublished i.icon.fa-calendar-times:before,.unpublished i.icon.fa-calendar:before,.unpublished i.icon.fa-caret-square-down:before,.unpublished i.icon.fa-caret-square-left:before,.unpublished i.icon.fa-caret-square-right:before,.unpublished i.icon.fa-caret-square-up:before,.unpublished i.icon.fa-chart-bar:before,.unpublished i.icon.fa-check-circle:before,.unpublished i.icon.fa-check-square:before,.unpublished i.icon.fa-circle:before,.unpublished i.icon.fa-clipboard:before,.unpublished i.icon.fa-clock:before,.unpublished i.icon.fa-clone:before,.unpublished i.icon.fa-closed-captioning:before,.unpublished i.icon.fa-comment-alt:before,.unpublished i.icon.fa-comment-dots:before,.unpublished i.icon.fa-comment:before,.unpublished i.icon.fa-comments:before,.unpublished i.icon.fa-compass:before,.unpublished i.icon.fa-copy:before,.unpublished i.icon.fa-copyright:before,.unpublished i.icon.fa-credit-card:before,.unpublished i.icon.fa-dizzy:before,.unpublished i.icon.fa-dot-circle:before,.unpublished i.icon.fa-edit:before,.unpublished i.icon.fa-envelope-open:before,.unpublished i.icon.fa-envelope:before,.unpublished i.icon.fa-eye-slash:before,.unpublished i.icon.fa-eye:before,.unpublished i.icon.fa-file-alt:before,.unpublished i.icon.fa-file-archive:before,.unpublished i.icon.fa-file-audio:before,.unpublished i.icon.fa-file-code:before,.unpublished i.icon.fa-file-excel:before,.unpublished i.icon.fa-file-image:before,.unpublished i.icon.fa-file-pdf:before,.unpublished i.icon.fa-file-powerpoint:before,.unpublished i.icon.fa-file-video:before,.unpublished i.icon.fa-file-word:before,.unpublished i.icon.fa-file:before,.unpublished i.icon.fa-flag:before,.unpublished i.icon.fa-flushed:before,.unpublished i.icon.fa-folder-open:before,.unpublished i.icon.fa-folder:before,.unpublished i.icon.fa-frown-open:before,.unpublished i.icon.fa-frown:before,.unpublished i.icon.fa-futbol:before,.unpublished i.icon.fa-gem:before,.unpublished i.icon.fa-grimace:before,.unpublished i.icon.fa-grin-alt:before,.unpublished i.icon.fa-grin-beam-sweat:before,.unpublished i.icon.fa-grin-beam:before,.unpublished i.icon.fa-grin-hearts:before,.unpublished i.icon.fa-grin-squint-tears:before,.unpublished i.icon.fa-grin-squint:before,.unpublished i.icon.fa-grin-stars:before,.unpublished i.icon.fa-grin-tears:before,.unpublished i.icon.fa-grin-tongue-squint:before,.unpublished i.icon.fa-grin-tongue-wink:before,.unpublished i.icon.fa-grin-tongue:before,.unpublished i.icon.fa-grin-wink:before,.unpublished i.icon.fa-grin:before,.unpublished i.icon.fa-hand-lizard:before,.unpublished i.icon.fa-hand-paper:before,.unpublished i.icon.fa-hand-peace:before,.unpublished i.icon.fa-hand-point-down:before,.unpublished i.icon.fa-hand-point-left:before,.unpublished i.icon.fa-hand-point-right:before,.unpublished i.icon.fa-hand-point-up:before,.unpublished i.icon.fa-hand-pointer:before,.unpublished i.icon.fa-hand-rock:before,.unpublished i.icon.fa-hand-scissors:before,.unpublished i.icon.fa-hand-spock:before,.unpublished i.icon.fa-handshake:before,.unpublished i.icon.fa-hdd:before,.unpublished i.icon.fa-heart:before,.unpublished i.icon.fa-hospital:before,.unpublished i.icon.fa-hourglass:before,.unpublished i.icon.fa-id-badge:before,.unpublished i.icon.fa-id-card:before,.unpublished i.icon.fa-image:before,.unpublished i.icon.fa-images:before,.unpublished i.icon.fa-keyboard:before,.unpublished i.icon.fa-kiss-beam:before,.unpublished i.icon.fa-kiss-wink-heart:before,.unpublished i.icon.fa-kiss:before,.unpublished i.icon.fa-laugh-beam:before,.unpublished i.icon.fa-laugh-squint:before,.unpublished i.icon.fa-laugh-wink:before,.unpublished i.icon.fa-laugh:before,.unpublished i.icon.fa-lemon:before,.unpublished i.icon.fa-life-ring:before,.unpublished i.icon.fa-lightbulb:before,.unpublished i.icon.fa-list-alt:before,.unpublished i.icon.fa-map:before,.unpublished i.icon.fa-meh-blank:before,.unpublished i.icon.fa-meh-rolling-eyes:before,.unpublished i.icon.fa-meh:before,.unpublished i.icon.fa-minus-square:before,.unpublished i.icon.fa-money-bill-alt:before,.unpublished i.icon.fa-moon:before,.unpublished i.icon.fa-newspaper:before,.unpublished i.icon.fa-object-group:before,.unpublished i.icon.fa-object-ungroup:before,.unpublished i.icon.fa-paper-plane:before,.unpublished i.icon.fa-pause-circle:before,.unpublished i.icon.fa-play-circle:before,.unpublished i.icon.fa-plus-square:before,.unpublished i.icon.fa-question-circle:before,.unpublished i.icon.fa-registered:before,.unpublished i.icon.fa-sad-cry:before,.unpublished i.icon.fa-sad-tear:before,.unpublished i.icon.fa-save:before,.unpublished i.icon.fa-share-square:before,.unpublished i.icon.fa-smile-beam:before,.unpublished i.icon.fa-smile-wink:before,.unpublished i.icon.fa-smile:before,.unpublished i.icon.fa-snowflake:before,.unpublished i.icon.fa-square:before,.unpublished i.icon.fa-star-half:before,.unpublished i.icon.fa-star:before,.unpublished i.icon.fa-sticky-note:before,.unpublished i.icon.fa-stop-circle:before,.unpublished i.icon.fa-sun:before,.unpublished i.icon.fa-surprise:before,.unpublished i.icon.fa-thumbs-down:before,.unpublished i.icon.fa-thumbs-up:before,.unpublished i.icon.fa-times-circle:before,.unpublished i.icon.fa-tired:before,.unpublished i.icon.fa-trash-alt:before,.unpublished i.icon.fa-user-circle:before,.unpublished i.icon.fa-user:before,.unpublished i.icon.fa-window-close:before,.unpublished i.icon.fa-window-maximize:before,.unpublished i.icon.fa-window-minimize:before,.unpublished i.icon.fa-window-restore:before,.unpublished i.icon.icon-address-book:before,.unpublished i.icon.icon-address-card:before,.unpublished i.icon.icon-angry:before,.unpublished i.icon.icon-arrow-alt-circle-down:before,.unpublished i.icon.icon-arrow-alt-circle-left:before,.unpublished i.icon.icon-arrow-alt-circle-right:before,.unpublished i.icon.icon-arrow-alt-circle-up:before,.unpublished i.icon.icon-bell-slash:before,.unpublished i.icon.icon-bell:before,.unpublished i.icon.icon-bookmark:before,.unpublished i.icon.icon-building:before,.unpublished i.icon.icon-calendar-alt:before,.unpublished i.icon.icon-calendar-check:before,.unpublished i.icon.icon-calendar-minus:before,.unpublished i.icon.icon-calendar-plus:before,.unpublished i.icon.icon-calendar-times:before,.unpublished i.icon.icon-calendar:before,.unpublished i.icon.icon-caret-square-down:before,.unpublished i.icon.icon-caret-square-left:before,.unpublished i.icon.icon-caret-square-right:before,.unpublished i.icon.icon-caret-square-up:before,.unpublished i.icon.icon-chart-bar:before,.unpublished i.icon.icon-check-circle:before,.unpublished i.icon.icon-check-square:before,.unpublished i.icon.icon-circle:before,.unpublished i.icon.icon-clipboard:before,.unpublished i.icon.icon-clock:before,.unpublished i.icon.icon-clone:before,.unpublished i.icon.icon-closed-captioning:before,.unpublished i.icon.icon-comment-alt:before,.unpublished i.icon.icon-comment-dots:before,.unpublished i.icon.icon-comment:before,.unpublished i.icon.icon-comments:before,.unpublished i.icon.icon-compass:before,.unpublished i.icon.icon-copy:before,.unpublished i.icon.icon-copyright:before,.unpublished i.icon.icon-credit-card:before,.unpublished i.icon.icon-dizzy:before,.unpublished i.icon.icon-dot-circle:before,.unpublished i.icon.icon-edit:before,.unpublished i.icon.icon-envelope-open:before,.unpublished i.icon.icon-envelope:before,.unpublished i.icon.icon-eye-slash:before,.unpublished i.icon.icon-eye:before,.unpublished i.icon.icon-file-alt:before,.unpublished i.icon.icon-file-archive:before,.unpublished i.icon.icon-file-audio:before,.unpublished i.icon.icon-file-code:before,.unpublished i.icon.icon-file-excel:before,.unpublished i.icon.icon-file-image:before,.unpublished i.icon.icon-file-pdf:before,.unpublished i.icon.icon-file-powerpoint:before,.unpublished i.icon.icon-file-video:before,.unpublished i.icon.icon-file-word:before,.unpublished i.icon.icon-file:before,.unpublished i.icon.icon-flag:before,.unpublished i.icon.icon-flushed:before,.unpublished i.icon.icon-folder-open:before,.unpublished i.icon.icon-folder:before,.unpublished i.icon.icon-frown-open:before,.unpublished i.icon.icon-frown:before,.unpublished i.icon.icon-futbol:before,.unpublished i.icon.icon-gem:before,.unpublished i.icon.icon-grimace:before,.unpublished i.icon.icon-grin-alt:before,.unpublished i.icon.icon-grin-beam-sweat:before,.unpublished i.icon.icon-grin-beam:before,.unpublished i.icon.icon-grin-hearts:before,.unpublished i.icon.icon-grin-squint-tears:before,.unpublished i.icon.icon-grin-squint:before,.unpublished i.icon.icon-grin-stars:before,.unpublished i.icon.icon-grin-tears:before,.unpublished i.icon.icon-grin-tongue-squint:before,.unpublished i.icon.icon-grin-tongue-wink:before,.unpublished i.icon.icon-grin-tongue:before,.unpublished i.icon.icon-grin-wink:before,.unpublished i.icon.icon-grin:before,.unpublished i.icon.icon-hand-lizard:before,.unpublished i.icon.icon-hand-paper:before,.unpublished i.icon.icon-hand-peace:before,.unpublished i.icon.icon-hand-point-down:before,.unpublished i.icon.icon-hand-point-left:before,.unpublished i.icon.icon-hand-point-right:before,.unpublished i.icon.icon-hand-point-up:before,.unpublished i.icon.icon-hand-pointer:before,.unpublished i.icon.icon-hand-rock:before,.unpublished i.icon.icon-hand-scissors:before,.unpublished i.icon.icon-hand-spock:before,.unpublished i.icon.icon-handshake:before,.unpublished i.icon.icon-hdd:before,.unpublished i.icon.icon-heart:before,.unpublished i.icon.icon-hospital:before,.unpublished i.icon.icon-hourglass:before,.unpublished i.icon.icon-id-badge:before,.unpublished i.icon.icon-id-card:before,.unpublished i.icon.icon-image:before,.unpublished i.icon.icon-images:before,.unpublished i.icon.icon-keyboard:before,.unpublished i.icon.icon-kiss-beam:before,.unpublished i.icon.icon-kiss-wink-heart:before,.unpublished i.icon.icon-kiss:before,.unpublished i.icon.icon-laugh-beam:before,.unpublished i.icon.icon-laugh-squint:before,.unpublished i.icon.icon-laugh-wink:before,.unpublished i.icon.icon-laugh:before,.unpublished i.icon.icon-lemon:before,.unpublished i.icon.icon-life-ring:before,.unpublished i.icon.icon-lightbulb:before,.unpublished i.icon.icon-list-alt:before,.unpublished i.icon.icon-map:before,.unpublished i.icon.icon-meh-blank:before,.unpublished i.icon.icon-meh-rolling-eyes:before,.unpublished i.icon.icon-meh:before,.unpublished i.icon.icon-minus-square:before,.unpublished i.icon.icon-money-bill-alt:before,.unpublished i.icon.icon-moon:before,.unpublished i.icon.icon-newspaper:before,.unpublished i.icon.icon-object-group:before,.unpublished i.icon.icon-object-ungroup:before,.unpublished i.icon.icon-paper-plane:before,.unpublished i.icon.icon-pause-circle:before,.unpublished i.icon.icon-play-circle:before,.unpublished i.icon.icon-plus-square:before,.unpublished i.icon.icon-question-circle:before,.unpublished i.icon.icon-registered:before,.unpublished i.icon.icon-sad-cry:before,.unpublished i.icon.icon-sad-tear:before,.unpublished i.icon.icon-save:before,.unpublished i.icon.icon-share-square:before,.unpublished i.icon.icon-smile-beam:before,.unpublished i.icon.icon-smile-wink:before,.unpublished i.icon.icon-smile:before,.unpublished i.icon.icon-snowflake:before,.unpublished i.icon.icon-square:before,.unpublished i.icon.icon-star-half:before,.unpublished i.icon.icon-star:before,.unpublished i.icon.icon-sticky-note:before,.unpublished i.icon.icon-stop-circle:before,.unpublished i.icon.icon-sun:before,.unpublished i.icon.icon-surprise:before,.unpublished i.icon.icon-thumbs-down:before,.unpublished i.icon.icon-thumbs-up:before,.unpublished i.icon.icon-times-circle:before,.unpublished i.icon.icon-tired:before,.unpublished i.icon.icon-trash-alt:before,.unpublished i.icon.icon-user-circle:before,.unpublished i.icon.icon-user:before,.unpublished i.icon.icon-window-close:before,.unpublished i.icon.icon-window-maximize:before,.unpublished i.icon.icon-window-minimize:before,.unpublished i.icon.icon-window-restore:before{font-weight:400}.x-tree-node-el .icon-plus-circle,.x-tree-node-el .icon-refresh{font-size:1em;vertical-align:0}.unpublished,.unpublished a span{color:#9c9c9c!important;font-style:normal}.unpublished a span i.icon,.unpublished a span i.icon-large,.unpublished i.icon,.unpublished i.icon-large{color:#9c9c9c!important}.hidemenu,.hidemenu a span{color:#999;font-style:italic}.hidemenu.unpublished a span i.icon,.hidemenu.unpublished a span i.icon-large,.hidemenu.unpublished i.icon,.hidemenu.unpublished i.icon-large,.hidemenu a span.unpublished a span i.icon,.hidemenu a span.unpublished a span i.icon-large,.hidemenu a span.unpublished i.icon,.hidemenu a span.unpublished i.icon-large{color:#999}.hidemenu a span i.icon,.hidemenu a span i.icon-large,.hidemenu i.icon,.hidemenu i.icon-large{color:#383838}.deleted,.deleted a span,.deleted i.icon,.deleted i.icon-large{color:#af5a62bf!important}.deleted a span{text-decoration:line-through}.element-node-disabled a span{color:#919191}.x-tree-node{background:#fff;color:#999;position:relative}.x-tree-node .element-node-disabled a span,.x-tree-node .element-node-disabled i.icon,.x-tree-node .x-tree-node-disabled a span,.x-tree-node .x-tree-node-disabled i.icon{color:#919191}.element-node-locked a span{font-style:inherit}.modx-tree-node-tool-ct{bottom:0;line-height:1.8;position:absolute;right:6px;top:0}html[dir=rtl] .modx-tree-node-tool-ct{left:6px;right:unset}.modx-tree-node-tool-ct .x-btn:focus,.modx-tree-node-tool-ct .x-btn:hover{color:#6cb24a!important}#modx-gr-tree-resource .modx-tree-node-tool-ct,#modx-ih-resource-tree .modx-tree-node-tool-ct{display:none}.x-tree-node-el .modx-tree-node-btn-create{bottom:0;line-height:34px;opacity:0;overflow:hidden;position:absolute;right:6px;top:0;transition:opacity .4s ease-in}html[dir=rtl] .x-tree-node-el .modx-tree-node-btn-create{left:6px;right:unset}.x-tree-node-el .modx-tree-node-btn-create .x-btn{color:#515151;opacity:.4;transition:opacity .2s ease-in-out,color .2s ease-in-out}.x-tree-node-el .modx-tree-node-btn-create .x-btn:focus,.x-tree-node-el .modx-tree-node-btn-create .x-btn:hover{color:#6cb24a;opacity:1}#modx-gr-tree-resource .x-tree-node-el .modx-tree-node-btn-create,#modx-ih-resource-tree .x-tree-node-el .modx-tree-node-btn-create{display:none}.x-tree-node-el:focus-within .modx-tree-node-btn-create,.x-tree-node-el:focus .modx-tree-node-btn-create,.x-tree-node-el:hover .modx-tree-node-btn-create{opacity:1}.tree-pseudoroot-node.x-tree-node-el{background-color:#f1f1f1;font:500 14px/3 -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;padding:0 5px;position:relative}.tree-pseudoroot-node.x-tree-node-el>.icon,.tree-pseudoroot-node.x-tree-node-el a span{color:#53595f}.tree-pseudoroot-node.x-tree-node-el .modx-tree-node-tool-ct{filter:alpha(opacity=50);line-height:3;opacity:.5}.tree-pseudoroot-node.x-tree-node-el .modx-tree-node-tool-ct .x-btn{margin-left:2px}.tree-pseudoroot-node.x-tree-node-el.x-tree-node-collapsed{border-bottom:1px solid #e4e4e4}.tree-pseudoroot-node.x-tree-node-el.x-tree-node-expanded,.tree-pseudoroot-node.x-tree-node-el.x-tree-node-expanded>.icon,.tree-pseudoroot-node.x-tree-node-el.x-tree-node-expanded span{color:#53595f}.tree-pseudoroot-node.x-tree-node-el.x-tree-node-over{background-color:#e4e4e4;color:#53595f}.tree-pseudoroot-node.x-tree-node-el+.x-tree-node-ct,.tree-pseudoroot-node.x-tree-node-el+div>.x-tree-node-ct{background:#fbfbfb;overflow-x:auto}.tree-pseudoroot-node.x-tree-node-el+.x-tree-node-ct:empty,.tree-pseudoroot-node.x-tree-node-el+div>.x-tree-node-ct:empty{padding:0}.tree-pseudoroot-node.x-tree-node-el:hover .modx-tree-node-tool-ct{filter:alpha(opacity=100);opacity:1}.tree-pseudoroot-node.x-tree-node-el:hover .modx-tree-node-tool-ct .x-btn{color:inherit}.x-tree-elbow,.x-tree-elbow-end{display:inline-block}#modx-leftbar .icon,.x-tree-node .icon{background:none;border:0;display:inline-block;filter:alpha(opacity=80);margin:0;opacity:.8;padding:3px;text-align:center}#modx-leftbar .icon.icon-code:before,#modx-leftbar .icon.icon-cogs:before,#modx-leftbar .icon.icon-columns:before,#modx-leftbar .icon.icon-folder:before,#modx-leftbar .icon.icon-th-large:before,.x-tree-node .icon.icon-code:before,.x-tree-node .icon.icon-cogs:before,.x-tree-node .icon.icon-columns:before,.x-tree-node .icon.icon-folder:before,.x-tree-node .icon.icon-th-large:before{font-weight:900}#modx-leftbar .icon i,.x-tree-node .icon i{font-style:normal}#modx-leftbar .icon button,.x-tree-node .icon button{display:none}.x-tree-node-ct .x-tree-node .icon{left:-1px;position:relative;top:-1px}.x-dd-drag-ghost a,.x-dd-drag-ghost a span,.x-tree-node a,.x-tree-node a span{color:#383838}.x-tree-node div.x-tree-drag-insert-below{border-bottom:2px solid #a8c3e2!important}.x-tree-node div.x-tree-drag-insert-above{border-top:2px solid #a8c3e2!important}.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below a{border-bottom:2px solid #a8c3e2!important}.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above a{border-top:2px solid #a8c3e2!important}.x-tree-node .x-tree-drag-append a span,.x-tree-node .x-tree-node-over{background-color:#e4e4e4}.x-tree-node .x-tree-selected{background-color:#d6e7f8}.x-tree-node .x-tree-expanded{background-color:#e4e4e4;color:#234368}.x-tree-node .x-tree-expanded a,.x-tree-node .x-tree-expanded a span{color:#234368}.icon-rss:before{content:"\f09e"}.icon-cal:before,.icon-ical:before,.icon-ics:before,.icon-vcs:before{content:"\f133"}.icon-db:before,.icon-sql:before{content:"\f1c0"}.icon-7z:before,.icon-bz2:before,.icon-dmg:before,.icon-gz:before,.icon-iso:before,.icon-rar:before,.icon-tar:before,.icon-tgz:before,.icon-zip:before{content:"\f1c6"}.icon-backup:before,.icon-bak:before,.icon-bk:before{content:"\f1da"}.icon-bmp:before,.icon-gif:before,.icon-jpeg:before,.icon-jpg:before,.icon-png:before,.icon-svg:before,.icon-tiff:before{content:"\f1c5"}.icon-bat:before,.icon-scr:before,.icon-sh:before{content:"\f120"}.icon-log:before,.icon-txt:before{content:"\f15c"}.icon-aac:before,.icon-aif:before,.icon-aiff:before,.icon-flac:before,.icon-m4a:before,.icon-mp3:before,.icon-ogg:before,.icon-wav:before,.icon-wma:before{content:"\f1c7"}.icon-3gp:before,.icon-avi:before,.icon-fla:before,.icon-flv:before,.icon-m4v:before,.icon-mov:before,.icon-mp4:before,.icon-mpeg:before,.icon-mpg:before,.icon-swf:before,.icon-wmv:before{content:"\f1c8"}.icon-access:before,.icon-htaccess:before{content:"\f023"}.icon-as:before,.icon-cfm:before,.icon-jar:before,.icon-java:before,.icon-php:before,.icon-rb:before{content:"\f1c9"}.icon-doc:before,.icon-docx:before{content:"\f1c2"}.icon-csv:before,.icon-xls:before,.icon-xlsx:before{content:"\f1c3"}.icon-ppt:before,.icon-pptx:before{content:"\f1c4"}.icon-pdf:before{content:"\f1c1"}.icon-coffeescript:before,.icon-css:before,.icon-htm:before,.icon-html:before,.icon-js:before,.icon-json:before,.icon-less:before,.icon-scss:before,.icon-styl:before,.icon-xml:before{content:"\f1c9"}.icon-action{background-image:url(../images/restyle/icons/application_osx_terminal.png)!important;background-position:50%!important;background-repeat:no-repeat!important;min-height:16px;min-width:16px;vertical-align:middle}.icon-action.x-tree-node-el{background-position:5px 5px!important}.icon-action:before{content:" "}.icon-namespace{background-image:url(../images/restyle/icons/computer.png)!important;background-position:50%!important;background-repeat:no-repeat!important;min-height:16px;min-width:16px;vertical-align:middle}.icon-namespace.x-tree-node-el{background-position:5px 5px!important}.icon-namespace:before{content:" "}.icon-list-new{background-image:url(../images/restyle/icons/layout_add.png)!important;background-position:50%!important;background-repeat:no-repeat!important;min-height:16px;min-width:16px;vertical-align:middle}.icon-list-new.x-tree-node-el{background-position:5px 5px!important}.icon-list-new:before{content:" "}.icon-mark-active{background-image:url(../images/restyle/icons/layout_edit.png)!important;background-position:50%!important;background-repeat:no-repeat!important;min-height:16px;min-width:16px;vertical-align:middle}.icon-mark-active.x-tree-node-el{background-position:5px 5px!important}.icon-mark-active:before{content:" "}.icon-mark-complete{background-image:url(../images/restyle/icons/layout_header.png)!important;background-position:50%!important;background-repeat:no-repeat!important;min-height:16px;min-width:16px;vertical-align:middle}.icon-mark-complete.x-tree-node-el{background-position:5px 5px!important}.icon-mark-complete:before{content:" "}.icon-package{background-image:url(../images/restyle/icons/package.png)!important;background-position:50%!important;background-repeat:no-repeat!important;min-height:16px;min-width:16px;padding-right:5px!important;vertical-align:middle}.icon-package.x-tree-node-el{background-position:5px 5px!important}.icon-package:before{content:" "}.icon-locked{background-image:url(../images/restyle/icons/lock_edit.png)!important;background-position:50%!important;background-repeat:no-repeat!important;min-height:16px;min-width:16px;vertical-align:middle}.icon-locked.x-tree-node-el{background-position:5px 5px!important}.icon-locked:before{content:" "}.icon-lock{content:"\f023"}#modx-resource-tree-panel .x-accordion-hd{background-position:0 0}#modx-element-tree-panel .x-accordion-hd{background-position:0 -32px}#modx-file-tree-panel .x-accordion-hd{background-position:0 -64px}#modx-static-page-settings .x-accordion-hd{background-position:0 -96px}.x-tree-node-el .x-tree-node-icon{display:inline-block}.x-tree-node-loading .x-tree-node-icon{background-image:url(../images/modx-theme/tree/loading.gif)!important}.x-tree-node-loading a span{color:#444;font-style:italic}.tree-context:before{content:"\f0ac"}.tree-resource:before{content:"\f15b"}.x-tree-node-el.unpublished .tree-resource:before{font-weight:400}.tree-resource.tree-static-resource:before{content:"\f15c"}.tree-resource.tree-weblink:before{content:"\f0c1"}.x-tree-node-el.unpublished .tree-resource.tree-weblink:before{font-weight:900}.tree-resource.tree-symlink:before{content:"\f0c5"}.tree-resource.icon-folder:before,.tree-resource.parent-resource:before{content:"\f07b"}.x-tree-node-expanded .tree-resource.icon-folder:before,.x-tree-node-expanded .tree-resource.parent-resource:before{content:"\f07c"}.tree-resource.locked-resource:before{content:"\f023"!important}.x-tree-node-el.unpublished .tree-resource.locked-resource:before{font-weight:900}.ext-ie .x-tree-node-el input{height:15px;width:15px}.x-tree-root-ct{border-radius:0;overflow:hidden;padding:0!important}.x-tree-root-node{margin:0}.x-dd-drag-ghost a,.x-dd-drag-ghost a span,.x-tree-node,.x-tree-node a,.x-tree-node a span{color:#383838}.x-tree-node .x-tree-node-disabled a span{color:#b7b7b7}.x-tree-node div.x-tree-drag-insert-below{border-bottom-color:#686868}.x-tree-node div.x-tree-drag-insert-above{border-top-color:#686868}.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below a{border-bottom-color:#686868}.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above a{border-top-color:#686868}.x-tree-node .x-tree-drag-append a span{background-color:#dfdfdf;border-color:#e4e4e4}.x-tree-drop-ok-append .x-dd-drop-icon{background-image:url(../images/modx-theme/tree/drop-add.gif)}.x-tree-drop-ok-above .x-dd-drop-icon{background-image:url(../images/modx-theme/tree/drop-over.gif)}.x-tree-drop-ok-below .x-dd-drop-icon{background-image:url(../images/modx-theme/tree/drop-under.gif)}.x-tree-drop-ok-between .x-dd-drop-icon{background-image:url(../images/modx-theme/tree/drop-between.gif)}#modx-leftbar-header{align-items:center;box-sizing:border-box;color:#53595f;display:flex;height:57px;justify-content:left;padding:.67rem 1rem}#modx-leftbar-header img{max-height:100%;max-width:33%}#modx-leftbar-header a{color:#53595f;font:normal 25px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:16px;text-decoration:none}#modx-leftbar-header a:focus,#modx-leftbar-header a:hover{color:#234368}#modx-leftbar-header a:after{content:"\f06e";font-size:14px;opacity:.5;padding:5px}#modx-leftbar-header img+a{padding-left:.67rem}#modx-leftbar-tabpanel .x-tab-panel-header .x-tab-strip-wrap{margin:0;padding:0}#modx-leftbar-tabpanel .x-tab-panel-header .x-tab-strip{display:flex;width:100%}#modx-leftbar-tabpanel .x-tab-panel-header .x-tab-strip li{box-sizing:border-box;flex-grow:1;float:none;margin-left:0;text-align:center}#modx-leftbar-tabpanel .x-tab-panel-header .x-tab-strip li#modx-leftbar-tabpanel__modx-trash-link{border-right:none}#modx-leftbar-tabpanel .x-tab-panel-header .x-tab-strip li:hover{color:#234368}#modx-leftbar-tabpanel .x-tab-panel-header .x-tab-strip li.x-tab-strip-active{background:#f1f1f1}#modx-leftbar-tabpanel .x-tab-panel-header .x-tab-strip li.x-tab-strip-active:after{box-shadow:none}#modx-leftbar-tabpanel .x-tab-panel-header .x-tab-strip li.x-tab-strip-active:before{background:#0000}#modx-leftbar-tabpanel .x-tab-panel-header .x-tab-strip .x-clear,#modx-leftbar-tabpanel .x-tab-panel-header .x-tab-strip .x-tab-edge{display:none}#modx-leftbar-tabpanel__modx-trash-link .icon{opacity:.5}#modx-leftbar-tabpanel__modx-trash-link.active .icon{opacity:1}#modx-leftbar-tabpanel__modx-trash-link.active:hover .icon{color:#cf1124}.modx-browser-rte{background:#fff}.modx-browser-tree{background:#fff;border-radius:3px}.modx-browser-rte .modx-browser-tree,.x-window .modx-browser-tree{border-radius:0;border-right:1px solid #e4e4e4;box-shadow:none}.modx-browser-view-ct{background:#fff;border-radius:3px;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.modx-browser-rte .modx-browser-view-ct,.x-window .modx-browser-view-ct{border-radius:0;box-shadow:none}.modx-browser-thumb-wrap{cursor:pointer;float:left;margin:5px;overflow:hidden;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.modx-browser-thumb-wrap.x-view-over .modx-browser-placeholder{color:#515151}.modx-browser-thumb-wrap.x-view-over .modx-browser-thumb{border:1px dotted #515151}.modx-browser-thumb-wrap.x-view-selected .modx-browser-placeholder{color:#234368}.modx-browser-thumb-wrap.x-view-selected .modx-browser-thumb{border:1px solid #234368}.modx-browser-thumb{background:#fff;border:1px solid #e4e4e4;height:100px;line-height:100px;padding:5px;width:100px}.modx-browser-thumb img{background-color:#ccc;background-image:url(../images/modx-theme/transparency-pattern.png);max-width:100%;vertical-align:middle}.modx-browser-placeholder{color:#dcdcdc;font-size:14px}.details .modx-browser-placeholder{align-items:center;display:flex;font-size:24px;font-weight:700;height:100px;justify-content:center;overflow:hidden;width:100%}.modx-browser-list-item{padding:0 5px}.modx-browser-list-item>span{background-position:0!important;border-bottom:1px solid #e4e4e4;clear:both;display:block;min-height:16px;padding:5px 0 5px 20px;position:relative}.modx-browser-list-item>span:before{font-size:14px;left:2px;position:absolute}.modx-browser-list-item>span span{display:inline-block;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.modx-browser-list-item>span span.file-size,.modx-browser-list-item>span span.image-size{float:right;width:13%}.modx-browser-list-item.x-view-over>span{background:#fbfbfb}.modx-browser-list-item.x-view-selected>span{background:#fbfbfb;color:#234368}.modx-browser-view-ct .loading-indicator{background-position:0;background-repeat:no-repeat;font-size:11px;margin:10px;padding-left:20px}.modx-browser-pathbbar table,.modx-browser-pathbbar tbody,.modx-browser-pathbbar td,.modx-browser-pathbbar tr{display:block}.modx-browser-pathbbar .x-toolbar-left .x-toolbar-left-row td.x-toolbar-cell{position:relative}.modx-browser-pathbbar .x-toolbar-left .x-toolbar-left-row td.x-toolbar-cell:before{content:"\f328";filter:alpha(opacity=60);font-size:14px;left:0;opacity:.6;position:absolute;text-align:center;top:50%;width:30px}.modx-browser-pathbbar .x-toolbar-left .x-toolbar-left-row .modx-browser-filepath{background:#0000;border:0;border-radius:0;border-top:1px solid #e4e4e4;box-sizing:border-box;height:32px!important;margin:0!important;padding-left:30px;width:100%}.modx-browser-details-ct{background:#fff;border-radius:3px}.modx-browser-rte .modx-browser-details-ct,.x-window .modx-browser-details-ct{border-left:1px solid #e4e4e4;border-radius:0;box-shadow:none}.modx-browser-detail-thumb{color:#000;cursor:default;padding:5px;position:relative}.modx-browser-detail-thumb.preview{cursor:pointer}.modx-browser-detail-thumb.preview:before{content:"\f002";filter:alpha(opacity=0);font-size:56px;left:0;margin-top:-28px;opacity:0;position:absolute;text-align:center;text-shadow:0 0 10px #0003;top:50%;transition:opacity .25s;width:100%}.modx-browser-detail-thumb.preview:hover:before{filter:alpha(opacity=60);opacity:.6}.modx-browser-detail-thumb img{background-color:#ccc;background-image:url(../images/modx-theme/transparency-pattern.png);display:block;height:auto;margin:0 auto;max-width:100%;width:100%}.modx-browser-details-info{border-top:1px solid #e4e4e4;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;padding:15px;text-align:left}.modx-browser-details-info b{color:#53595f;display:block;margin-bottom:2px}.modx-browser-details-info span{display:block;margin-bottom:10px}.modx-browser-fullview{text-align:center}.modx-browser-fullview img{background-color:#ccc;background-image:url(../images/modx-theme/transparency-pattern.png);display:block;height:auto;margin:0 auto;max-width:100%;width:100%}@media screen and (max-width:960px){.modx-browser{max-height:100%!important;overflow-y:scroll;top:15px!important}.modx-browser-panel{background-color:#fff!important;margin:15px 0!important;min-height:700px;width:100%!important}.modx-browser-tree,.modx-browser-view-ct{max-width:35%!important;width:35%!important}.modx-browser-details-ct,.modx-browser-tree,.modx-browser-view-ct{display:inline-block!important;float:left;left:0!important;padding:0 5px;position:relative!important}.modx-browser-details-ct{max-width:20%!important;width:20%!important}.modx-browser-details-ct *,.modx-browser-tree *,.modx-browser-view-ct *{font-size:12px!important}.modx-browser-details-ct input,.modx-browser-tree input,.modx-browser-view-ct input{padding:5px!important}.modx-browser-tree .x-toolbar-ct tbody tr td{display:table-cell}.modx-browser-view-ct .x-panel-body,.modx-browser-view-ct .x-panel-tbar,.modx-browser-view-ct .x-panel-tbar-noheader,.modx-browser-view-ct .x-panel-tbar .x-toolbar,.modx-browser .x-panel-tbar-noheader,.modx-browser .x-toolbar{width:100%!important}.modx-browser-view-ct .x-panel-tbar .x-toolbar-cell label{line-height:2.2}.modx-browser-thumb-wrap{margin:5px;padding:5px;width:24%}.modx-browser-thumb{height:25px;line-height:25px;max-width:100%;overflow:hidden;padding:0}.modx-browser-thumb img{max-width:100%}.modx-browser-placeholder{height:50px}.modx-browser-details-info{padding:5px}}.x-window{-webkit-backface-visibility:hidden;border-radius:3px;box-shadow:0 0 15px 0 #0003;filter:alpha(opacity=0);opacity:0;overflow:visible;transform:scale(1) translateZ(0);transition:opacity .25s ease-in-out,transform .25s ease-in-out}.x-window.anim-ready{transform:scale(.7) translateZ(0)}.x-window.zoom-in{filter:alpha(opacity=100);opacity:1;transform:scale(1) translateZ(0)}.x-window.zoom-out{filter:alpha(opacity=0);opacity:0;transform:scale(1.3) translateZ(0)}.ext-ie8 .x-window.x-window-dlg{filter:alpha(opacity=100)}.x-window .x-window-tl,.x-window .x-window-tr{padding:0}.x-window .x-window-tc{z-index:1}.x-window .x-window-tc .x-window-header{background-color:#f4f4f4;border-bottom:1px solid #f4f4f4;border-radius:3px 3px 0 0;color:#515151;font:normal 13px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-weight:700;padding:8px;text-align:center}.x-window .x-window-tc .x-window-header-text{padding-left:24px}.x-window.x-panel-collapsed .x-window-tl{border-bottom:1px solid #dcdcdc}.x-window.x-panel-collapsed .x-window-header{border-radius:3px}.x-window .x-window-bwrap{overflow:visible}.x-window .x-window-bwrap .x-window-ml,.x-window .x-window-bwrap .x-window-mr{padding:0}.x-window .x-window-bwrap .x-window-mc{border:0;padding:0}.x-window .x-window-bwrap .x-window-mc .x-panel-bl,.x-window .x-window-bwrap .x-window-mc .x-panel-mc,.x-window .x-window-bwrap .x-window-mc .x-panel-ml,.x-window .x-window-bwrap .x-window-mc .x-panel-mr,.x-window .x-window-bwrap .x-window-mc .x-panel-tl{background:#0000;border:0;padding:0}.x-window .x-window-body{background-color:#fff!important;border:0;overflow-y:auto;padding:15px}.x-window.modx-window .x-window-body{padding-top:0}.x-window.modx-window.modx-alert .x-window-body,.x-window.modx-window.modx-confirm .x-window-body,.x-window.modx-window.modx-console .x-window-body,.x-window.modx-window .x-window-with-tabs .x-window-body{padding-top:15px}.x-window.modx-window .x-window-tc .x-window-header-text{padding-left:64px}.x-window .x-panel-bwrap{background:#fff;padding:0}.x-window .x-panel-bwrap .x-panel-bwrap{background:#0000;box-shadow:none;overflow:visible;padding:0}.x-window .x-window-with-tabs .x-window-body{background-color:#fbfbfb!important;overflow:visible}.x-window .x-window-with-tabs .x-panel-bwrap{background:#0000;box-shadow:none;overflow:visible;padding:0}.x-window form.x-panel-body:first-of-type{overflow:visible!important}.x-window .modx-tabs .x-tab-panel-header .x-tab-strip-wrap{padding-top:3px}.x-window .modx-tabs .x-tab-panel-header .x-tab-strip-wrap .x-tab-strip{border:0}.x-window .x-tab-panel-bwrap{background:#fff;box-shadow:0 4px 6px #00000026;padding:10px}.x-window .x-tab-panel-bwrap .x-tab-panel-body{overflow-y:auto}.x-window .x-tab-panel-bwrap .x-tab-panel-body .modx-panel .x-panel-bwrap,.x-window .x-window-bl,.x-window .x-window-br{padding:0}.x-window .x-window-bc .x-window-footer{background-color:#fff;border-radius:0 0 3px 3px;border-top:1px solid #fff;box-sizing:border-box;padding:5px 15px 15px;width:100%!important}.x-window.x-window-maximized{margin:0}.x-window.x-window-maximized .x-window-mc,.x-window.x-window-maximized .x-window-tc{padding:0}.x-window.modx-console .modx-console-text{background-color:#fff;border:none;font:12px SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;height:auto!important}.x-window.modx-console .debug{color:#515151}.x-window.modx-console .success{color:#6cb24a}.x-window.modx-console .warn{color:#4a90e2}.x-window.modx-console .error{color:#cf1124}.x-progress-wrap{border:1px solid #6cb24a;width:100%!important}.x-progress-wrap .x-progress-inner{background-color:#fdfefd}.x-progress-wrap .x-progress-bar{background-color:#6cb24a;border:0}.x-progress-wrap .x-progress-text{color:#fff;font-size:11px;font-weight:700}.x-progress-wrap .x-progress-text-back{color:#515151}.ext-el-mask{background-color:#fff;filter:alpha(opacity=0);opacity:0;transition:opacity .25s}.ext-el-mask.fade-in,.x-masked .ext-el-mask{filter:alpha(opacity=50);opacity:.5}.x-masked .ext-el-mask{z-index:9}.ext-mb-icon{display:inline-block;float:left;position:relative;width:40px!important}.ext-mb-icon:before{color:#4a90e2;content:"";font-size:32px;position:absolute;right:0;text-align:left;top:50%;transform:translateY(-50%);width:100%}.ext-mb-icon.ext-mb-info:before{color:#4a90e2;content:"\f05a"}.ext-mb-icon.ext-mb-question:before{color:#4a90e2;content:"\f059"}.ext-mb-icon.ext-mb-warning:before{color:#f0b429;content:"\f071"}.ext-mb-icon.ext-mb-error:before{color:#cf1124;content:"\f057"}.ext-mb-content{display:block;margin-left:0!important}.ext-el-mask-msg{background-color:#fff;border:1px solid #dcdcdc;border-radius:3px;box-shadow:0 4px 6px #00000026;padding:5px;z-index:10}.ext-el-mask-msg div{background-color:initial;border:0;color:#515151;cursor:default;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.ext-el-mask-msg .modx-lockmask div{color:#cf1124}.x-mask-loading div{background-image:url(../images/modx-theme/grid/loading.gif)}.dashboard{display:flex;flex-flow:row wrap;margin:-.5rem 0 0 -1rem!important;padding:0 15px}.dashboard .dashboard-button{background:#fff;border:1px solid #0000;border-radius:3px;display:inline-block;padding:5px 20px;text-decoration:none}.dashboard .dashboard-button-green{background:#6cb24a;border-color:#6cb24a;color:#fff}.dashboard .dashboard-button[disabled]{background-color:#e4e4e4}.dashboard .dashboard-button:not([disabled]):hover{border-color:#e4e4e4}.dashboard .dashboard-block{margin:1rem 0 0 1rem}.dashboard .dashboard-block:not(.headless){background-color:#fff;border-radius:3px}.dashboard .dashboard-block.headless .body{max-height:100%;overflow:visible;padding:0}.dashboard .dashboard-block.quarter{width:calc(25% - 1rem)}.dashboard .dashboard-block.one-third{width:calc(33.33332% - 1rem)}.dashboard .dashboard-block.half{width:calc(50% - 1rem)}.dashboard .dashboard-block.two-thirds{width:calc(66.66668% - 1rem)}.dashboard .dashboard-block.three-quarters{width:calc(75% - 1rem)}.dashboard .dashboard-block.full{width:calc(100% - 1rem)}.dashboard .dashboard-block.double{margin-top:2rem;min-height:250px;width:calc(100% - 1rem)}.dashboard .dashboard-block.double .body{height:100%;max-height:100%}.dashboard .dashboard-block.double .dashboard-buttons{height:100%}.dashboard .dashboard-block.double .dashboard-button{align-items:center}.dashboard .dashboard-block h4{color:#515151;font-size:13px;padding-bottom:2px}.dashboard .dashboard-block em{font-style:italic}.dashboard .dashboard-block strong{font-weight:700}.dashboard .dashboard-block ul{list-style:circle outside;padding:0 0 0 15px}.dashboard .dashboard-block img{max-width:100%}.dashboard .dashboard-block .draggable{cursor:move}.dashboard .dashboard-block .action-buttons{margin-left:auto;margin-right:10px}.dashboard .dashboard-block .action-buttons button{background:#0000;border:none;cursor:pointer;opacity:0}.dashboard .dashboard-block .action-buttons button.hidden{display:none}.dashboard .dashboard-block .body{color:#444;font-size:12px;height:auto;max-height:300px;overflow:auto;padding:10px;position:relative}.dashboard .dashboard-block .body .action-buttons{position:absolute;right:-5px;top:20px}.dashboard .dashboard-block .title-wrapper{align-items:center;border-bottom:1px solid #f0f0f0;display:flex;flex-wrap:nowrap}.dashboard .dashboard-block .title-wrapper .title{zoom:1;background:#fff;border-radius:3px;color:#515151;flex-grow:1;font-size:12px;font-weight:700;margin:0;padding:15px 10px}.dashboard .dashboard-block .actions button{height:10px;width:10px}.dashboard .dashboard-block:focus-within .action-buttons button,.dashboard .dashboard-block:hover .action-buttons button{opacity:1}.dashboard ul.configcheck{list-style-type:none;padding:0}.dashboard ul.configcheck li{background-color:#fbfbfb;margin-bottom:.5em;margin-top:.5em;padding:1em 1.618em}.dashboard ul.configcheck li h5{color:#cf1124}.dashboard ul.configcheck li p{color:#515151}.dashboard .news_article{border-bottom:1px solid #dfdfdf;overflow:hidden;padding:15px 0}.dashboard .news_article h2 a{text-decoration:none}.dashboard .news_article h2{font-size:18px}.dashboard .news_article .date_stamp{float:right;font-size:12px;font-style:italic}.dashboard .configcheck a,.dashboard .news_article a{text-decoration:underline}.dashboard .configcheck a:hover,.dashboard .news_article a:hover{text-decoration:none}.dashboard .table-wrapper{overflow:auto;width:100%}.dashboard .table-wrapper table{border:1px solid #ddd;border-radius:5px;width:100%}.dashboard .table-wrapper table th{border-bottom:2px solid #f0f0f0;font-weight:700;padding:10px;text-align:initial}.dashboard .table-wrapper table td{border-bottom:1px solid #f0f0f0;padding:10px;vertical-align:center;white-space:nowrap}.dashboard .table-wrapper table td .unpublished{color:#999;font-style:italic}.dashboard .table-wrapper table td .deleted{color:#af5a62bf!important;text-decoration:line-through}.dashboard .table-wrapper table tr:last-child td,.dashboard .table-wrapper table tr:last-child td tr:last-child td{border:none}.dashboard .table-wrapper table tr:last-child td tr:last-child td:first-child{border-bottom-left-radius:10px}.dashboard .table-wrapper table tr:last-child td tr:last-child td:last-child{border-bottom-right-radius:10px}.dashboard .widget-footer{border-top:1px solid #f0f0f0;padding-top:10px}.dashboard .widget-footer a{display:block;font-size:14px;padding-bottom:5px;padding-top:5px;text-align:center;text-decoration:none}.dashboard .widget-actions a{border:1px solid #e4e4e4;border-radius:3px;display:inline-block;margin-left:5px;padding:3px 5px;text-decoration:none}.dashboard .widget-actions a:first-child{margin-left:0}.dashboard .widget-actions a:hover{background:#f0f0f0}.dashboard .widget-actions a .icon{display:inline-block;height:12px;text-align:center;width:12px}.dashboard .no-results{color:#999;padding:10px;text-align:center}.dashboard .user-with-avatar{align-items:center;display:flex}.dashboard .user-with-avatar .user-avatar{margin:0 10px}.dashboard .user-with-avatar .user-avatar img{border-radius:50%;width:35px}.dashboard .user-with-avatar .user-name{color:#234368;font-weight:500}.dashboard .user-with-avatar .user-group{color:#999}.dashboard .occurred-date,.dashboard .resource .title{color:#234368;font-weight:500}.dashboard .occurred-time{color:#999}#modx-news-feed-container img{max-width:100%}.dashboard-buttons{display:flex;flex-wrap:wrap;justify-content:center;margin:-1rem 0 0 -1rem;width:calc(100% + 1rem)}.dashboard-buttons .dashboard-button{align-items:center;background-color:#fff;border-radius:3px;color:#53595f;display:flex;flex:1;margin:1rem 0 0 1rem;padding:20px;text-decoration:none}.dashboard-buttons .dashboard-button:hover{color:#000}.dashboard-buttons .dashboard-button:hover .icon{opacity:.7}.dashboard-buttons .dashboard-button-icon{background:#6cb24a33;border:1px solid #6cb24a;border-radius:20px;padding:10px;text-align:center}.dashboard-buttons .dashboard-button-icon .icon{color:#6cb24a;display:block;font-size:16px;font-weight:700;height:16px;text-align:center;width:16px}.dashboard-buttons .dashboard-button-wrapper{padding:0 10px}.dashboard-buttons .dashboard-button-title{font-weight:700}::-webkit-scrollbar,::-webkit-scrollbar-thumb{background-color:initial;border:.25rem solid #0000;border-radius:.5rem;height:1rem;width:1rem}::-webkit-scrollbar-thumb{box-shadow:inset 0 0 0 1rem #556c881a}::-webkit-scrollbar-thumb:hover{box-shadow:inset 0 0 0 1rem #556c8833}::-webkit-resizer,::-webkit-scrollbar-corner{background-color:initial}.updates-widget .updates-title{color:#234368;font-weight:500}.updates-widget .updates-updateable{background:#4a90e2;border-radius:20px;color:#fff;display:inline-block;font-weight:700;padding:2px 8px}.updates-widget .updates-available,.updates-widget .updates-ok{border-radius:3px;color:#fff;font-size:10px;padding:3px 8px;text-transform:uppercase}.updates-widget .updates-ok{background:#6cb24a}.updates-widget .updates-available{background:#cf1124}#modx-panel-system-info .x-form-label-left .x-form-item{padding:0 5px}#modx-panel-system-info .x-form-label-left .x-form-item:nth-child(2n){background:#f0f0f0}#modx-panel-system-info .x-form-label-left .x-form-item .x-form-display-field{padding:7px 0}@media screen and (max-width:960px){.dashboard-buttons .dashboard-button{align-items:center;flex-direction:column;flex-wrap:wrap;text-align:center}.dashboard-buttons .dashboard-button-wrapper{margin-left:0;margin-top:5px}.dashboard .dashboard-block.half,.dashboard .dashboard-block.one-third,.dashboard .dashboard-block.quarter,.dashboard .dashboard-block.two-thirds{width:calc(100% - 1rem)}.dashboard-buttons{flex-wrap:wrap}.dashboard-buttons .dashboard-button{padding:10px}.dashboard-buttons .dashboard-button-wrapper{display:none}}.nobg .x-panel-body{background:#0000;padding-right:1.5em}#managerbuttons{margin-bottom:1em;overflow:hidden;width:100%}#managerbuttons ul:after,#managerbuttons ul:before{content:" ";display:table}#managerbuttons ul:after{clear:both}#managerbuttons ul{*zoom:1;margin:0;width:100%}#managerbuttons ul li{box-sizing:border-box;display:table;float:left;margin:0;padding:0 1%;position:relative;width:20%}#managerbuttons ul li:first-child{padding-left:0}#managerbuttons ul li:last-child{padding-right:0}#managerbuttons ul li a{background-color:#fff;border:1px solid #e4e4e4;border-radius:3px;box-shadow:0 1px 0 #e4e4e4;color:#53595f;display:table-cell;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-weight:700;padding:12px;position:relative;text-align:center;text-decoration:none;vertical-align:middle}#managerbuttons ul li a span{display:block;line-height:1.4}#managerbuttons ul li a span.headline{font-size:12px}#managerbuttons ul li a span.subline{font-weight:400}#managerbuttons ul li a span.icon{display:block;margin:0 auto;padding:0 0 10px;width:auto}#managerbuttons ul li a:hover span.icon{color:#234368}#contactus,#helpBanner{background:#fff;border:1px solid #e4e4e4;box-shadow:0 1px 0 #e4e4e4;box-sizing:border-box;margin:.75em 0 1.75em;padding:18px;width:100%}#contactus h3,#helpBanner h3{margin:0 0 1em}#helpBanner{background-attachment:none;background-image:url(../images/modx-logo-color.svg),none;background-position:97%;background-repeat:no-repeat;background-size:200px;margin-top:1.5em;min-height:112px}#helpBanner #helpLogo{float:right;height:76px;margin-right:1em;width:200px}#contactus{box-sizing:border-box;float:left;width:60%}#contactus form{display:inline}#contactus input[type=email]{box-sizing:border-box;font-size:1.1em;margin-right:4px;padding:.4em;width:70%}#contactus input[type=submit]{border:0;cursor:pointer;font-size:1.1em;padding:6px 10px}#contactus p{color:#132539;margin:1em 0}#contactus form+p{margin:2em 0 0}#contactus a{color:#000;text-decoration:none}#contactus a:hover{text-decoration:underline}#contactus a:hover i{text-decoration:none}#contactus a i{margin:0 15px -6px 0}#mcsignup input.x-btn{padding:10px 15px}.icon.icon-2x{text-align:center;vertical-align:text-bottom;width:22px}#aboutMODX{background:#f0f0f0;box-sizing:border-box;float:left;margin:1em 0 0 2%;min-height:300px;padding:1em;width:38%}#aboutMODX p{line-height:1.6;margin:0 0 1em}#aboutMODX a{color:#234368;margin:-2px -4px;padding:2px 4px}#aboutMODX a:hover{background-color:#234368;color:#fff;text-decoration:none}.trashrow{background-color:#ccc!important}.x-btn-purge-all{color:#cf1124}.x-btn-purge-all:hover{background:#cf1124;box-shadow:0 0 0 1px #cf1124;color:#fff}.x-btn-restore-all{color:#6cb24a}.x-btn-restore-all:hover{background:#6cb24a;box-shadow:0 0 0 1px #6cb24a;color:#fff}#changelog-tab p{margin-bottom:.3rem}#changelog-tab h1{color:#595959}#changelog-tab h2{font-weight:700;margin-top:1rem}#changelog-tab ul{margin-bottom:1rem}#modx-package-browser-details-main p{color:#595959;margin-bottom:.3rem}#modx-package-browser-details-main h1,#modx-package-browser-details-main h2,#modx-package-browser-details-main h3,#modx-package-browser-details-main h4,#modx-package-browser-details-main h5,#modx-package-browser-details-main h6{color:#595959;font-weight:700}#modx-package-browser-details-main h1{font-size:1.2em}#modx-package-browser-details-main h2{font-size:1.15em}#modx-package-browser-details-main h3{font-size:1.1em}#modx-package-browser-details-main h4{font-size:1.05em}#modx-package-browser-details-main h5{font-size:1em}#modx-package-browser-details-main h6{font-size:.95em}#modx-package-browser-details-aside h4{text-align:center}#modx-package-browser-details-aside ul li{margin-bottom:.5em}.ext-webkit :focus-visible{outline:auto!important;outline-offset:.1em}.ext-webkit :focus-visible.x-form-focus{outline:none!important}.ext-webkit .x-form-check-wrap:focus-within:has(:focus-visible) label:before{outline:auto!important;outline-offset:.1em}.skiplinks{height:0;left:-100rem;position:fixed;top:-100rem;width:0;z-index:99999}.skiplinks a:active,.skiplinks a:focus{background-color:#fff;left:0;margin:1rem;padding:1rem;position:fixed;top:0}body{-webkit-font-smoothing:antialiased;color:#000;font:normal 13px/1.4 -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;scrollbar-color:#e1e3e6 #0000}body a{color:#234368}body a:hover{color:#162a42}h2,h3{color:#515151;font:normal 25px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;margin:0 0 8px -1px}h3{font:550 15px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}strong{font-weight:700}em{font-style:italic}hr{background-color:#e4e4e4;border:0;color:#e4e4e4;height:1px;margin:20px 0}.aleft{text-align:left}.aright{text-align:right}.right{float:right}.left{float:left}.clear{clear:left}.bold{font-weight:700}.installed{color:#515151}.not-installed{color:#999;font-style:italic}.yellow{color:#fce588!important}.orange{color:#f0b429!important}.error,.red{color:#cf1124!important}.green{color:#6cb24a!important}.blue{color:#4a90e2!important}.primary{color:#6cb24a!important}.centered{text-align:center}.wait{background:#0000 url(../images/style/wait.gif) no-repeat scroll center 55px;color:#53595f;font-size:15px;font-weight:700;padding:20px 10px 60px}.padding{background-color:#fff;padding:11px}.dashed{border-bottom:1px dashed #90b1b9}.x-form-text,textarea.x-form-field{border-color:#e4e4e4}#modx-content,#modx-leftbar{position:absolute;transition:left .2s ease}#modx-leftbar-tabpanel{transition:all .6s ease}#modx-content{left:370px;right:0;width:calc(100% - 370px);z-index:0}.modx-form p{padding-bottom:10px}.x-layout-mini{left:2px}#modx-resource-content .x-panel-header{margin:0;padding:15px}#modx-resource-content .x-panel-bwrap{border:0}#modx-resource-content .modx-tv .modx-tv-label{clear:none;float:none;padding:15px 0 4px;position:static;width:auto}#modx-content-above .x-panel-bwrap,#modx-content-below .x-panel-bwrap{border:0}.x-tab-panel-header,.x-tab-panel-header .x-tab-strip li{box-sizing:border-box}@media screen and (max-width:960px){.x-viewport{overflow-y:auto}.x-viewport body{height:auto}}#modx-container{background:#f1f1f1;height:100%;width:100%}@media screen and (max-width:960px){#modx-container{height:auto}}@media screen and (max-width:1140px){#modx-page-settings-left,#modx-page-settings-right,#modx-resource-main-left,#modx-resource-main-right{box-sizing:border-box;margin:0 auto 15px;width:100%!important}#modx-page-settings-left .x-panel-body,#modx-page-settings-right .x-panel-body,#modx-resource-main-left .x-panel-body,#modx-resource-main-right .x-panel-body{height:auto!important;max-height:100%!important;max-width:100%!important;width:auto!important}}@media screen and (max-width:960px){#modx-chunk-form .main-wrapper,#modx-panel-plugin .main-wrapper,#modx-snippet-form .main-wrapper,#modx-template-form .main-wrapper,#modx-tv-tabs .main-wrapper{padding:0;width:100%!important}#modx-chunk-form .main-wrapper>.x-panel-bwrap,#modx-panel-plugin .main-wrapper>.x-panel-bwrap,#modx-snippet-form .main-wrapper>.x-panel-bwrap,#modx-template-form .main-wrapper>.x-panel-bwrap,#modx-tv-tabs .main-wrapper>.x-panel-bwrap{padding:1em}#modx-resource-main-right{margin:15px auto 0}.x-toolbar-ct,.x-toolbar-ct tbody,.x-toolbar-ct tbody tr{display:block}.x-toolbar-ct tbody tr td{display:block;width:100%}.x-toolbar-ct tbody tr td table{width:100%}.x-toolbar-ct tbody tr td table .x-form-field-wrap{margin-left:0!important;margin-right:0!important;width:100%!important}.x-toolbar-ct tbody tr td table .x-btn,.x-toolbar-ct tbody tr td table .x-form-text{box-sizing:border-box;margin-left:0!important;margin-right:0!important;width:100%!important}.x-column{float:none;margin-left:0!important;margin-right:0!important;width:100%!important}#modx-tree-panel-usergroup .main-wrapper{display:inline-block;float:left;max-width:100%;position:relative;width:100%!important}.x-window{left:.5em!important;max-width:100%!important;right:.5em!important;width:auto!important}.x-window .x-window-body{box-sizing:border-box!important;height:auto!important;width:100%!important}.x-window .x-form-field-wrap{width:auto!important}.x-window input{box-sizing:border-box;height:auto!important;width:100%!important}}#modx-template-form .main-wrapper input{max-width:100%!important}@media screen and (max-width:960px){.x-column-inner>.x-column~.x-column{margin-left:0}#modx-import-base-path,.x-form-item label.x-form-item-label[for=modx-import-allowed-extensions],.x-form-item label.x-form-item-label[for=modx-import-base-path],.x-form-item label.x-form-item-label[for=modx-import-element],.x-form-item label.x-form-item-label[for=modx-import-parent],.x-form-item label.x-form-item-label[for=modx-import-resource-class]{float:none;width:auto!important}}#modx-import-allowed-extensions,#modx-import-base-path,#modx-import-element,#modx-import-resource-class{box-sizing:border-box;height:auto;width:100%!important}@media screen and (max-width:960px){#x-form-el-modx-import-allowed-extensions,#x-form-el-modx-import-base-path,#x-form-el-modx-import-element,#x-form-el-modx-import-resource-class{padding-left:0!important;width:100%!important}}.x-panel.drag-n-drop{z-index:0}.x-panel.drag-n-drop:before{background:#0000 url(../images/restyle/dragndrop.svg) no-repeat 50%;background-size:50% 50%;bottom:0;content:" ";display:block;left:0;opacity:.1;position:absolute;right:0;top:0;z-index:-5}.x-panel.drag-n-drop>.x-panel-bwrap,.x-panel.drag-over .x-form-field{background:#0000}.x-panel.drag-over:after{background:#6cb24a;border:5px solid #6cb24a;bottom:0;content:"";display:block;left:0;opacity:.1;position:absolute;right:0;top:0}#modx-panel-packages.drag-n-drop:before{background:#0000 url(../images/restyle/dragndrop.svg) no-repeat top;background-size:50% 30%;z-index:0}.x-panel-header{background:none;border:none;font-size:16px;margin:0;padding:0 0 10px}#modx-resource-tabs .x-panel-header{border-bottom:1px solid #e4e4e4;color:#515151;display:flex;margin-bottom:5px}#modx-resource-tabs .x-panel-header .x-panel-header-text{flex:1;font-size:14px;order:0}#modx-resource-tabs .x-panel-header .x-tool.x-tool-toggle{margin-left:auto;order:1}#modx-resource-main-left .x-panel-header{border-bottom:0;position:absolute;right:15px;z-index:9}#modx-resource-main-left .x-panel-header .x-panel-header-text{display:none}#modx-resource-main-left .x-panel-animated .x-panel-header,#modx-resource-main-left .x-panel-collapsed .x-panel-header{padding-top:15px!important;position:relative;right:0;width:100%}#modx-resource-main-left .x-panel-animated .x-panel-header .x-panel-header-text,#modx-resource-main-left .x-panel-collapsed .x-panel-header .x-panel-header-text{display:block}#modx-resource-tabs .x-panel-collapsed .x-panel-header{border-color:#0000;margin-bottom:0;padding:0}.modx-protected-row .x-grid3-cell-inner{color:#234368;font-style:italic}.x-small-editor .x-form-field{font-size:12px!important}.x-small-editor .x-form-num-field{text-align:left}.grid-row-inactive{color:#999!important}.x-grid-link{color:#234368;-webkit-text-decoration-color:#749fd0;text-decoration-color:#749fd0;-webkit-text-decoration-style:dotted;text-decoration-style:dotted}.x-grid-link:hover{border-bottom-color:#336299;color:#000}.x-grid-link.simulated-link{cursor:pointer}.grid-row-inactive .x-grid-link{color:#999!important;-webkit-text-decoration-color:#999!important;text-decoration-color:#999!important}.x-editable-column{cursor:default}.x-editable-column:not(.editor-disabled){cursor:pointer}.x-editable-column:not(.editor-disabled):focus,.x-editable-column:not(.editor-disabled):hover{color:#234368}.x-editable-column:not(.editor-disabled):focus>div:after,.x-editable-column:not(.editor-disabled):hover>div:after{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:auto;color:#234368;content:"\f304";display:inline-block;font-family:Font Awesome\ 5 Free,Font Awesome\ 5 Brands;font-style:normal;font-variant:normal;font-weight:900;margin:0 .5em}.x-editable-column.locked{cursor:default}.x-editable-column.locked:focus>div:after,.x-editable-column.locked:hover>div:after{color:#6b7c90;content:"\f023"}.x-grid-buttons{text-align:center}.x-grid-buttons li{cursor:pointer;display:inline-block;font-size:1.1em;line-height:.7;margin-right:10px}.x-grid-buttons li:last-child{margin-right:0}.x-grid-empty .error-with-icon{color:#cf1124;font:normal 12px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;line-height:1.3;padding:1rem}.x-grid-empty .error-with-icon:before{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:auto;content:"\f071";display:inline-block;font-family:Font Awesome\ 5 Free,Font Awesome\ 5 Brands;font-style:normal;font-variant:normal;font-weight:900;margin-right:.5rem}.x-grid-empty .error-with-icon *{color:#09121c;line-height:1.6;text-align:left}.x-grid-empty .error-with-icon .error-status-info{margin:.25rem 0;text-align:center}.x-grid-empty .error-with-icon code{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:11px;white-space:pre-line}.xdebug-error{border:none}.xdebug-error tbody td,.xdebug-error tbody th{border-color:#dcdcdc;border-style:solid none none!important;border-width:thin!important;padding:.1rem .25rem}.xdebug-error tbody th{color:#000!important;font-weight:700}.xdebug-error tbody th:first{border-top:none!important}.xdebug-error tbody th[colspan="5"]{border-color:#fff;border-width:thick!important;padding:.5rem 2rem;text-align:center!important}.xdebug-error tbody th[bgcolor^="#f57"]{background:#fdf0f1;font-weight:400}.xdebug-error tbody th[bgcolor^="#e9b"]{background:#234368;color:#fff!important}.xdebug-error tbody td{background-color:#fff}.xdebug-error tbody tr:nth-child(2n) td{background-color:#f0f0f0}.modx-page-header,.modx-page-header div{background-color:initial!important}#modx-panel-trash .modx-page-header,#modx-panel-trash .modx-page-header div,#modx-panel-welcome .modx-page-header,#modx-panel-welcome .modx-page-header div{margin:1rem!important}@media screen and (min-width:961px){#modx-content>.x-panel-bwrap>.x-panel-body .modx-page-header{box-sizing:border-box;margin-top:1.25rem}html[dir=rtl] #modx-content>.x-panel-bwrap>.x-panel-body .modx-page-header{margin-top:4rem}#modx-content>.x-panel-bwrap>.x-panel-body .modx-page-header+div{margin:1rem}#modx-content>.x-panel-bwrap>.x-panel-body>.x-panel{margin:0}#modx-content>.x-panel-bwrap>.x-panel-body>.x-panel .modx-header-breadcrumbs{box-sizing:border-box;font-size:18px;font-weight:700;margin-top:1.25rem;padding:0 15px}html[dir=rtl] #modx-content>.x-panel-bwrap>.x-panel-body>.x-panel .modx-header-breadcrumbs{margin-top:4rem}#modx-content>.x-panel-bwrap>.x-panel-body>.x-panel .modx-header-breadcrumbs+div{margin:1rem}#modx-content>.x-panel-bwrap>.x-panel-body>.x-panel .modx-header-breadcrumbs{width:100%!important}}#modx-content form.x-panel-body{background-color:initial!important}@media screen and (max-width:960px){#modx-content{left:auto!important;position:relative;top:auto!important;width:auto!important}}#modx-content .modx_error{margin:26px 0 0 15px;width:95%}#modx-content .modx_error h2{margin:0 0 14px}#modx-content .modx_error .error_container{background:#f99;border:2px solid #cf1124;border-bottom-left-radius:3px;border-bottom-right-radius:3px;border-top-left-radius:3px;border-top-right-radius:3px;padding:10px}#modx-content .modx_error .error_container ul{list-style:none;margin-left:0;margin-top:6px}#modx-content .modx_error .error_container ul li{margin-bottom:6px}#modx-content .modx_error .error_container ul li:last-child{margin-bottom:0}#modx-content .modx_error .error_container.multiple p:first-child{font-size:1.4em;font-weight:700}@media screen and (max-width:960px){#modx-content .x-panel-body{height:auto!important;max-height:100%!important;max-width:100%!important;width:auto!important}}#modx-mainpanel{height:100%;position:relative}.x-portal .x-panel-dd-spacer,.x-portlet{margin-bottom:10px}.x-portlet .x-panel-ml{padding-left:2px}.x-portlet .x-panel-mr{padding-right:2px}.x-portlet .x-panel-bl{padding-left:2px}.x-portlet .x-panel-br{padding-right:2px}.x-portlet .x-panel-body{background:#fff}.x-portlet .x-panel-mc{padding-top:2px}.x-portlet .x-panel-bc .x-panel-footer{padding-bottom:2px}.x-portlet .x-panel-nofooter .x-panel-bc{height:2px}.x-portal-space h2{border-bottom:1px solid #d4d4d4;margin:0 0 8px;padding:0 0 2px}.x-column-tree .x-panel-header{border-bottom-width:0;padding:3px 0 0}.x-column-tree .x-panel-header .x-panel-header-text{margin-left:3px}.x-column-tree .x-tree-node,.x-column-tree .x-tree-node-el{zoom:1}.x-column-tree .x-tree-selected{background:#d9e8fb}.x-column-tree .x-tree-node a{line-height:18px;vertical-align:middle}.x-column-tree .x-tree-node .x-tree-selected a span{background:#0000;color:#515151}.x-tree-col{zoom:1;float:left;overflow:hidden;padding:0 1px}.x-tree-col-text,.x-tree-hd-text{color:#515151;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;overflow:hidden;padding:3px 3px 3px 5px;text-overflow:ellipsis;white-space:nowrap}.x-tree-headers{zoom:1;cursor:default;margin-top:3px}.x-tree-hd{border-left:1px solid #eee;border-right:1px solid #d0d0d0;float:left;overflow:hidden}.x-grid3-row.disable-selection .x-grid3-row-checker,.x-grid3-row.disable-selection.x-grid3-row-selected .x-grid3-row-checker{position:relative}.x-grid3-row.disable-selection .x-grid3-row-checker:after,.x-grid3-row.disable-selection .x-grid3-row-checker:before,.x-grid3-row.disable-selection.x-grid3-row-selected .x-grid3-row-checker:after,.x-grid3-row.disable-selection.x-grid3-row-selected .x-grid3-row-checker:before{color:#919191}.x-grid3-row.disable-selection .x-grid3-row-checker:before,.x-grid3-row.disable-selection.x-grid3-row-selected .x-grid3-row-checker:before{content:"\f0c8"}.x-grid3-row.disable-selection .x-grid3-row-checker:after,.x-grid3-row.disable-selection.x-grid3-row-selected .x-grid3-row-checker:after{content:"\f715";font-family:Font Awesome\ 5 Free;font-size:6px;font-weight:600;left:50%;margin-left:2px;margin-top:1px;position:absolute;top:50%;transform:translate(-50%,-50%) rotate(98deg)}.x-grid3-row.disable-selection .x-grid3-row-checker:hover,.x-grid3-row.disable-selection.x-grid3-row-selected .x-grid3-row-checker:hover{cursor:default}.ux-row-action-cell .x-grid3-cell-inner{padding:1px 0 0}.ext-ie .ux-row-action-item{width:16px}.ext-ie .ux-row-action-text{width:auto}.ux-row-action-item span{background:#0000 url(../images/style/go-next.png) no-repeat scroll 1px 4px;display:inline!important;line-height:24px;margin:0 5px;padding:5px 5px 5px 22px;vertical-align:middle}.icon-uninstall span{background:url(../images/style/delete.png) no-repeat scroll 1px 4px #0000}.package-details span{background:url(../images/style/info.png) no-repeat scroll 1px 4px #0000}.package-download span{background:url(../images/style/download.png) no-repeat scroll 1px 4px #0000}.package-installed span{background:url(../images/style/accept.png) no-repeat scroll 1px 4px #0000}.ext-ie .ux-row-action-item span{width:auto}.x-grid-group-hd div{height:16px;position:relative}.ux-grow-action-item{background-position:0 50%!important;background-repeat:no-repeat;cursor:pointer;float:left;margin:0;min-width:16px;padding:0!important}.ext-ie .ux-grow-action-item{width:16px}.ux-action-right{float:right;margin:0 3px 0 2px;padding:0!important}.ux-grow-action-text{background:#0000 none!important;float:left;margin:0!important;padding:0!important}.ux-row-action-item:hover{background:#dfdfdf;background:linear-gradient(center bottom,#dfdfdf 0,#fff);border:1px solid #9caf78;color:#636f4c!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=$white,endColorstr=$alto,GradientType=0)}.ux-row-action-item:active{background-color:#fff;background-image:none;border-color:#cfcfcf silver #aaa;box-shadow:inset 0 0 3px #aaa;margin:2px 1px 0}.ux-row-action-item:active span{text-shadow:none}.ux-row-action-item{background:linear-gradient(center bottom,#dcdcdc 0,#fcfcfc);background:url(/manager/templates/default/images/modx-theme/form/button-bg.png) repeat-x scroll 0 bottom #dcdcdc;border-collapse:initial;border-color:#cacaca silver #aaa;border-radius:3px;border-style:solid;border-width:1px;box-shadow:0 0 1px #0003;color:#444;cursor:pointer;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#fcfcfc,endColorstr=#dcdcdc,GradientType=0);float:left;font-weight:700;margin:2px 1px 0;overflow:hidden;padding:3px;position:relative;text-shadow:0 1px 0 #fafafa}.x-tree-checkbox{background:url(../../../assets/ext3/resources/images/default/form/checkbox.gif) no-repeat 0 0;height:13px;margin:0 1px;vertical-align:middle;width:13px}.x-tree-checkbox-over .x-tree-checkbox{background-position:-13px 0}.x-tree-checkbox-down .x-tree-checkbox{background-position:-26px 0}.x-tree-node-disabled .x-tree-checkbox{background-position:-39px 0}.x-tree-node-checked{background-position:0 -13px}.x-tree-checkbox-over .x-tree-node-checked{background-position:-13px -13px}.x-tree-checkbox-down .x-tree-node-checked{background-position:-26px -13px}.x-tree-node-disabled .x-tree-node-checked{background-position:-39px -13px}.x-tree-node-grayed{background-position:0 -26px}.x-tree-checkbox-over .x-tree-node-grayed{background-position:-13px -26px}.x-tree-checkbox-down .x-tree-node-grayed{background-position:-26px -26px}.x-tree-node-disabled .x-tree-node-grayed{background-position:-39px -26px}.x-tree-branch-unchecked .x-tree-checkbox,.x-tree-branch-unchecked .x-tree-node-checked,.x-tree-branch-unchecked .x-tree-node-grayed{background-position:0 0}.x-tree-branch-unchecked .x-tree-checkbox-over .x-tree-checkbox,.x-tree-branch-unchecked .x-tree-checkbox-over .x-tree-node-checked,.x-tree-branch-unchecked .x-tree-checkbox-over .x-tree-node-grayed{background-position:-13px 0}.x-tree-branch-unchecked .x-tree-checkbox-down .x-tree-checkbox,.x-tree-branch-unchecked .x-tree-checkbox-down .x-tree-node-checked,.x-tree-branch-unchecked .x-tree-checkbox-down .x-tree-node-grayed{background-position:-26px 0}.x-tree-branch-unchecked .x-tree-node-disabled .x-tree-checkbox,.x-tree-branch-unchecked .x-tree-node-disabled .x-tree-node-checked,.x-tree-branch-unchecked .x-tree-node-disabled .x-tree-node-grayed{background-position:-39px 0}.x-tree-branch-checked .x-tree-checkbox,.x-tree-branch-checked .x-tree-node-checked,.x-tree-branch-checked .x-tree-node-grayed{background-position:0 -13px}.x-tree-branch-checked .x-tree-checkbox-over .x-tree-checkbox,.x-tree-branch-checked .x-tree-checkbox-over .x-tree-node-checked,.x-tree-branch-checked .x-tree-checkbox-over .x-tree-node-grayed{background-position:-13px -13px}.x-tree-branch-checked .x-tree-checkbox-down .x-tree-checkbox,.x-tree-branch-checked .x-tree-checkbox-down .x-tree-node-checked,.x-tree-branch-checked .x-tree-checkbox-down .x-tree-node-grayed{background-position:-26px -13px}.x-tree-branch-checked .x-tree-node-disabled .x-tree-checkbox,.x-tree-branch-checked .x-tree-node-disabled .x-tree-node-checked,.x-tree-branch-checked .x-tree-node-disabled .x-tree-node-grayed{background-position:-39px -13px}.x-rbtn button{background-color:initial;background-position:50%;background-repeat:no-repeat;border:0;cursor:pointer;font-size:1px;height:16px;line-height:1px;margin:0;-moz-outline:0 none;outline:0 none;padding:0;width:24px}.x-rbtn{table-layout:fixed}.x-rbtn td{background-image:url(../images/restyle/icons/rbtn.gif);background-repeat:no-repeat;border:0;height:21px;padding:0;vertical-align:middle;width:24px}.x-rbtn td.x-rbtn-first{background-position:0 0}.x-rbtn td.x-rbtn-item{background-position:0 -42px}.x-rbtn td.x-rbtn-last{background-position:right -21px}.x-rbtn td.x-rbtn-first-active{background-position:0 -63px}.x-rbtn td.x-rbtn-item-active{background-position:0 -105px}.x-rbtn td.x-rbtn-last-active{background-position:right -84px}.ux-up-item{background-color:#f0f0f0;background-image:url(../../../assets/modext/util/filetree/img/white_bg.png);background-repeat:no-repeat;cursor:default;height:17px;line-height:17px;margin-bottom:1px;position:relative}.ux-up-icon-file{float:left;height:16px;margin-right:4px;vertical-align:-3px;width:16px}.ux-up-indicator{background-color:#ff0;filter:alpha(opacity=40);height:17px;opacity:.4;position:absolute;width:40px}.ux-up-icon-state{cursor:pointer;float:right;margin-right:2px;width:16px;z-index:-1}.ux-up-icon-queued{background-image:url(../../../assets/modext/util/filetree/img/silk/icons/page_white_get.png)}.ux-up-icon-uploading{background-image:url(../../../../ext2/resources/images/default/grid/wait.gif)}.ux-up-icon-done{background-image:url(../../../assets/modext/util/filetree/img/silk/icons/accept.png)}.ux-up-icon-failed{background-image:url(../../../assets/modext/util/filetree/img/silk/icons/error.png)}.ux-up-icon-stopped{background-image:url(../../../assets/modext/util/filetree/img/silk/icons/stop.png)}.ux-up-text{float:left}.ux-ftm-nodename{color:#515151;cursor:default!important;font-weight:700}.ux-icon-combo-icon{background-position:0 50%;background-repeat:no-repeat;height:14px;width:18px}.ux-icon-combo-input{padding-left:25px}.x-form-field-wrap .ux-icon-combo-icon{left:5px;top:3px}.ux-icon-combo-item{background-position:3px 50%!important;background-repeat:no-repeat!important;padding-left:24px!important}.modx-status-msg{align-items:center;background:#6cb24a;border-radius:3px;bottom:20px;box-sizing:border-box;color:#fff;-moz-column-gap:12px;column-gap:12px;display:flex;max-width:360px;padding:15px;position:fixed;right:15px;width:25%;z-index:20000}@media screen and (max-width:960px){.modx-status-msg{max-width:100%}}.modx-status-msg:before{background:#fff;border-radius:50%;color:#6cb24a;content:"\f00c";font-size:16px;height:38px;line-height:38px;text-align:center;width:38px}.modx-status-msg h3,.modx-status-msg span{font-size:14px}.modx-status-msg h3{color:#fff;margin:0}.modx-status-msg .has-position-center-center{bottom:auto;left:0;margin-left:auto;margin-right:auto;right:0;top:50%;transform:translateY(-50%)}.modx-status-msg .has-position-center-top{bottom:auto;left:0;margin-left:auto;margin-right:auto;right:0;top:15px}.modx-status-msg .has-position-right-top{bottom:auto;left:auto;right:15px;top:15px}@media screen and (max-width:960px){.modx-status-msg,.modx-status-msg .has-position-center-center,.modx-status-msg .has-position-center-top,.modx-status-msg .has-position-right-top{border-radius:0;bottom:0;left:0;right:0;top:auto;width:100%}}iframe[classname=x-hidden]{visibility:hidden}html[dir=rtl] .x-hide-offsets,html[dir=rtl] .x-hiden{left:unset;right:-9999px}.ext-ux-uploaddialog-addbtn{background:url(../images/restyle/fileup/file-add.gif) no-repeat 0!important}.ext-ux-uploaddialog-removebtn{background:url(../images/restyle/fileup/file-remove.gif) no-repeat 0!important}.ext-ux-uploaddialog-resetbtn{background:url(../images/restyle/fileup/reset.gif) no-repeat 0!important}.ext-ux-uploaddialog-uploadstartbtn{background:url(../images/restyle/fileup/upload-start.gif) no-repeat 0!important}.ext-ux-uploaddialog-uploadstopbtn{background:url(../images/restyle/fileup/upload-stop.gif) no-repeat 0!important}.ext-ux-uploaddialog-indicator-stoped{background:url(../images/restyle/fileup/done.gif) no-repeat 50%;height:16px;width:16px}.ext-ux-uploaddialog-indicator-processing{background:url(../images/restyle/fileup/loading.gif) no-repeat 50%;height:16px;width:16px}.ext-ux-uploaddialog-state{background-position:50%;background-repeat:no-repeat;text-align:center}.ext-ux-uploaddialog-state-0{background-image:url(../images/restyle/fileup/uncheck.gif)}.ext-ux-uploaddialog-state-1{background-image:url(../images/restyle/fileup/check.gif)}.ext-ux-uploaddialog-state-2{background-image:url(../images/restyle/fileup/failed.gif)}.ext-ux-uploaddialog-state-3{background-image:url(../images/restyle/fileup/file-uploading.gif)}.tq-treegrid .tq-treegrid-col{border:none}.tq-treegrid .tq-treegrid-icons{float:left}.tq-treegrid .x-tree-node-el{line-height:13px;padding:1px 3px 1px 5px}.tq-treegrid .tq-treegrid-static .x-tree-ec-icon{display:none}.tq-treegrid .tq-treegrid-static .x-tree-node-el{cursor:default}.modx-tree-load-msg{color:#000;font-size:.9em;line-height:1;padding:3px;white-space:pre-line}#modx-grid-policy-permissions .x-grid3-cell-inner,#modx-grid-policy-permissions .x-grid3-hd-inner,#modx-grid-template-permissions .x-grid3-cell-inner,#modx-grid-template-permissions .x-grid3-hd-inner{white-space:normal}.container{margin:20px 15px}.container,.x-plain-body,.x-plain-bwrap{overflow:visible}.shadowbox,.x-form-label-left{border-radius:3px}.shadowbox .x-form-label-left,.x-form-label-left .x-form-label-left,.x-tab-panel-bwrap .shadowbox,.x-tab-panel-bwrap .x-form-label-left,.x-window .shadowbox,.x-window .x-form-label-left{border-radius:0;box-shadow:none}.panel-desc{border-bottom:1px solid #f0f0f0;border-radius:0;color:#53595f;line-height:1.5;padding:15px!important}.x-window .panel-desc{margin-bottom:15px;margin-top:0}.panel-desc .x-panel-bwrap{background-color:initial!important}.with-title .panel-desc{margin:0}.panel-desc p{padding:0}.main-wrapper{background-color:#fff;padding:15px}.with-title .main-wrapper{padding:0 15px 10px}.left-col{padding-right:15px}.right-col{padding-left:15px}.modx-page-header{color:#53595f;font:normal 20px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;margin:0;order:1;padding:0 15px}@media screen and (max-width:960px){.modx-page-header{font-size:2em;text-align:center;width:100%}}.modx-header-breadcrumbs .breadcrumbs{align-items:baseline;display:flex;flex-wrap:wrap}.modx-header-breadcrumbs .breadcrumbs h2{color:#53595f;font:normal 20px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;margin:0!important;order:1;padding-left:0}@media screen and (max-width:960px){.modx-header-breadcrumbs .breadcrumbs h2{font-size:2em;text-align:center;width:100%}}.modx-header-breadcrumbs ul{align-items:center;display:flex;flex-wrap:wrap;order:0}.modx-header-breadcrumbs ul li{color:#53595f}.modx-header-breadcrumbs ul li,.modx-header-breadcrumbs ul li a{font:normal 18px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.modx-header-breadcrumbs ul li a{text-decoration:none}.modx-header-breadcrumbs ul li a.menu_hidden{font-style:italic}.modx-header-breadcrumbs ul li a.menu_hidden:hover{color:#162a42}.modx-header-breadcrumbs ul li a.not_published{color:#9c9c9c!important}.modx-header-breadcrumbs ul li a.not_published:hover{color:#162a42}.modx-header-breadcrumbs ul li a.deleted{color:#af5a62bf!important;text-decoration:line-through}.modx-header-breadcrumbs ul li a.deleted:hover{color:#162a42}.modx-header-breadcrumbs ul li:after{color:#999;content:"\f054";font-size:12px;padding:0 10px}#modx-abtn-delete{color:#cf1124}#modx-abtn-undelete{color:#6cb24a}#modx-abtn-purge{background-color:#cf1124;color:#fff}#modx-abtn-purge:hover{background-color:#a00d1c}#modx-abtn-help{color:#234368}#modx-resource-tabs .x-tab-panel-bwrap{box-shadow:none}#modx-resource-tabs .x-tab-panel-body,#modx-resource-tabs .x-tab-panel-bwrap{overflow:visible!important}#modx-resource-settings{background:#f1f1f1}#modx-resource-settings #modx-resource-main-left{background:#fff;border-bottom-left-radius:3px;border-bottom-right-radius:3px;border-top-right-radius:3px;padding:15px;position:relative}#modx-resource-settings .x-panel-collapsed{min-height:18px}#modx-resource-settings #modx-resource-main-right .modx-resource-panel{background:#fff;border-radius:3px;padding:15px}#modx-resource-settings #modx-resource-main-right .modx-resource-panel:not(:last-child){margin-bottom:15px}#modx-resource-settings .main-wrapper{background:#0000;padding:0}#modx-resource-settings .x-datetime-wrap table{width:100%}#modx-resource-settings .x-datetime-wrap table td{max-width:50%!important;width:50%!important}#modx-resource-settings .x-datetime-wrap table td input{width:calc(100% - 30px)}#modx-resource-settings .x-datetime-wrap table td:first-child{padding-right:5px!important}#modx-resource-settings .x-datetime-wrap table td:last-child{padding-left:5px!important}#modx-resource-settings .x-datetime-wrap table .x-form-field-trigger-wrap{width:100%!important}.tvs-wrapper{padding:0}#modx-resource-tvs-div{border-top-width:0;visibility:hidden}.modx-permissions-list{color:#777;font-size:12px}.modx-permissions-list-textarea{background-color:initial!important;border:0!important}.info-list.hide-list{display:none}.info-list .header{color:#626262;font:normal 12px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-weight:600}.info-list .header:before{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:auto;color:#517196;content:"\f09c";display:inline-block;font-family:Font Awesome\ 5 Free,Font Awesome\ 5 Brands;font-style:normal;font-variant:normal;font-weight:900;margin:0 .25rem}.info-list .header span{font-weight:400}.info-list ul{border:1px dashed #e4e4e4;border-radius:3px;margin-top:.5rem;padding:.5rem}.info-list ul li{color:#6b6b6b;font:normal 12px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;line-height:1;padding:.15rem 0;word-break:break-word}@media screen and (min-width:641px){.info-list ul{-moz-columns:2;column-count:2;-moz-column-gap:2rem;column-gap:2rem}}.x-window .info-list{margin-top:1rem}.x-grid3 .info-list ul{background-color:#fcfbfb;padding-left:1rem;position:relative}.x-grid3-row-alt .x-grid3 .info-list ul{background-color:#f9faff}.x-grid3 .info-list ul:before{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:auto;background-color:#fff;border-radius:100%;box-shadow:-1px 1px 3px #888;color:#517196;content:"\f09c";display:inline-block;font-family:Font Awesome\ 5 Free,Font Awesome\ 5 Brands;font-size:11px;font-style:normal;font-variant:normal;font-weight:900;height:14px;left:-7px;padding-top:2px;position:absolute;text-align:center;top:-7px;width:14px}.x-grid3 .info-list ul li{font-style:italic}@media screen and (min-width:769px){.x-grid3 .info-list ul{-moz-columns:3;column-count:3}}@media screen and (min-width:1141px){.x-grid3 .info-list ul{-moz-columns:4;column-count:4}}@media screen and (min-width:1401px){.x-grid3 .info-list ul{-moz-columns:5;column-count:5}}.x-selectable,.x-selectable *{-webkit-user-select:text!important;-moz-user-select:text!important;-ms-user-select:text!important;user-select:text!important}.x-selectable.simulated-link *{color:#234368;-webkit-text-decoration-color:#749fd0;text-decoration-color:#749fd0;-webkit-text-decoration-style:dotted;text-decoration-style:dotted}.x-selectable.simulated-link :hover{border-bottom-color:#336299;color:#000}#ux-lightbox{left:0;line-height:0;position:absolute;text-align:center;width:100%;z-index:15000}#ux-lightbox img{height:auto;width:auto}#ux-lightbox a img{border:none}#ux-lightbox-outerImageContainer{background-color:#fff;height:250px;margin:0 auto;position:relative;width:250px}#ux-lightbox-imageContainer{padding:10px}#ux-lightbox-loading{background:url(../images/style/loading.gif) no-repeat scroll center 15% #0000;height:25%;left:0;line-height:0;position:absolute;text-align:center;top:40%;width:100%}#ux-lightbox-hoverNav{height:100%;left:0;position:absolute;top:0;width:100%;z-index:10}#ux-lightbox-hoverNav a{outline:medium none}#ux-lightbox-imageContainer>#ux-lightbox-hoverNav{left:0}#ux-lightbox-navNext,#ux-lightbox-navPrev{display:block;height:100%;width:49%}#ux-lightbox-navPrev{float:left;left:0}#ux-lightbox-navPrev:hover,#ux-lightbox-navPrev:visited:hover{background:#0000 url(images/lb-prev.png) no-repeat scroll left 33%}#ux-lightbox-navNext{float:right;right:0}#ux-lightbox-navNext:hover,#ux-lightbox-navNext:visited:hover{background:#0000 url(images/lb-next.png) no-repeat scroll right 33%}#ux-lightbox-outerDataContainer{margin:0 auto;width:100%}#ux-lightbox-dataContainer{background-color:#fff;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:10px;overflow:auto}#ux-lightbox-data{color:#666;padding:0 10px}#ux-lightbox-data #ux-lightbox-details{float:left;text-align:left;width:80%}#ux-lightbox-data #ux-lightbox-caption{font-weight:700}#ux-lightbox-data #ux-lightbox-imageNumber{clear:left;display:block;padding-bottom:1em}#ux-lightbox-data #ux-lightbox-navClose{background:#0000 url(../images/style/close.png) no-repeat scroll 0 0;float:right;height:16px;outline:medium none;padding-bottom:.7em;width:16px}#ux-lightbox-overlay,#ux-lightbox-shim{background-color:#515151;border:0;height:500px;left:0;margin:0;padding:0;position:absolute;top:0;width:100%;z-index:14999}#ux-lightbox-shim{background-color:initial;z-index:89}.x-panel-body-noheader .x-grid3-row{position:relative}.x-grid3-col-main{padding:10px 5px 35px}.x-grid3-cell-inner .x-grid3-col-main h3{color:#555;font:normal 13px/1.4 -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:20px;line-height:1;margin:0 0 5px}.package-installed{color:#515151;filter:alpha(opacity=50);opacity:.5}#modx-grid-package .green{text-align:center}#modx-grid-package .green a{color:#cf1124!important}#modx-grid-package .red{color:#6cb24a!important;text-align:center}.grid-with-buttons .x-grid3-row-expanded .x-grid3-row-body{margin:-45px 2px 0 -20px;padding:18px 25px 40px}.x-grid3-row-expanded .x-grid3-row-body .manager-user-message{border-top:1px dashed #868b8f80;display:flex;flex-direction:column-reverse;gap:1rem;padding:.5rem .25rem 0}.x-grid3-row-expanded .x-grid3-row-body .manager-user-message .meta{-moz-column-gap:.5rem;column-gap:.5rem;display:flex;flex-direction:row;font-style:italic;line-height:1.4;font:normal 11px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;justify-content:space-between;row-gap:.25rem}.x-grid3-row-expanded .x-grid3-row-body .manager-user-message .meta span{display:block}.x-grid3-row-expanded .x-grid3-row-body .manager-user-message .body{flex-grow:1}.x-grid3-row-expanded .x-grid3-row-body .manager-user-message .body p{font:normal 12px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}@media screen and (min-width:641px){.x-grid3-row-expanded .x-grid3-row-body .manager-user-message{flex-direction:row-reverse}.x-grid3-row-expanded .x-grid3-row-body .manager-user-message .meta{flex-direction:column;justify-content:normal}.x-grid3-row-expanded .x-grid3-row-body .manager-user-message .meta span{display:inline}}.home-panel ol{border-top:1px solid #cacaca}.home-panel ol li{border-bottom:1px solid #e0e0e0}.home-panel ol li:first-child{border-top-color:0 none}.home-panel ol li:last-child{border-bottom:0}.home-panel ol li button{background-color:initial;border:0;color:#53595f;cursor:pointer;display:block;font-size:15px;font-weight:700;padding:12px 20px 12px 6px;position:relative;text-decoration:none}.home-panel ol li:hover button{color:#234368}.home-panel ol li:hover button:before{content:"\f002";filter:alpha(opacity=60);font-size:14px;margin-top:-7px;opacity:.6;position:absolute;right:0;text-align:center;top:50%;transition:opacity .25s;width:20px}.home-panel ol li .highlighted{color:#909090;float:right;font-size:10px;padding:13px 10px 0}.home-panel ol li button .ct{color:#aaa;margin-right:10px}.home-panel .one_half{overflow:hidden}.home-panel .desc-wrapper{margin-top:38px}.home-panel .text-wrapper{font-style:normal;max-height:none}.home-panel .provider_name{background-color:#9bb3bf;line-height:1.8}.home-panel .pnl_instructions{margin:20px 0}.home-panel .stats{clear:both;display:inline-block;margin-top:15px}.home-panel .stats p{color:#777;font-size:12px;font-style:italic;line-height:1.5}.pbr-provider-box{float:left;margin-top:10px;width:250px}.pbr-provider-home,.pbr-repository-view,.pbr-tag-view{padding:10px}.pbr-details-right{float:right!important;text-align:right!important}.pbr-thumb-downloaded{filter:alpha(opacity=50);opacity:.5}.one_half{float:left;margin-right:3%;position:relative;width:48%}.last{clear:right;margin-right:0!important}.package-readme{padding:8px 11px 0}#modx-package-browser-home{margin-top:5px;min-height:560px}.empty-text-wrapper{color:#888;font-weight:700;line-height:1.4;padding:12px}.aside-details{background-color:initial;border:1px solid #e4e4e4;border-radius:3px;margin-right:0}.aside-details .selected h5{color:#53595f;font-size:14px;margin:10px 0}.aside-details .selected img{border:1px solid #e4e4e4;border-radius:3px;height:80px;width:90px}.aside-details .item{margin-bottom:25px}.aside-details .item li,.aside-details .item p{color:#888;line-height:1.4}.aside-details .item a{color:#53595f;font-style:italic}.aside-details h4{color:#53595f;font-size:14px;margin:10px 0;text-transform:uppercase}.aside-details .aside-details h4{font-size:12px;margin-top:0}.aside-details .selected{border-bottom:1px solid #e4e4e4;color:#000;padding:15px;text-align:center}.aside-details .description,.aside-details .instructions{background-color:#fbfbfb}.aside-details .description,.aside-details .infos,.aside-details .instructions{color:#53595f;font-size:12px;line-height:1.2;padding:15px}.aside-details .infos ul li{font-size:12px}.aside-details .infos ul li .infoname{color:#999;font-weight:700;width:50%}.aside-details .infos ul li .infovalue{word-wrap:break-word;max-width:50%;padding:0 8px}.aside-details .infos ul li span{display:inline-block;padding:0}.thumb-wrapper{background-color:#f5f5f5;border:1px solid #ccc;border-radius:3px;cursor:pointer;float:left;margin:0 15px 15px 0;overflow:hidden;padding:0 0 12px;position:relative;width:250px}.thumb-wrapper,.thumb-wrapper *{box-sizing:border-box}.thumb-wrapper .thumb{background-color:#fff;border-bottom:1px solid #ccc;height:170px;margin:0 auto;position:relative;text-align:center;width:100%}.thumb-wrapper .thumb img{max-height:100%;max-width:100%}.thumb-wrapper .thumb .no-preview{color:#888;display:inline-block;font-size:9px;font-weight:700;padding:31px 15px;text-align:center;text-transform:uppercase}.thumb-wrapper span.downloaded,.thumb-wrapper span.featured{background-color:#6cb24a;color:#fff;font-weight:700;padding:5px 0;position:absolute;text-align:center;text-shadow:none;top:68px;width:100%}.thumb-wrapper span.featured{background-color:#234368;bottom:0;color:#fff;top:auto}.thumb-wrapper span{display:block;margin:0;overflow:hidden;text-align:left;text-overflow:ellipsis;text-shadow:0 1px 0 #fff;white-space:nowrap}.thumb-wrapper .name{color:#53595f;float:left;font-size:12px;font-weight:700;padding:12px 8px 12px 12px;width:55%}.thumb-wrapper .downloads{color:#999;float:right;font-size:9px;padding:8px 12px 8px 8px;text-align:right;text-transform:uppercase;width:45%}.thumb-wrapper .thumb-description{clear:both;font-size:12px;height:50px;overflow:hidden;padding:0 12px}.thumb-wrapper .thumb-footer{color:#999;font-size:9px;padding:8px 12px 0;text-align:center;text-transform:uppercase}.thumb-wrapper.selected{background-color:#fff;border-color:#234368;padding:0 0 12px}.thumb-wrapper.selected img{border:0}.pbr-thumb{background:#dfdfdf;padding:3px}.pbr-thumb,.pbr-thumb img{height:80px;width:100px}.x-grid3-hd-info-col,.x-grid3-hd-meta-col,.x-grid3-hd-text-col{text-align:center}.x-grid3-col-text-col{font-size:11px;text-align:center}.x-grid3-col-info-col,.x-grid3-col-meta-col{font-size:11px;font-weight:700;text-align:center}.x-grid3-col-meta-col{color:#53595f}.x-grid3-col-info-col{color:#6cb24a}.not-installed .x-grid3-col-info-col{color:#cf1124}.inline-button{-webkit-box-align:center;display:inline;margin:0 auto;padding:8px;text-align:center}.meta-wrapper{word-wrap:break-word;color:grey;max-height:400px;overflow:auto;padding:15px}.meta-wrapper ul{list-style:disc inside;padding-left:15px}.meta-wrapper h1{font-size:1.2em}.meta-wrapper h2{font-size:1.15em}.meta-wrapper h3{font-size:1.1em}.meta-wrapper h4{font-size:1.05em}.meta-wrapper h5{font-size:1em}.meta-wrapper h6{font-size:.95em}.window-no-padding .x-panel-mc,.window-no-padding .x-panel-ml,.window-no-padding .x-panel-mr{padding:0!important}.window-no-padding .x-tab-panel-noborder{margin:0!important}.upload-error{color:#cf1124}.upload-success{color:#6cb24a}.upload-status-text{white-space:normal}.upload-thumb{float:right}.auto-width{width:auto!important}.auto-height{height:auto!important}.x-datetime-inline-editor .x-datetime-wrap{margin-top:0!important} /*# sourceMappingURL=index-min.css.map */ \ No newline at end of file diff --git a/manager/templates/default/css/index.css b/manager/templates/default/css/index.css index e2909141768..652da186a46 100644 --- a/manager/templates/default/css/index.css +++ b/manager/templates/default/css/index.css @@ -21161,6 +21161,12 @@ input::-moz-focus-inner { .desc-under .copy-this:hover:active::after { color: #515151; } +.desc-under .copy-this:active { + color: #515151; +} +.desc-under .copy-this:active::after { + color: #515151; +} .desc-under .feedback { margin-left: 1.4rem; color: #1b5ca8; @@ -22329,15 +22335,15 @@ html[dir=rtl] .display-switch .x-fieldset legend [type=checkbox] { background-color: #FFF; } -/* fix combo on grid editor bug */ +.x-grid-editor { + z-index: 9002 !important; +} .x-grid-editor .x-form-field-wrap { background: #f6f2f7 url("../images/modx-theme/form/combo-bck.png") repeat-x scroll 0 100%; } - .x-grid-editor .x-form-field-wrap input { background-color: transparent !important; } - .x-grid-editor .x-form-field-wrap img { background-color: #FFF; background-image: url("../images/modx-theme/form/trigger.png"); @@ -27082,7 +27088,7 @@ body a:hover { color: #162a42; } -/* TODO: conver font heirarchy into a vertical rhythm formula */ +/* TODO: convert font heirarchy into a vertical rhythm formula */ h2, h3 { color: #515151; @@ -27514,6 +27520,11 @@ textarea.x-form-field { } /* grids */ +.modx-protected-row .x-grid3-cell-inner { + font-style: italic; + color: #234368; +} + .x-small-editor .x-form-field { font-size: 12px !important; } @@ -27526,14 +27537,21 @@ textarea.x-form-field { color: #999 !important; } -a.x-grid-link { +.x-grid-link { color: #234368; - text-decoration: underline; + text-decoration-style: dotted; + text-decoration-color: #749fd0; } - -a.x-grid-link:hover, -a.x-grid-link:focus { - text-decoration: none; +.x-grid-link:hover { + color: black; + border-bottom-color: #336299; +} +.x-grid-link.simulated-link { + cursor: pointer; +} +.grid-row-inactive .x-grid-link { + color: #999 !important; + text-decoration-color: #999 !important; } .x-editable-column { @@ -27865,6 +27883,31 @@ a.x-grid-link:focus { } /* rowactions */ +.x-grid3-row.disable-selection .x-grid3-row-checker, .x-grid3-row.disable-selection.x-grid3-row-selected .x-grid3-row-checker { + position: relative; +} +.x-grid3-row.disable-selection .x-grid3-row-checker::before, .x-grid3-row.disable-selection .x-grid3-row-checker::after, .x-grid3-row.disable-selection.x-grid3-row-selected .x-grid3-row-checker::before, .x-grid3-row.disable-selection.x-grid3-row-selected .x-grid3-row-checker::after { + color: #919191; +} +.x-grid3-row.disable-selection .x-grid3-row-checker::before, .x-grid3-row.disable-selection.x-grid3-row-selected .x-grid3-row-checker::before { + content: "\f0c8"; +} +.x-grid3-row.disable-selection .x-grid3-row-checker::after, .x-grid3-row.disable-selection.x-grid3-row-selected .x-grid3-row-checker::after { + content: "\f715"; + font-size: 6px; + position: absolute; + left: 50%; + top: 50%; + margin-left: 2px; + margin-top: 1px; + transform: translate(-50%, -50%) rotate(98deg); + font-weight: 600; + font-family: "Font Awesome 5 Free"; +} +.x-grid3-row.disable-selection .x-grid3-row-checker:hover, .x-grid3-row.disable-selection.x-grid3-row-selected .x-grid3-row-checker:hover { + cursor: default; +} + .ux-row-action-cell .x-grid3-cell-inner { padding: 1px 0 0 0; } @@ -28770,6 +28813,16 @@ html[dir=rtl] .x-hide-offsets { user-select: text !important; } +.x-selectable.simulated-link * { + color: #234368; + text-decoration-style: dotted; + text-decoration-color: #749fd0; +} +.x-selectable.simulated-link *:hover { + color: black; + border-bottom-color: #336299; +} + /* Lightbox */ #ux-lightbox { left: 0;