From c43680b2ef28885a4511f8dce0fa2c3da415f9bf Mon Sep 17 00:00:00 2001 From: gergo85 Date: Fri, 19 Dec 2014 10:28:27 +0100 Subject: [PATCH 01/26] Improve multilanguage support and cleanup --- modules/backend/ServiceProvider.php | 6 +- modules/backend/lang/en/lang.php | 143 +++++++++++------------- modules/backend/models/user/fields.yaml | 4 +- modules/cms/ServiceProvider.php | 42 +++++-- modules/cms/lang/en/lang.php | 63 ++++++----- modules/system/ServiceProvider.php | 6 +- modules/system/lang/en/lang.php | 16 +-- 7 files changed, 146 insertions(+), 134 deletions(-) diff --git a/modules/backend/ServiceProvider.php b/modules/backend/ServiceProvider.php index 950cea44e..8bef4862a 100644 --- a/modules/backend/ServiceProvider.php +++ b/modules/backend/ServiceProvider.php @@ -138,11 +138,11 @@ class ServiceProvider extends ModuleServiceProvider $manager->registerPermissions('October.Backend', [ 'backend.access_dashboard' => [ 'label' => 'system::lang.permissions.view_the_dashboard', - 'tab' => 'System' + 'tab' => 'system::lang.permissions.name' ], - 'backend.manage_users' => [ + 'backend.manage_users' => [ 'label' => 'system::lang.permissions.manage_other_administrators', - 'tab' => 'System' + 'tab' => 'system::lang.permissions.name' ], ]); }); diff --git a/modules/backend/lang/en/lang.php b/modules/backend/lang/en/lang.php index d7b6348e0..a62abc7d1 100644 --- a/modules/backend/lang/en/lang.php +++ b/modules/backend/lang/en/lang.php @@ -2,26 +2,26 @@ return [ 'auth' => [ - 'title' => 'Administration Area', + 'title' => 'Administration Area' ], 'field' => [ 'invalid_type' => 'Invalid field type used :type.', - 'options_method_not_exists' => 'The model class :model must define a method :method() returning options for the ":field" form field.', + 'options_method_not_exists' => "The model class :model must define a method :method() returning options for the ':field' form field." ], 'widget' => [ 'not_registered' => "A widget class name ':name' has not been registered", - 'not_bound' => "A widget with class name ':name' has not been bound to the controller", + 'not_bound' => "A widget with class name ':name' has not been bound to the controller" ], 'page' => [ - 'untitled' => "Untitled", + 'untitled' => 'Untitled', 'access_denied' => [ - 'label' => "Access denied", + 'label' => 'Access denied', 'help' => "You don't have the required permissions to view this page.", - 'cms_link' => "Return to the back-end", - ], + 'cms_link' => 'Return to the back-end' + ] ], 'partial' => [ - 'not_found' => "The partial ':name' is not found.", + 'not_found' => "The partial ':name' is not found." ], 'account' => [ 'sign_out' => 'Sign out', @@ -30,21 +30,21 @@ return [ 'restore' => 'Restore', 'login_placeholder' => 'login', 'password_placeholder' => 'password', - 'forgot_password' => "Forgot your password?", - 'enter_email' => "Enter your email", - 'enter_login' => "Enter your login", - 'email_placeholder' => "email", - 'enter_new_password' => "Enter a new password", - 'password_reset' => "Password Reset", - 'restore_success' => "An email has been sent to your email address with password restore instructions.", + 'forgot_password' => 'Forgot your password?', + 'enter_email' => 'Enter your email', + 'enter_login' => 'Enter your login', + 'email_placeholder' => 'email', + 'enter_new_password' => 'Enter a new password', + 'password_reset' => 'Password Reset', + 'restore_success' => 'An email has been sent to your email address with password restore instructions.', 'restore_error' => "A user could not be found with a login value of ':login'", - 'reset_success' => "Your password has been successfully reset. You may now sign in.", - 'reset_error' => "Invalid password reset data supplied. Please try again!", - 'reset_fail' => "Unable to reset your password!", + 'reset_success' => 'Your password has been successfully reset. You may now sign in.', + 'reset_error' => 'Invalid password reset data supplied. Please try again!', + 'reset_fail' => 'Unable to reset your password!', 'apply' => 'Apply', 'cancel' => 'Cancel', 'delete' => 'Delete', - 'ok' => 'OK', + 'ok' => 'OK' ], 'dashboard' => [ 'menu_label' => 'Dashboard', @@ -66,7 +66,7 @@ return [ 'widget_title_default' => 'System status', 'online' => 'online', 'maintenance' => 'in maintenance', - 'update_available' => '{0} updates available!|{1} update available!|[2,Inf] updates available!', + 'update_available' => '{0} updates available!|{1} update available!|[2,Inf] updates available!' ] ], 'user' => [ @@ -75,18 +75,19 @@ return [ 'menu_description' => 'Manage back-end administrator users, groups and permissions.', 'list_title' => 'Manage Administrators', 'new' => 'New Administrator', - 'login' => "Login", - 'first_name' => "First Name", - 'last_name' => "Last Name", - 'full_name' => "Full Name", - 'email' => "Email", - 'groups' => "Groups", - 'groups_comment' => "Specify which groups this person belongs to.", - 'avatar' => "Avatar", - 'password' => "Password", - 'password_confirmation' => "Confirm Password", - 'superuser' => "Super User", - 'superuser_comment' => "Check this box to allow this person to access all areas.", + 'login' => 'Login', + 'first_name' => 'First Name', + 'last_name' => 'Last Name', + 'full_name' => 'Full Name', + 'email' => 'Email', + 'groups' => 'Groups', + 'groups_comment' => 'Specify which groups this person belongs to.', + 'avatar' => 'Avatar', + 'password' => 'Password', + 'password_confirmation' => 'Confirm Password', + 'permissions' => 'Permissions', + 'superuser' => 'Super User', + 'superuser_comment' => 'Check this box to allow this person to access all areas.', 'send_invite' => 'Send invitation by email', 'send_invite_comment' => 'Use this checkbox to send an invitation to the user by email', 'delete_confirm' => 'Do you really want to delete this administrator?', @@ -97,15 +98,11 @@ return [ 'group' => [ 'name' => 'Group', 'name_field' => 'Name', - 'description_field' => 'Description', - 'is_new_user_default_field' => 'Add new administrators to this group by default', - 'code_field' => 'Code', - 'code_comment' => 'Enter a unique code if you want to access it with the API.', 'menu_label' => 'Groups', 'list_title' => 'Manage Groups', 'new' => 'New Administrator Group', 'delete_confirm' => 'Do you really want to delete this administrator group?', - 'return' => 'Return to the group list', + 'return' => 'Return to the group list' ], 'preferences' => [ 'not_authenticated' => 'There is no an authenticated user to load or save preferences for.' @@ -137,17 +134,17 @@ return [ 'description_label' => 'Description' ], 'form' => [ - 'create_title' => "New :name", - 'update_title' => "Edit :name", - 'preview_title' => "Preview :name", + 'create_title' => 'New :name', + 'update_title' => 'Edit :name', + 'preview_title' => 'Preview :name', 'create_success' => 'The :name has been created successfully', 'update_success' => 'The :name has been updated successfully', 'delete_success' => 'The :name has been deleted successfully', - 'missing_id' => "Form record ID has not been specified.", + 'missing_id' => 'Form record ID has not been specified.', 'missing_model' => 'Form behavior used in :class does not have a model defined.', 'missing_definition' => "Form behavior does not contain a field for ':field'.", 'not_found' => 'Form record with an ID of :id could not be found.', - 'action_confirm' => "Are you sure?", + 'action_confirm' => 'Are you sure?', 'create' => 'Create', 'create_and_close' => 'Create and close', 'creating' => 'Creating...', @@ -159,9 +156,6 @@ return [ 'delete' => 'Delete', 'deleting' => 'Deleting...', 'deleting_name' => 'Deleting :name...', - 'reset_default' => 'Reset to default', - 'resetting' => 'Resetting', - 'resetting_name' => 'Resetting :name', 'undefined_tab' => 'Misc', 'field_off' => 'Off', 'field_on' => 'On', @@ -182,41 +176,38 @@ return [ 'select_placeholder' => 'please select', 'insert_row' => 'Insert Row', 'delete_row' => 'Delete Row', - 'concurrency_file_changed_title' => "File was changed", - 'concurrency_file_changed_description' => "The file you're editing has been changed on disk by another user. You can either reload the file and lose your changes or override the file on the disk.", + 'concurrency_file_changed_title' => 'File was changed', + 'concurrency_file_changed_description' => "The file you're editing has been changed on disk by another user. You can either reload the file and lose your changes or override the file on the disk." ], 'relation' => [ 'missing_definition' => "Relation behavior does not contain a definition for ':field'.", - 'missing_model' => "Relation behavior used in :class does not have a model defined.", - 'invalid_action_single' => "This action cannot be performed on a singular relationship.", - 'invalid_action_multi' => "This action cannot be performed on a multiple relationship.", - 'help' => "Click on an item to add", - 'related_data' => "Related :name data", - 'add' => "Add", - 'add_selected' => "Add selected", - 'add_a_new' => "Add a new :name", - 'cancel' => "Cancel", - 'close' => "Close", - 'add_name' => "Add :name", - 'create' => "Create", - 'create_name' => "Create :name", - 'update' => "Update", - 'update_name' => "Update :name", - 'preview' => "Preview", - 'preview_name' => "Preview :name", - 'remove' => "Remove", - 'remove_name' => "Remove :name", - 'delete' => "Delete", - 'delete_name' => "Delete :name", - 'delete_confirm' => "Are you sure?", + 'missing_model' => 'Relation behavior used in :class does not have a model defined.', + 'invalid_action_single' => 'This action cannot be performed on a singular relationship.', + 'invalid_action_multi' => 'This action cannot be performed on a multiple relationship.', + 'help' => 'Click on an item to add', + 'related_data' => 'Related :name data', + 'add' => 'Add', + 'add_selected' => 'Add selected', + 'add_a_new' => 'Add a new :name', + 'cancel' => 'Cancel', + 'add_name' => 'Add :name', + 'create' => 'Create', + 'create_name' => 'Create :name', + 'update' => 'Update', + 'update_name' => 'Update :name', + 'remove' => 'Remove', + 'remove_name' => 'Remove :name', + 'delete' => 'Delete', + 'delete_name' => 'Delete :name', + 'delete_confirm' => 'Are you sure?' ], 'model' => [ - 'name' => "Model", + 'name' => 'Model', 'not_found' => "Model ':class' with an ID of :id could not be found", - 'missing_id' => "There is no ID specified for looking up the model record.", + 'missing_id' => 'There is no ID specified for looking up the model record.', 'missing_relation' => "Model ':class' does not contain a definition for ':relation'.", 'invalid_class' => "Model :model used in :class is not valid, it must inherit the \Model class.", - 'mass_assignment_failed' => "Mass assignment failed for Model attribute ':attribute'.", + 'mass_assignment_failed' => "Mass assignment failed for Model attribute ':attribute'." ], 'warnings' => [ 'tips' => 'System configuration tips', @@ -235,14 +226,14 @@ return [ 'highlight_active_line' => 'Highlight active line', 'show_invisibles' => 'Show invisible characters', 'show_gutter' => 'Show gutter', - 'theme' => 'Color scheme', + 'theme' => 'Color scheme' ], 'tooltips' => [ 'preview_website' => 'Preview the website' ], 'mysettings' => [ 'menu_label' => 'My Settings', - 'menu_description' => 'Settings relate to your administration account', + 'menu_description' => 'Settings relate to your administration account' ], 'myaccount' => [ 'menu_label' => 'My account', @@ -271,7 +262,7 @@ return [ 'menu_label' => 'Back-end preferences', 'menu_description' => 'Manage your account preferences such as desired language.', 'locale' => 'Language', - 'locale_comment' => 'Select your desired locale for language use.', + 'locale_comment' => 'Select your desired locale for language use.' ], 'access_log' => [ 'hint' => 'This log displays a list of successful sign in attempts by administrators. Records are kept for a total of :days days.', @@ -282,7 +273,7 @@ return [ 'ip_address' => 'IP address', 'first_name' => 'First name', 'last_name' => 'Last name', - 'email' => 'Email', + 'email' => 'Email' ], 'filter' => [ 'all' => 'all' diff --git a/modules/backend/models/user/fields.yaml b/modules/backend/models/user/fields.yaml index f5b3d3cf7..9c4ec61a0 100644 --- a/modules/backend/models/user/fields.yaml +++ b/modules/backend/models/user/fields.yaml @@ -40,14 +40,14 @@ tabs: permissions[superuser]: context: [create, update] - tab: Permissions + tab: backend::lang.user.permissions label: backend::lang.user.superuser type: checkbox comment: backend::lang.user.superuser_comment groups: context: [create, update] - tab: Permissions + tab: backend::lang.user.permissions label: backend::lang.user.groups commentAbove: backend::lang.user.groups_comment type: checkboxlist diff --git a/modules/cms/ServiceProvider.php b/modules/cms/ServiceProvider.php index 86ec3e1d2..982eec54e 100644 --- a/modules/cms/ServiceProvider.php +++ b/modules/cms/ServiceProvider.php @@ -39,7 +39,7 @@ class ServiceProvider extends ModuleServiceProvider 'label' => 'cms::lang.page.menu_label', 'icon' => 'icon-copy', 'url' => 'javascript:;', - 'attributes' => ['data-menu-item'=>'pages'], + 'attributes' => ['data-menu-item' => 'pages'], 'permissions' => ['cms.manage_pages'], 'counterLabel' => 'cms::lang.page.unsaved_label', ], @@ -47,7 +47,7 @@ class ServiceProvider extends ModuleServiceProvider 'label' => 'cms::lang.partial.menu_label', 'icon' => 'icon-tags', 'url' => 'javascript:;', - 'attributes' => ['data-menu-item'=>'partials'], + 'attributes' => ['data-menu-item' => 'partials'], 'permissions' => ['cms.manage_partials'], 'counterLabel' => 'cms::lang.partial.unsaved_label', ], @@ -55,7 +55,7 @@ class ServiceProvider extends ModuleServiceProvider 'label' => 'cms::lang.layout.menu_label', 'icon' => 'icon-th-large', 'url' => 'javascript:;', - 'attributes' => ['data-menu-item'=>'layouts'], + 'attributes' => ['data-menu-item' => 'layouts'], 'permissions' => ['cms.manage_layouts'], 'counterLabel' => 'cms::lang.layout.unsaved_label', ], @@ -63,7 +63,7 @@ class ServiceProvider extends ModuleServiceProvider 'label' => 'cms::lang.content.menu_label', 'icon' => 'icon-file-text-o', 'url' => 'javascript:;', - 'attributes' => ['data-menu-item'=>'content'], + 'attributes' => ['data-menu-item' => 'content'], 'permissions' => ['cms.manage_content'], 'counterLabel' => 'cms::lang.content.unsaved_label', ], @@ -71,7 +71,7 @@ class ServiceProvider extends ModuleServiceProvider 'label' => 'cms::lang.asset.menu_label', 'icon' => 'icon-picture-o', 'url' => 'javascript:;', - 'attributes' => ['data-menu-item'=>'assets'], + 'attributes' => ['data-menu-item' => 'assets'], 'permissions' => ['cms.manage_assets'], 'counterLabel' => 'cms::lang.asset.unsaved_label', ], @@ -79,7 +79,7 @@ class ServiceProvider extends ModuleServiceProvider 'label' => 'cms::lang.component.menu_label', 'icon' => 'icon-puzzle-piece', 'url' => 'javascript:;', - 'attributes' => ['data-menu-item'=>'components'], + 'attributes' => ['data-menu-item' => 'components'], 'permissions' => ['cms.manage_pages', 'cms.manage_layouts', 'cms.manage_partials'] ] ] @@ -93,12 +93,30 @@ class ServiceProvider extends ModuleServiceProvider */ BackendAuth::registerCallback(function ($manager) { $manager->registerPermissions('October.Cms', [ - 'cms.manage_content' => ['label' => 'cms::lang.permissions.manage_content', 'tab' => 'Cms'], - 'cms.manage_assets' => ['label' => 'cms::lang.permissions.manage_assets', 'tab' => 'Cms'], - 'cms.manage_pages' => ['label' => 'cms::lang.permissions.manage_pages', 'tab' => 'Cms'], - 'cms.manage_layouts' => ['label' => 'cms::lang.permissions.manage_layouts', 'tab' => 'Cms'], - 'cms.manage_partials' => ['label' => 'cms::lang.permissions.manage_partials', 'tab' => 'Cms'], - 'cms.manage_themes' => ['label' => 'cms::lang.permissions.manage_themes', 'tab' => 'Cms'] + 'cms.manage_content' => [ + 'label' => 'cms::lang.permissions.manage_content', + 'tab' => 'cms::lang.permissions.name' + ], + 'cms.manage_assets' => [ + 'label' => 'cms::lang.permissions.manage_assets', + 'tab' => 'cms::lang.permissions.name' + ], + 'cms.manage_pages' => [ + 'label' => 'cms::lang.permissions.manage_pages', + 'tab' => 'cms::lang.permissions.name' + ], + 'cms.manage_layouts' => [ + 'label' => 'cms::lang.permissions.manage_layouts', + 'tab' => 'cms::lang.permissions.name' + ], + 'cms.manage_partials' => [ + 'label' => 'cms::lang.permissions.manage_partials', + 'tab' => 'cms::lang.permissions.name' + ], + 'cms.manage_themes' => [ + 'label' => 'cms::lang.permissions.manage_themes', + 'tab' => 'cms::lang.permissions.name' + ] ]); }); diff --git a/modules/cms/lang/en/lang.php b/modules/cms/lang/en/lang.php index 3ead1ede9..a05af3a63 100644 --- a/modules/cms/lang/en/lang.php +++ b/modules/cms/lang/en/lang.php @@ -3,23 +3,23 @@ return [ 'cms_object' => [ 'invalid_file' => 'Invalid file name: :name. File names can contain only alphanumeric symbols, underscores, dashes and dots. Some examples of correct file names: page.htm, page, subdirectory/page', - 'invalid_property' => 'The property ":name" cannot be set', - 'file_already_exists' => 'File ":name" already exists.', - 'error_saving' => 'Error saving file ":name". Please check write permissions.', + 'invalid_property' => "The property ':name' cannot be set", + 'file_already_exists' => "File ':name' already exists.", + 'error_saving' => "Error saving file ':name'. Please check write permissions.", 'error_creating_directory' => 'Error creating directory :name. Please check write permissions.', 'invalid_file_extension'=>'Invalid file extension: :invalid. Allowed extensions are: :allowed.', - 'error_deleting' => 'Error deleting the template file ":name". Please check write permissions.', + 'error_deleting' => "Error deleting the template file ':name'. Please check write permissions.", 'delete_success' => 'Templates were successfully deleted: :count.', 'file_name_required' => 'The File Name field is required.' ], 'theme' => [ 'active' => [ - 'not_set' => "The active theme is not set.", - 'not_found' => "The active theme is not found.", + 'not_set' => 'The active theme is not set.', + 'not_found' => 'The active theme is not found.' ], 'edit' => [ - 'not_set' => "The edit theme is not set.", - 'not_found' => "The edit theme is not found.", + 'not_set' => 'The edit theme is not set.', + 'not_found' => 'The edit theme is not found.', 'not_match' => "The object you're trying to access doesn't belong to the theme being edited. Please reload the page." ], 'settings_menu' => 'Front-end theme', @@ -27,22 +27,22 @@ return [ 'find_more_themes' => 'Find more themes on OctoberCMS Theme Marketplace.', 'activate_button' => 'Activate', 'active_button' => 'Activate', - 'customize_button' => 'Customize', + 'customize_button' => 'Customize' ], 'maintenance' => [ 'settings_menu' => 'Maintenance mode', 'settings_menu_description' => 'Configure the maintenance mode page and toggle the setting.', 'is_enabled' => 'Enable maintenance mode', - 'is_enabled_comment' => 'When activated website visitors will see the page chosen below.', + 'is_enabled_comment' => 'When activated website visitors will see the page chosen below.' ], 'page' => [ 'not_found' => [ - 'label' => "Page not found", - 'help' => "The requested page cannot be found.", + 'label' => 'Page not found', + 'help' => 'The requested page cannot be found.' ], 'custom_error' => [ - 'label' => "Page error", - 'help' => "We're sorry, but something went wrong and the page cannot be displayed.", + 'label' => 'Page error', + 'help' => "We're sorry, but something went wrong and the page cannot be displayed." ], 'menu_label' => 'Pages', 'unsaved_label' => 'Unsaved page(s)', @@ -63,7 +63,7 @@ return [ 'delete_confirm_single' => 'Do you really want delete this layout?' ], 'partial' => [ - 'invalid_name' => "Invalid partial name: :name.", + 'invalid_name' => 'Invalid partial name: :name.', 'not_found' => "The partial ':name' is not found.", 'menu_label' => 'Partials', 'unsaved_label' => 'Unsaved partial(s)', @@ -82,11 +82,11 @@ return [ 'new' => 'New content file' ], 'ajax_handler' => [ - 'invalid_name' => "Invalid AJAX handler name: :name.", - 'not_found' => "AJAX handler ':name' was not found.", + 'invalid_name' => 'Invalid AJAX handler name: :name.', + 'not_found' => "AJAX handler ':name' was not found." ], 'cms' => [ - 'menu_label' => "CMS" + 'menu_label' => 'CMS' ], 'sidebar' => [ 'add' => 'Add', @@ -113,7 +113,7 @@ return [ 'exit_fullscreen' => 'Exit fullscreen mode' ], 'asset' => [ - 'menu_label' => "Assets", + 'menu_label' => 'Assets', 'unsaved_label' => 'Unsaved asset(s)', 'drop_down_add_title' => 'Add...', 'drop_down_operation_title' => 'Action...', @@ -141,7 +141,7 @@ return [ 'too_large' => 'The uploaded file is too large. The maximum allowed file size is :max_size', 'type_not_allowed' => 'Only the following file types are allowed: :allowed_types', 'file_not_valid' => 'File is not valid', - 'error_uploading_file' => 'Error uploading file ":name": :error', + 'error_uploading_file' => "Error uploading file ':name': :error", 'move_please_select' => 'please select', 'move_destination' => 'Destination directory', 'move_popup_title' => 'Move assets', @@ -155,23 +155,24 @@ return [ 'path' => 'Path' ], 'component' => [ - 'menu_label' => "Components", - 'unnamed' => "Unnamed", - 'no_description' => "No description provided", - 'alias' => "Alias", - 'alias_description' => "A unique name given to this component when using it in the page or layout code.", - 'validation_message' => "Component aliases are required and can contain only Latin symbols, digits, and underscores. The aliases should start with a Latin symbol.", - 'invalid_request' => "The template cannot be saved because of invalid component data.", + 'menu_label' => 'Components', + 'unnamed' => 'Unnamed', + 'no_description' => 'No description provided', + 'alias' => 'Alias', + 'alias_description' => 'A unique name given to this component when using it in the page or layout code.', + 'validation_message' => 'Component aliases are required and can contain only Latin symbols, digits, and underscores. The aliases should start with a Latin symbol.', + 'invalid_request' => 'The template cannot be saved because of invalid component data.', 'no_records' => 'No components found', 'not_found' => "The component ':name' is not found.", - 'method_not_found' => "The component ':name' does not contain a method ':method'.", + 'method_not_found' => "The component ':name' does not contain a method ':method'." ], 'template' => [ - 'invalid_type' => "Unknown template type.", - 'not_found' => "The requested template was not found.", - 'saved'=> "The template has been successfully saved." + 'invalid_type' => 'Unknown template type.', + 'not_found' => 'The requested template was not found.', + 'saved'=> 'The template has been successfully saved.' ], 'permissions' => [ + 'name' => 'Cms', 'manage_content' => 'Manage content', 'manage_assets' => 'Manage assets', 'manage_pages' => 'Manage pages', diff --git a/modules/system/ServiceProvider.php b/modules/system/ServiceProvider.php index cb5664378..b0c31417d 100644 --- a/modules/system/ServiceProvider.php +++ b/modules/system/ServiceProvider.php @@ -204,15 +204,15 @@ class ServiceProvider extends ModuleServiceProvider $manager->registerPermissions('October.System', [ 'system.manage_settings' => [ 'label' => 'system::lang.permissions.manage_system_settings', - 'tab' => 'System' + 'tab' => 'system::lang.permissions.name' ], 'system.manage_updates' => [ 'label' => 'system::lang.permissions.manage_software_updates', - 'tab' => 'System' + 'tab' => 'system::lang.permissions.name' ], 'system.manage_mail_templates' => [ 'label' => 'system::lang.permissions.manage_mail_templates', - 'tab' => 'System' + 'tab' => 'system::lang.permissions.name' ], ]); }); diff --git a/modules/system/lang/en/lang.php b/modules/system/lang/en/lang.php index 1193184b7..0a1ad455d 100644 --- a/modules/system/lang/en/lang.php +++ b/modules/system/lang/en/lang.php @@ -23,10 +23,10 @@ return [ 'tr' => 'Turkish', ], 'directory' => [ - 'create_fail' => "Cannot create directory: :name", + 'create_fail' => 'Cannot create directory: :name', ], 'file' => [ - 'create_fail' => "Cannot create file: :name", + 'create_fail' => 'Cannot create file: :name', ], 'combiner' => [ 'not_found' => "The combiner file ':name' is not found.", @@ -66,13 +66,13 @@ return [ 'disabled_help' => 'Plugins that are disabled are ignored by the application.', 'selected_amount' => 'Plugins selected: :amount', 'remove_confirm' => 'Are you sure?', - 'remove_success' => "Successfully removed those plugins from the system.", + 'remove_success' => 'Successfully removed those plugins from the system.', 'refresh_confirm' => 'Are you sure?', - 'refresh_success' => "Successfully refreshed those plugins in the system.", + 'refresh_success' => 'Successfully refreshed those plugins in the system.', 'disable_confirm' => 'Are you sure?', - 'disable_success' => "Successfully disabled those plugins.", - 'enable_success' => "Successfully enabled those plugins.", - 'unknown_plugin' => "Plugin has been removed from the file system.", + 'disable_success' => 'Successfully disabled those plugins.', + 'enable_success' => 'Successfully enabled those plugins.', + 'unknown_plugin' => 'Plugin has been removed from the file system.', ], 'project' => [ 'name' => 'Project', @@ -114,6 +114,7 @@ return [ 'smtp_password' => 'Password', 'smtp_port' => 'SMTP Port', 'smtp_ssl' => 'SSL connection required', + 'sendmail' => 'Sendmail', 'sendmail_path' => 'Sendmail Path', 'sendmail_path_comment' => 'Please specify the path of the sendmail program.', 'mailgun' => 'Mailgun', @@ -242,6 +243,7 @@ return [ 'status_code' => 'Status', ], 'permissions' => [ + 'name' => 'System', 'manage_system_settings' => 'Manage system settings', 'manage_software_updates' => 'Manage software updates', 'manage_mail_templates' => 'Manage mail templates', From 242bac4ce806808e1f14fb19af9a0e7b1c97c18b Mon Sep 17 00:00:00 2001 From: jtherczeg Date: Mon, 22 Dec 2014 19:06:15 +0100 Subject: [PATCH 02/26] Hungarian language files updated Hungarian translations updated for the latest build, some corrections made. --- modules/backend/lang/hu/lang.php | 7 +++++++ modules/cms/lang/hu/lang.php | 2 +- modules/system/lang/hu/lang.php | 4 ++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/modules/backend/lang/hu/lang.php b/modules/backend/lang/hu/lang.php index 4d52c3e08..df48c453e 100644 --- a/modules/backend/lang/hu/lang.php +++ b/modules/backend/lang/hu/lang.php @@ -97,6 +97,10 @@ return [ 'group' => [ 'name' => 'Csoport', 'name_field' => 'Név', + 'description_field' => 'Leírás', + 'is_new_user_default_field' => 'Az új webhelygazdák hozzáadása alapértelmezésként ehhez a csoporthoz', + 'code_field' => 'Kód', + 'code_comment' => 'Adjon meg egy egyedi kódot, ha az API-val kíván hozzáférni.', 'menu_label' => 'Csoportok', 'list_title' => 'Csoportok kezelése', 'new' => 'Új webhelygazda csoport', @@ -192,11 +196,14 @@ return [ 'add_selected' => "Kijelöltek hozzáadása", 'add_a_new' => "Új :name hozzáadása", 'cancel' => "Mégse", + 'close' => "Bezárás", 'add_name' => ":name hozzáadása", 'create' => "Létrehozás", 'create_name' => ":name létrehozása", 'update' => "Frissítés", 'update_name' => "A(z) :name frissítése", + 'preview' => "Előnézet", + 'preview_name' => "Előnézet neve", 'remove' => "Eltávolítás", 'remove_name' => "A(z) :name eltávolítása", 'delete' => "Törlés", diff --git a/modules/cms/lang/hu/lang.php b/modules/cms/lang/hu/lang.php index 762cc533f..3213d56af 100644 --- a/modules/cms/lang/hu/lang.php +++ b/modules/cms/lang/hu/lang.php @@ -33,7 +33,7 @@ return [ 'settings_menu' => 'Karbantartás mód', 'settings_menu_description' => 'A karbantartás mód lap konfigurálása, és a beűllítás ki-/bekapcsolása.', 'is_enabled' => 'A karbantartás mód engedélyezése', - 'is_enabled_comment' => 'Aktiválása esetén a webhely látogatói az alább bejelölt lapot fogják látni.', + 'is_enabled_comment' => 'Aktiválása esetén a webhely látogatói az alább kiválasztott lapot fogják látni.', ], 'page' => [ 'not_found' => [ diff --git a/modules/system/lang/hu/lang.php b/modules/system/lang/hu/lang.php index af262b382..b077fcf98 100644 --- a/modules/system/lang/hu/lang.php +++ b/modules/system/lang/hu/lang.php @@ -97,6 +97,7 @@ return [ 'search' => 'Keresés' ], 'mail' => [ + 'log_file' => 'Naplófájl', 'menu_label' => 'Levelezés konfigurálása', 'menu_description' => 'Az e-mail küldés konfigurációjának kezelése.', 'general' => 'Általános', @@ -113,7 +114,6 @@ return [ 'smtp_password' => 'Jelszó', 'smtp_port' => 'SMTP port', 'smtp_ssl' => 'SSL-kapcsolat szükséges', - 'sendmail' => 'Sendmail', 'sendmail_path' => 'Sendmail elérési útja', 'sendmail_path_comment' => 'Adja meg a Sendmail program elérési útját.', 'mailgun' => 'Mailgun', @@ -191,7 +191,7 @@ return [ ], 'none' => [ 'label' => 'Nincsenek frissítések', - 'help' => 'Nem találhatók új frissítések.', + 'help' => 'Nem található új frissítés.', ], ], 'server' => [ From 9bda36e441b8923484e68c613b6a4abb4ca2ba4b Mon Sep 17 00:00:00 2001 From: Darek Magusiak Date: Mon, 22 Dec 2014 21:02:46 -0500 Subject: [PATCH 03/26] Model field definitions and default value of '0' #845 --- modules/backend/widgets/Form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/backend/widgets/Form.php b/modules/backend/widgets/Form.php index 715bd7752..3081793bc 100644 --- a/modules/backend/widgets/Form.php +++ b/modules/backend/widgets/Form.php @@ -710,7 +710,7 @@ class Form extends WidgetBase } $fieldName = $field->fieldName; - $defaultValue = (!$this->model->exists) && !empty($field->defaults) ? $field->defaults : null; + $defaultValue = (!$this->model->exists && $field->defaults !== '') ? $field->defaults : null; /* * Array field name, eg: field[key][key2][key3] From 99d34789a49ec66430ab1456ce270fd852e00047 Mon Sep 17 00:00:00 2001 From: Nicolas Lescop Date: Tue, 23 Dec 2014 14:57:28 +0100 Subject: [PATCH 04/26] Extend query of the filter options lists --- modules/backend/behaviors/ListController.php | 17 +++++++++++++++++ modules/backend/widgets/Filter.php | 8 ++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/modules/backend/behaviors/ListController.php b/modules/backend/behaviors/ListController.php index 1cba33666..ce40e392d 100644 --- a/modules/backend/behaviors/ListController.php +++ b/modules/backend/behaviors/ListController.php @@ -216,6 +216,13 @@ class ListController extends ControllerBehavior return $widget->onRefresh(); }); + /* + * Extend the query of the list of options + */ + $filterWidget->bindEvent('filter.extendQuery', function($query, $scope) { + $this->controller->listFilterExtendQuery($query, $scope); + }); + // Apply predefined filter values $widget->addFilter([$filterWidget, 'applyAllScopesToQuery']); @@ -350,6 +357,16 @@ class ListController extends ControllerBehavior { } + /** + * Controller override: Extend the query used for populating the filter + * options before the default query is processed. + * @param October\Rain\Database\Builder $query + * @param array $scope + */ + public function listFilterExtendQuery($query, $scope) + { + } + /** * Returns a CSS class name for a list row (). * @param Model $record The populated model used for the column diff --git a/modules/backend/widgets/Filter.php b/modules/backend/widgets/Filter.php index 4f3417bdb..27e0418bc 100644 --- a/modules/backend/widgets/Filter.php +++ b/modules/backend/widgets/Filter.php @@ -208,12 +208,16 @@ class Filter extends WidgetBase protected function getOptionsFromModel($scope, $searchQuery = null) { $model = $this->scopeModels[$scope->scopeName]; + $query = $model->newQuery(); + + $this->fireEvent('filter.extendQuery', [$query, $scope]); + if (!$searchQuery) { - return $model->all(); + return $query->get(); } $searchFields = [$model->getKeyName(), $this->getScopeNameColumn($scope)]; - return $model->searchWhere($searchQuery, $searchFields)->get(); + return $query->searchWhere($searchQuery, $searchFields)->get(); } /** From 82868801489dcbeeb02e74f9e212f2b9c8014286 Mon Sep 17 00:00:00 2001 From: Scott Bedard Date: Sat, 27 Dec 2014 17:33:27 -0500 Subject: [PATCH 05/26] Valid strtotime() format when time is left empty Date-type laravel validation ("date", "before", and "after") may not be used with datetime widgets containing empty time fields because they are not in a valid strtotime() format (example: 2014-12-27 :00). This extra check ensures a valid strtotime() format by only adding the ":00" seconds value when a time value is present. --- modules/backend/formwidgets/DatePicker.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/backend/formwidgets/DatePicker.php b/modules/backend/formwidgets/DatePicker.php index 7b2d1aa44..dc9cc3ccd 100644 --- a/modules/backend/formwidgets/DatePicker.php +++ b/modules/backend/formwidgets/DatePicker.php @@ -126,8 +126,8 @@ class DatePicker extends FormWidgetBase return null; } - if ($this->mode == 'datetime') { - $value .= ' ' . post(self::TIME_PREFIX.$this->formField->getName(false)) . ':00'; + if ($this->mode == 'datetime' && $timeValue = post(self::TIME_PREFIX.$this->formField->getName(false))) { + $value .= ' ' . $timeValue . ':00'; } elseif ($this->mode == 'time') { $value .= ':00'; From bc016adad74f55623306ff9915bdf21545967860 Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Sun, 28 Dec 2014 13:03:52 +1100 Subject: [PATCH 06/26] Rollback performance change to framework.js because it's broken (Submitting an invalid form in the backend will result in a page refresh, flash messaegs are suppressed) K.I.S.S > Performance + premature optimization is the root of all evil --- modules/system/assets/js/framework.js | 32 ++++----------------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/modules/system/assets/js/framework.js b/modules/system/assets/js/framework.js index 593fc0729..7dfd3db97 100644 --- a/modules/system/assets/js/framework.js +++ b/modules/system/assets/js/framework.js @@ -366,34 +366,10 @@ if (window.jQuery === undefined) $(this).request() }) - document.addEventListener('click', function nativeClickListener(ev){ - // Faster native click listener. This implementation doesn't use - // jQuery until it's really necessary. - var target = ev.target ? ev.target : ev.srcElement - - if (target.getAttribute('data-request') == null) - return - - var tagName = target.tagName - if (tagName == 'A' || tagName == 'BUTTON') { - $(target).request() - return false; - } - - if (tagName == 'INPUT') { - var type = target.getAttribute('type').toLowerCase() - - if (type == 'button' || type == 'submit') { - $(target).request() - return false; - } - } - }); - - // $(document).on('click', 'a[data-request], button[data-request], input[type=button][data-request], input[type=submit][data-request]', function(){ - // $(this).request() - // return false - // }) + $(document).on('click', 'a[data-request], button[data-request], input[type=button][data-request], input[type=submit][data-request]', function(){ + $(this).request() + return false + }) $(document).on('keydown', 'input[type=text][data-request], input[type=submit][data-request], input[type=password][data-request]', function(e){ if (e.keyCode == 13) { From 9cfe4ad8f4d1767332ff77703d6a1b5f37a44a8f Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Fri, 2 Jan 2015 13:24:09 +1100 Subject: [PATCH 07/26] Control CSS: table-control -> control-table --- modules/backend/widgets/Table.php | 18 +-- modules/backend/widgets/table/README.md | 2 +- .../widgets/table/assets/css/table.css | 106 +++++++++--------- .../widgets/table/assets/less/table.less | 18 +-- .../backend/widgets/table/partials/_table.htm | 4 +- 5 files changed, 76 insertions(+), 72 deletions(-) diff --git a/modules/backend/widgets/Table.php b/modules/backend/widgets/Table.php index 3d9bbb67c..bbff7ec57 100644 --- a/modules/backend/widgets/Table.php +++ b/modules/backend/widgets/Table.php @@ -48,14 +48,17 @@ class Table extends WidgetBase $this->recordsKeyColumn = $this->getConfig('key_column', 'id'); $dataSourceClass = $this->getConfig('data_source'); - if (!strlen($dataSourceClass)) + if (!strlen($dataSourceClass)) { throw new SystemException('The Table widget data source is not specified in the configuration.'); + } - if (array_key_exists($dataSourceClass, $this->dataSourceAliases)) + if (array_key_exists($dataSourceClass, $this->dataSourceAliases)) { $dataSourceClass = $this->dataSourceAliases[$dataSourceClass]; + } - if (!class_exists($dataSourceClass)) + if (!class_exists($dataSourceClass)) { throw new SystemException(sprintf('The Table widget data source class "%s" is could not be found.', $dataSourceClass)); + } $this->dataSource = new $dataSourceClass($this->recordsKeyColumn); @@ -106,9 +109,9 @@ class Table extends WidgetBase $isClientDataSource = $this->isClientDataSource(); $this->vars['clientDataSourceClass'] = $isClientDataSource ? 'client' : 'server'; - $this->vars['data'] = $isClientDataSource ? - json_encode($this->dataSource->getAllRecords()) : - []; + $this->vars['data'] = $isClientDataSource + ? json_encode($this->dataSource->getAllRecords()) + : []; } // @@ -167,8 +170,9 @@ class Table extends WidgetBase $eventResults = $this->fireEvent('table.getDropdownOptions', [$columnName, $rowData]); $options = []; - if (count($eventResults)) + if (count($eventResults)) { $options = $eventResults[0]; + } return [ 'options' => $options diff --git a/modules/backend/widgets/table/README.md b/modules/backend/widgets/table/README.md index 985c9a541..f8625673a 100644 --- a/modules/backend/widgets/table/README.md +++ b/modules/backend/widgets/table/README.md @@ -166,7 +166,7 @@ Multiple fields are allowed as well: The widget is configured with YAML file. Required parameters: -* `columns` - the columns definitions, see below +* `columns` - the columns definitions, see below. * `data_source` - The data source class. Should specify the full qualified data source class name or alias. See the data source aliases below. * `key_column` - name of the key column. The default value is **id**. * `records_per_page` - number of records per page. If not specified, the pagination will be disabled. diff --git a/modules/backend/widgets/table/assets/css/table.css b/modules/backend/widgets/table/assets/css/table.css index 4f50e5a7f..c872831ae 100644 --- a/modules/backend/widgets/table/assets/css/table.css +++ b/modules/backend/widgets/table/assets/css/table.css @@ -1,7 +1,7 @@ /* * General control styling */ -.table-control .table-container { +.control-table .table-container { border: 1px solid #808c8d; -webkit-border-radius: 4px; -moz-border-radius: 4px; @@ -9,18 +9,18 @@ overflow: hidden; margin-bottom: 15px; } -.table-control table { +.control-table table { width: 100%; border-collapse: collapse; table-layout: fixed; } -.table-control table td, -.table-control table th { +.control-table table td, +.control-table table th { padding: 0; font-size: 13px; color: #555555; } -.table-control table [data-view-container] { +.control-table table [data-view-container] { padding: 5px 10px; width: 100%; white-space: nowrap; @@ -28,7 +28,7 @@ text-overflow: ellipsis; min-height: 28px; } -.table-control table.headers:after { +.control-table table.headers:after { content: ' '; display: block; position: absolute; @@ -37,7 +37,7 @@ margin-top: -1px; border-bottom: 1px solid #bdc3c7; } -.table-control table.headers th { +.control-table table.headers th { padding: 7px 10px; font-size: 13px; text-transform: uppercase; @@ -49,84 +49,84 @@ overflow: hidden; text-overflow: ellipsis; } -.table-control table.headers th [data-view-container] { +.control-table table.headers th [data-view-container] { padding-bottom: 6px; } -.table-control table.headers th:last-child { +.control-table table.headers th:last-child { border-right: none; } -.table-control table.data td { +.control-table table.data td { border: 1px solid #ecf0f1; /* TODO: this should be applied only when the control is active */ } -.table-control table.data td .content-container { +.control-table table.data td .content-container { position: relative; padding: 1px; } -.table-control table.data td.active { +.control-table table.data td.active { border-color: #5fb6f5 !important; } -.table-control table.data td.active .content-container { +.control-table table.data td.active .content-container { padding: 0; border: 1px solid #5fb6f5; } -.table-control table.data td.active .content-container:before, -.table-control table.data td.active .content-container:after { +.control-table table.data td.active .content-container:before, +.control-table table.data td.active .content-container:after { content: ' '; background: #5fb6f5; position: absolute; left: -2px; top: -2px; } -.table-control table.data td.active .content-container:before { +.control-table table.data td.active .content-container:before { width: 1px; bottom: -2px; } -.table-control table.data td.active .content-container:after { +.control-table table.data td.active .content-container:after { right: -2px; height: 1px; } -.table-control table.data tr { +.control-table table.data tr { background-color: white; } -.table-control table.data tr:nth-child(2n) { +.control-table table.data tr:nth-child(2n) { background-color: #fbfbfb; } -.table-control table.data tr:first-child td { +.control-table table.data tr:first-child td { border-top: none; } -.table-control table.data tr:last-child td { +.control-table table.data tr:last-child td { border-bottom: none; } -.table-control table.data td:first-child { +.control-table table.data td:first-child { border-left: none; } -.table-control table.data td:last-child { +.control-table table.data td:last-child { border-right: none; } -.table-control .control-scrollbar > div { +.control-table .control-scrollbar > div { border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; overflow: hidden; } -.table-control .control-scrollbar table.data tr:last-child td { +.control-table .control-scrollbar table.data tr:last-child td { border-bottom: 1px solid #ecf0f1; } -.table-control .toolbar { +.control-table .toolbar { background: white; border-bottom: 1px solid #bdc3c7; } -.table-control .toolbar a { +.control-table .toolbar a { color: #323e50; padding: 10px; opacity: 0.5; filter: alpha(opacity=50); } -.table-control .toolbar a:hover { +.control-table .toolbar a:hover { opacity: 1; filter: alpha(opacity=100); } -.table-control .toolbar a:before { +.control-table .toolbar a:before { display: inline-block; content: ' '; width: 16px; @@ -138,17 +138,17 @@ background-position: 0 0; background-size: 32px auto; } -.table-control .toolbar a.add-table-row-above:before { +.control-table .toolbar a.add-table-row-above:before { background-position: 0 -56px; } -.table-control .toolbar a.delete-table-row:before { +.control-table .toolbar a.delete-table-row:before { background-position: 0 -113px; } -.table-control .pagination ul { +.control-table .pagination ul { padding: 0; margin-bottom: 15px; } -.table-control .pagination ul li { +.control-table .pagination ul li { list-style: none; padding: 4px 6px; -webkit-border-radius: 2px; @@ -160,32 +160,32 @@ background: #ecf0f1; line-height: 100%; } -.table-control .pagination ul li a { +.control-table .pagination ul li a { text-decoration: none; color: #95a5a6; } -.table-control .pagination ul li.active { +.control-table .pagination ul li.active { background: #5fb6f5; } -.table-control .pagination ul li.active a { +.control-table .pagination ul li.active a { color: #ffffff; } @media only screen and (-moz-min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3/2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-devicepixel-ratio: 1.5), only screen and (min-resolution: 1.5dppx) { - .table-control .toolbar a:before { + .control-table .toolbar a:before { background-position: 0px -9px; background-size: 16px auto; } - .table-control .toolbar a.add-table-row-above:before { + .control-table .toolbar a.add-table-row-above:before { background-position: 0 -39px; } - .table-control .toolbar a.delete-table-row:before { + .control-table .toolbar a.delete-table-row:before { background-position: 0 -66px; } } /* * String editor */ -.table-control td[data-column-type=string] input[type=text] { +.control-table td[data-column-type=string] input[type=text] { width: 100%; height: 100%; display: block; @@ -196,7 +196,7 @@ /* * Checkbox editor */ -.table-control td[data-column-type=checkbox] div[data-checkbox-element] { +.control-table td[data-column-type=checkbox] div[data-checkbox-element] { width: 16px; height: 16px; border-radius: 2px; @@ -209,14 +209,14 @@ -ms-user-select: none; user-select: none; } -.table-control td[data-column-type=checkbox] div[data-checkbox-element]:hover { +.control-table td[data-column-type=checkbox] div[data-checkbox-element]:hover { border-color: #808080; color: #4d4d4d; } -.table-control td[data-column-type=checkbox] div[data-checkbox-element].checked { +.control-table td[data-column-type=checkbox] div[data-checkbox-element].checked { border-width: 2px; } -.table-control td[data-column-type=checkbox] div[data-checkbox-element].checked:before { +.control-table td[data-column-type=checkbox] div[data-checkbox-element].checked:before { font-family: FontAwesome; font-weight: normal; font-style: normal; @@ -229,25 +229,25 @@ left: 1px; top: -4px; } -.table-control td[data-column-type=checkbox] div[data-checkbox-element]:focus { +.control-table td[data-column-type=checkbox] div[data-checkbox-element]:focus { border-color: #5fb6f5; outline: none; } /* * Dropdown editor */ -.table-control td[data-column-type=dropdown] { +.control-table td[data-column-type=dropdown] { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } -.table-control td[data-column-type=dropdown] [data-view-container] { +.control-table td[data-column-type=dropdown] [data-view-container] { padding-right: 20px; position: relative; cursor: pointer; } -.table-control td[data-column-type=dropdown] [data-view-container]:after { +.control-table td[data-column-type=dropdown] [data-view-container]:after { font-family: FontAwesome; font-weight: normal; font-style: normal; @@ -262,13 +262,13 @@ top: 8px; right: 10px; } -.table-control td[data-column-type=dropdown] [data-view-container]:hover:after { +.control-table td[data-column-type=dropdown] [data-view-container]:hover:after { color: #0181b9; } -.table-control td[data-column-type=dropdown] [data-dropdown-open=true] { +.control-table td[data-column-type=dropdown] [data-dropdown-open=true] { background: white; } -.table-control td[data-column-type=dropdown] [data-dropdown-open=true] [data-view-container]:after { +.control-table td[data-column-type=dropdown] [data-dropdown-open=true] [data-view-container]:after { font-family: FontAwesome; font-weight: normal; font-style: normal; @@ -277,10 +277,10 @@ *margin-right: .3em; content: "\f106"; } -.table-control td[data-column-type=dropdown] .content-container { +.control-table td[data-column-type=dropdown] .content-container { outline: none; } -html.cssanimations .table-control td[data-column-type=dropdown] [data-view-container].loading:after { +html.cssanimations .control-table td[data-column-type=dropdown] [data-view-container].loading:after { background-image: url(../../../../assets/images/loading-indicator-transparent.svg); background-size: 15px 15px; background-position: 50% 50%; diff --git a/modules/backend/widgets/table/assets/less/table.less b/modules/backend/widgets/table/assets/less/table.less index 19183ddef..42ad7ade8 100644 --- a/modules/backend/widgets/table/assets/less/table.less +++ b/modules/backend/widgets/table/assets/less/table.less @@ -4,7 +4,7 @@ * General control styling */ -.table-control { +.control-table { .table-container { border: 1px solid #808c8d; .border-radius(4px); @@ -43,7 +43,7 @@ margin-top: -1px; border-bottom: 1px solid #bdc3c7; } - + th { padding: 7px 10px; font-size: 13px; @@ -108,12 +108,12 @@ background-color: white; } - tr:nth-child(2n) { + tr:nth-child(2n) { background-color: #fbfbfb; } } - table.data { + table.data { tr:first-child td { border-top: none; } @@ -211,7 +211,7 @@ } @media only screen and (-moz-min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3/2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-devicepixel-ratio: 1.5), only screen and (min-resolution: 1.5dppx) { - .table-control .toolbar { + .control-table .toolbar { a { &:before { background-position: 0px -9px; @@ -233,7 +233,7 @@ * String editor */ -.table-control { +.control-table { td[data-column-type=string] { input[type=text] { width: 100%; @@ -250,7 +250,7 @@ * Checkbox editor */ -.table-control { +.control-table { td[data-column-type=checkbox] { div[data-checkbox-element] { width: 16px; @@ -292,7 +292,7 @@ * Dropdown editor */ -.table-control { +.control-table { td[data-column-type=dropdown] { .user-select(none); @@ -334,7 +334,7 @@ } html.cssanimations { - .table-control td[data-column-type=dropdown] { + .control-table td[data-column-type=dropdown] { [data-view-container].loading:after { background-image:url(../../../../assets/images/loading-indicator-transparent.svg); background-size: 15px 15px; diff --git a/modules/backend/widgets/table/partials/_table.htm b/modules/backend/widgets/table/partials/_table.htm index bed4c36e0..648e0056e 100644 --- a/modules/backend/widgets/table/partials/_table.htm +++ b/modules/backend/widgets/table/partials/_table.htm @@ -1,6 +1,6 @@ -
Date: Fri, 2 Jan 2015 13:35:27 +1100 Subject: [PATCH 08/26] records_per_page -> recordsPerPage --- modules/backend/widgets/Table.php | 2 +- modules/backend/widgets/table/README.md | 2 +- modules/backend/widgets/table/partials/_table.htm | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/backend/widgets/Table.php b/modules/backend/widgets/Table.php index bbff7ec57..4f712ca8a 100644 --- a/modules/backend/widgets/Table.php +++ b/modules/backend/widgets/Table.php @@ -99,7 +99,7 @@ class Table extends WidgetBase $this->vars['columns'] = $this->prepareColumnsArray(); $this->vars['recordsKeyColumn'] = $this->recordsKeyColumn; - $this->vars['recordsPerPage'] = $this->getConfig('records_per_page', false) ?: 'false'; + $this->vars['recordsPerPage'] = $this->getConfig('recordsPerPage', false) ?: 'false'; $this->vars['postbackHandlerName'] = $this->getConfig('postback_handler_name', 'onSave'); $this->vars['adding'] = $this->getConfig('adding', true); $this->vars['deleting'] = $this->getConfig('deleting', true); diff --git a/modules/backend/widgets/table/README.md b/modules/backend/widgets/table/README.md index f8625673a..4efc765c6 100644 --- a/modules/backend/widgets/table/README.md +++ b/modules/backend/widgets/table/README.md @@ -169,7 +169,7 @@ The widget is configured with YAML file. Required parameters: * `columns` - the columns definitions, see below. * `data_source` - The data source class. Should specify the full qualified data source class name or alias. See the data source aliases below. * `key_column` - name of the key column. The default value is **id**. -* `records_per_page` - number of records per page. If not specified, the pagination will be disabled. +* `recordsPerPage` - number of records per page. If not specified, the pagination will be disabled. * `postback_handler_name` - AJAX data handler name for the automatic data postback. The data will be posted only when the AJAX requests posts data to this handler. The default value is **onSave**. This parameter is applicable only with client-memory data sources. * `adding` - indicates if record deleting is allowed, default is **true**. * `deleting` - indicates if record deleting is allowed, default is **true**. diff --git a/modules/backend/widgets/table/partials/_table.htm b/modules/backend/widgets/table/partials/_table.htm index 648e0056e..4f621f059 100644 --- a/modules/backend/widgets/table/partials/_table.htm +++ b/modules/backend/widgets/table/partials/_table.htm @@ -1,4 +1,5 @@
Date: Fri, 2 Jan 2015 13:49:26 +1100 Subject: [PATCH 09/26] postbackHandlerName / postback_handler_name -> handler --- modules/backend/widgets/Table.php | 2 +- modules/backend/widgets/table/README.md | 10 +++++----- modules/backend/widgets/table/assets/js/table.js | 4 ++-- modules/backend/widgets/table/partials/_table.htm | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/modules/backend/widgets/Table.php b/modules/backend/widgets/Table.php index 4f712ca8a..168e39131 100644 --- a/modules/backend/widgets/Table.php +++ b/modules/backend/widgets/Table.php @@ -100,7 +100,7 @@ class Table extends WidgetBase $this->vars['recordsKeyColumn'] = $this->recordsKeyColumn; $this->vars['recordsPerPage'] = $this->getConfig('recordsPerPage', false) ?: 'false'; - $this->vars['postbackHandlerName'] = $this->getConfig('postback_handler_name', 'onSave'); + $this->vars['handler'] = $this->getConfig('handler', 'onSave'); $this->vars['adding'] = $this->getConfig('adding', true); $this->vars['deleting'] = $this->getConfig('deleting', true); $this->vars['toolbar'] = $this->getConfig('toolbar', true); diff --git a/modules/backend/widgets/table/README.md b/modules/backend/widgets/table/README.md index 4efc765c6..8c08be947 100644 --- a/modules/backend/widgets/table/README.md +++ b/modules/backend/widgets/table/README.md @@ -78,8 +78,8 @@ The options below are listed in the JavaScript notation. Corresponding data attr - `columns` - column definitions in JSON format, see the server-side column definition format below. - `rowSorting` - enables the drag & drop row sorting. The sorting cannot be used with the pagination (`recordsPerPage` is not `null` or `false`). - `keyColumn` - specifies the name of the key column. The default value is **id**. -- `postback` - post the client-memory data source data to the server automatically when the parent form gets submitted. The default value is `true`. The option is used only with client-memory data sources. When enabled, the data source data is available in the widget's server-side data source: `$table->getDataSource()->getRecords();` The data postback occurs only of the request handler name matches the `postbackHandlerName` option value. -- `postbackHandlerName` - AJAX data handler name for the automatic data postback. The data will be posted only when the AJAX requests posts data to this handler. The default value is **onSave**. +- `postback` - post the client-memory data source data to the server automatically when the parent form gets submitted. The default value is `true`. The option is used only with client-memory data sources. When enabled, the data source data is available in the widget's server-side data source: `$table->getDataSource()->getRecords();` The data postback occurs only of the request handler name matches the `handler` option value. +- `handler` - AJAX data handler name for the automatic data postback. The data will be posted only when the AJAX requests posts data to this handler. The default value is **onSave**. - `adding` - determines whether users can add new records. Default value is **true**. - `deleting` - determines whether users can delete records. Default value is **true**. - `toolbar` - determines whether the toolbar is visible. The default value is **true**. @@ -170,7 +170,7 @@ The widget is configured with YAML file. Required parameters: * `data_source` - The data source class. Should specify the full qualified data source class name or alias. See the data source aliases below. * `key_column` - name of the key column. The default value is **id**. * `recordsPerPage` - number of records per page. If not specified, the pagination will be disabled. -* `postback_handler_name` - AJAX data handler name for the automatic data postback. The data will be posted only when the AJAX requests posts data to this handler. The default value is **onSave**. This parameter is applicable only with client-memory data sources. +* `handler` - AJAX data handler name for the automatic data postback. The data will be posted only when the AJAX requests posts data to this handler. The default value is **onSave**. This parameter is applicable only with client-memory data sources. * `adding` - indicates if record deleting is allowed, default is **true**. * `deleting` - indicates if record deleting is allowed, default is **true**. * `toolbar` - specifies if the toolbar should be visible, default is **true**. @@ -247,11 +247,11 @@ $dataSource->purge(); The server-side data sources (PHP) automatically maintain the actual data, but that mechanism for the client-memory and server-memory data sources is different. -In case of the client-memory data source, the table widget adds the data records to the POST, when the form is saved (see `postback` and `postbackHandlerName` options). On the server side the data is inserted to the data source by the table widget. +In case of the client-memory data source, the table widget adds the data records to the POST, when the form is saved (see `postback` and `handler` options). On the server side the data is inserted to the data source by the table widget. The server-memory data source always automatically maintain its contents in synch with the client using AJAX, and POSTing data is not required. -In PHP reading data from a data source of any type looks like this (it should be in the AJAX handler that saves the data, for the client-memory data source the handler name should match the `postbackHandlerName` option value): +In PHP reading data from a data source of any type looks like this (it should be in the AJAX handler that saves the data, for the client-memory data source the handler name should match the `handler` option value): ``` public function onSave() diff --git a/modules/backend/widgets/table/assets/js/table.js b/modules/backend/widgets/table/assets/js/table.js index 9f5ae4026..a6d8e95f8 100644 --- a/modules/backend/widgets/table/assets/js/table.js +++ b/modules/backend/widgets/table/assets/js/table.js @@ -664,7 +664,7 @@ } Table.prototype.onFormSubmit = function(ev, data) { - if (data.handler == this.options.postbackHandlerName) { + if (data.handler == this.options.handler) { this.unfocusTable() data.options.data[this.options.alias + 'TableData'] = this.dataSource.getAllData() } @@ -844,7 +844,7 @@ recordsPerPage: false, data: null, postback: true, - postbackHandlerName: 'onSave', + handler: 'onSave', adding: true, deleting: true, toolbar: true, diff --git a/modules/backend/widgets/table/partials/_table.htm b/modules/backend/widgets/table/partials/_table.htm index 4f621f059..9c547f9d5 100644 --- a/modules/backend/widgets/table/partials/_table.htm +++ b/modules/backend/widgets/table/partials/_table.htm @@ -4,7 +4,7 @@ class="control-table" data-columns="" data-data="" - data-postback-handler-name="" + data-handler="" data-adding="" data-deleting="" data-toolbar="" From 59a0e08cd090144f1690df4c41124e68580f0fbb Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Fri, 2 Jan 2015 13:50:51 +1100 Subject: [PATCH 10/26] data_source -> dataSource --- modules/backend/widgets/Table.php | 2 +- modules/backend/widgets/table/README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/backend/widgets/Table.php b/modules/backend/widgets/Table.php index 168e39131..6b37078b9 100644 --- a/modules/backend/widgets/Table.php +++ b/modules/backend/widgets/Table.php @@ -47,7 +47,7 @@ class Table extends WidgetBase $this->recordsKeyColumn = $this->getConfig('key_column', 'id'); - $dataSourceClass = $this->getConfig('data_source'); + $dataSourceClass = $this->getConfig('dataSource'); if (!strlen($dataSourceClass)) { throw new SystemException('The Table widget data source is not specified in the configuration.'); } diff --git a/modules/backend/widgets/table/README.md b/modules/backend/widgets/table/README.md index 8c08be947..0753f383f 100644 --- a/modules/backend/widgets/table/README.md +++ b/modules/backend/widgets/table/README.md @@ -167,7 +167,7 @@ Multiple fields are allowed as well: The widget is configured with YAML file. Required parameters: * `columns` - the columns definitions, see below. -* `data_source` - The data source class. Should specify the full qualified data source class name or alias. See the data source aliases below. +* `dataSource` - The data source class. Should specify the full qualified data source class name or alias. See the data source aliases below. * `key_column` - name of the key column. The default value is **id**. * `recordsPerPage` - number of records per page. If not specified, the pagination will be disabled. * `handler` - AJAX data handler name for the automatic data postback. The data will be posted only when the AJAX requests posts data to this handler. The default value is **onSave**. This parameter is applicable only with client-memory data sources. @@ -176,7 +176,7 @@ The widget is configured with YAML file. Required parameters: * `toolbar` - specifies if the toolbar should be visible, default is **true**. * `height` - specifies the data table height, in pixels. The default value is **false** - the height is not limited. -The `data_source` parameter can take aliases for some data source classes for the simpler configuration syntax. Known aliases are: +The `dataSource` parameter can take aliases for some data source classes for the simpler configuration syntax. Known aliases are: * `client` = \Backend\Classes\TableClientMemoryDataSource From 433c4c07ff9713c1505de89e3b8640c4b652f347 Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Fri, 2 Jan 2015 13:53:56 +1100 Subject: [PATCH 11/26] key_column -> keyFrom --- modules/backend/widgets/Table.php | 8 ++++---- modules/backend/widgets/table/README.md | 2 +- modules/backend/widgets/table/partials/_table.htm | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/backend/widgets/Table.php b/modules/backend/widgets/Table.php index 6b37078b9..c7450b6ca 100644 --- a/modules/backend/widgets/Table.php +++ b/modules/backend/widgets/Table.php @@ -32,7 +32,7 @@ class Table extends WidgetBase protected $dataSource = null; - protected $recordsKeyColumn; + protected $recordsKeyFrom; protected $dataSourceAliases = [ 'client' => '\Backend\Classes\TableClientMemoryDataSource' @@ -45,7 +45,7 @@ class Table extends WidgetBase { $this->columns = $this->getConfig('columns', []); - $this->recordsKeyColumn = $this->getConfig('key_column', 'id'); + $this->recordsKeyFrom = $this->getConfig('keyFrom', 'id'); $dataSourceClass = $this->getConfig('dataSource'); if (!strlen($dataSourceClass)) { @@ -60,7 +60,7 @@ class Table extends WidgetBase throw new SystemException(sprintf('The Table widget data source class "%s" is could not be found.', $dataSourceClass)); } - $this->dataSource = new $dataSourceClass($this->recordsKeyColumn); + $this->dataSource = new $dataSourceClass($this->recordsKeyFrom); if (Request::method() == 'POST' && $this->isClientDataSource()) { $requestDataField = $this->alias.'TableData'; @@ -97,7 +97,7 @@ class Table extends WidgetBase public function prepareVars() { $this->vars['columns'] = $this->prepareColumnsArray(); - $this->vars['recordsKeyColumn'] = $this->recordsKeyColumn; + $this->vars['recordsKeyFrom'] = $this->recordsKeyFrom; $this->vars['recordsPerPage'] = $this->getConfig('recordsPerPage', false) ?: 'false'; $this->vars['handler'] = $this->getConfig('handler', 'onSave'); diff --git a/modules/backend/widgets/table/README.md b/modules/backend/widgets/table/README.md index 0753f383f..e9d651348 100644 --- a/modules/backend/widgets/table/README.md +++ b/modules/backend/widgets/table/README.md @@ -168,7 +168,7 @@ The widget is configured with YAML file. Required parameters: * `columns` - the columns definitions, see below. * `dataSource` - The data source class. Should specify the full qualified data source class name or alias. See the data source aliases below. -* `key_column` - name of the key column. The default value is **id**. +* `keyFrom` - name of the key column. The default value is **id**. * `recordsPerPage` - number of records per page. If not specified, the pagination will be disabled. * `handler` - AJAX data handler name for the automatic data postback. The data will be posted only when the AJAX requests posts data to this handler. The default value is **onSave**. This parameter is applicable only with client-memory data sources. * `adding` - indicates if record deleting is allowed, default is **true**. diff --git a/modules/backend/widgets/table/partials/_table.htm b/modules/backend/widgets/table/partials/_table.htm index 9c547f9d5..352b18a73 100644 --- a/modules/backend/widgets/table/partials/_table.htm +++ b/modules/backend/widgets/table/partials/_table.htm @@ -10,6 +10,6 @@ data-toolbar="" data-height="" data-records-per-page="" - data-key-column="" + data-key-column="" data-client-data-source-class="" data-alias="alias) ?>">
\ No newline at end of file From a6259ff915aba8c17ee5476b80c8523999323033 Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Sat, 3 Jan 2015 10:04:06 +1100 Subject: [PATCH 12/26] depends_on -> dependsOn --- modules/backend/ServiceProvider.php | 4 ++++ modules/backend/widgets/table/README.md | 10 +++++----- .../assets/js/table.processor.dropdown.js | 19 ++++++++++--------- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/modules/backend/ServiceProvider.php b/modules/backend/ServiceProvider.php index 950cea44e..fd18a0d4d 100644 --- a/modules/backend/ServiceProvider.php +++ b/modules/backend/ServiceProvider.php @@ -56,6 +56,10 @@ class ServiceProvider extends ModuleServiceProvider $manager->registerFormWidget('Backend\FormWidgets\DataGrid', [ 'label' => 'Data Grid', 'code' => 'datagrid' + ]); // @drepcated + $manager->registerFormWidget('Backend\FormWidgets\DataTable', [ + 'label' => 'Data Table', + 'code' => 'datatable' ]); $manager->registerFormWidget('Backend\FormWidgets\RecordFinder', [ 'label' => 'Record Finder', diff --git a/modules/backend/widgets/table/README.md b/modules/backend/widgets/table/README.md index e9d651348..ec461406c 100644 --- a/modules/backend/widgets/table/README.md +++ b/modules/backend/widgets/table/README.md @@ -144,19 +144,19 @@ If the `options` element is not presented in the configuration, the options will **TODO:** Document the AJAX interface -The drop-down options could depend on other columns. This works only with AJAX-based drop-downs. The column a drop-down depends on are defined with the `depends_on` property: +The drop-down options could depend on other columns. This works only with AJAX-based drop-downs. The column a drop-down depends on are defined with the `dependsOn` property: state: title: State type: dropdown - depends_on: country + dependsOn: country Multiple fields are allowed as well: state: title: State type: dropdown - depends_on: [country, language] + dependsOn: [country, language] **Note:** Dependent drop-down should always be defined after their master columns. @@ -187,9 +187,9 @@ Columns are defined as array with the `columns` property. The array keys corresp - `title` - `type` (string, checkbox, dropdown, autocomplete) - `width` - sets the column width, can be specified in percents (10%) or pixels (50px). There could be a single column without the width specified. It will be stretched to take the available space. -- `readonly` +- `readOnly` - `options` (for drop-down elements and autocomplete types) -- `depends_on` (from drop-down elements) +- `dependsOn` (from drop-down elements) ## Events diff --git a/modules/backend/widgets/table/assets/js/table.processor.dropdown.js b/modules/backend/widgets/table/assets/js/table.processor.dropdown.js index 1b7b4dd0c..ad984e956 100644 --- a/modules/backend/widgets/table/assets/js/table.processor.dropdown.js +++ b/modules/backend/widgets/table/assets/js/table.processor.dropdown.js @@ -230,7 +230,7 @@ DropdownProcessor.prototype.createOptionsCachingKey = function(row) { var cachingKey = 'non-dependent', - dependsOn = this.columnConfiguration.depends_on + dependsOn = this.columnConfiguration.dependsOn if (dependsOn) { if (typeof dependsOn == 'object') { @@ -277,8 +277,7 @@ DropdownProcessor.prototype.onItemClick = function(ev) { var target = this.tableObj.getEventTarget(ev) - if (target.tagName == 'LI') - { + if (target.tagName == 'LI') { this.updateCellFromSelectedItem(target) var selected = this.findSelectedItem() @@ -349,11 +348,11 @@ // Determine if this drop-down depends on the changed column // and update the option list if necessary - if (!this.columnConfiguration.depends_on) + if (!this.columnConfiguration.dependsOn) return var dependsOnColumn = false, - dependsOn = this.columnConfiguration.depends_on + dependsOn = this.columnConfiguration.dependsOn if (typeof dependsOn == 'object') { for (var i = 0, len = dependsOn.length; i < len; i++ ) { @@ -362,8 +361,10 @@ break } } - } else + } + else { dependsOnColumn = dependsOn == columnName + } if (!dependsOnColumn) return @@ -372,9 +373,9 @@ viewContainer = this.getViewContainer(cellElement) this.fetchOptions(cellElement, function rowValueChangedFetchOptions(options) { - var value = options[currentValue] !== undefined ? - options[currentValue] : - '...' + var value = options[currentValue] !== undefined + ? options[currentValue] + : '...' viewContainer.textContent = value viewContainer = null From 83223938b2439e3034e8c0e0c0b834670cc955db Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Sat, 3 Jan 2015 11:25:08 +1100 Subject: [PATCH 13/26] Minor --- modules/backend/ServiceProvider.php | 2 +- modules/backend/lang/en/lang.php | 1 + modules/backend/widgets/table/README.md | 2 +- modules/backend/widgets/table/assets/js/table.js | 16 ++++++++-------- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/modules/backend/ServiceProvider.php b/modules/backend/ServiceProvider.php index fd18a0d4d..6b1df8b3f 100644 --- a/modules/backend/ServiceProvider.php +++ b/modules/backend/ServiceProvider.php @@ -56,7 +56,7 @@ class ServiceProvider extends ModuleServiceProvider $manager->registerFormWidget('Backend\FormWidgets\DataGrid', [ 'label' => 'Data Grid', 'code' => 'datagrid' - ]); // @drepcated + ]); // @deprecated if year >= 2015 $manager->registerFormWidget('Backend\FormWidgets\DataTable', [ 'label' => 'Data Table', 'code' => 'datatable' diff --git a/modules/backend/lang/en/lang.php b/modules/backend/lang/en/lang.php index d7b6348e0..2917833d3 100644 --- a/modules/backend/lang/en/lang.php +++ b/modules/backend/lang/en/lang.php @@ -215,6 +215,7 @@ return [ 'not_found' => "Model ':class' with an ID of :id could not be found", 'missing_id' => "There is no ID specified for looking up the model record.", 'missing_relation' => "Model ':class' does not contain a definition for ':relation'.", + 'missing_method' => "Model ':class' does not contain a method ':method'.", 'invalid_class' => "Model :model used in :class is not valid, it must inherit the \Model class.", 'mass_assignment_failed' => "Mass assignment failed for Model attribute ':attribute'.", ], diff --git a/modules/backend/widgets/table/README.md b/modules/backend/widgets/table/README.md index ec461406c..2a5b808d9 100644 --- a/modules/backend/widgets/table/README.md +++ b/modules/backend/widgets/table/README.md @@ -79,7 +79,7 @@ The options below are listed in the JavaScript notation. Corresponding data attr - `rowSorting` - enables the drag & drop row sorting. The sorting cannot be used with the pagination (`recordsPerPage` is not `null` or `false`). - `keyColumn` - specifies the name of the key column. The default value is **id**. - `postback` - post the client-memory data source data to the server automatically when the parent form gets submitted. The default value is `true`. The option is used only with client-memory data sources. When enabled, the data source data is available in the widget's server-side data source: `$table->getDataSource()->getRecords();` The data postback occurs only of the request handler name matches the `handler` option value. -- `handler` - AJAX data handler name for the automatic data postback. The data will be posted only when the AJAX requests posts data to this handler. The default value is **onSave**. +- `handler` - AJAX data handler name for the automatic data postback. The data will be posted only when the AJAX request posts data matching this handler name. The default value is **onSave**. - `adding` - determines whether users can add new records. Default value is **true**. - `deleting` - determines whether users can delete records. Default value is **true**. - `toolbar` - determines whether the toolbar is visible. The default value is **true**. diff --git a/modules/backend/widgets/table/assets/js/table.js b/modules/backend/widgets/table/assets/js/table.js index a6d8e95f8..f835a2d79 100644 --- a/modules/backend/widgets/table/assets/js/table.js +++ b/modules/backend/widgets/table/assets/js/table.js @@ -278,9 +278,9 @@ if (this.options.columns[i].width) header.setAttribute('style', 'width: '+this.options.columns[i].width) - header.textContent !== undefined ? - header.textContent = this.options.columns[i].title : - header.innerText = this.options.columns[i].title + header.textContent !== undefined + ? header.textContent = this.options.columns[i].title + : header.innerText = this.options.columns[i].title row.appendChild(header) } @@ -395,7 +395,7 @@ Table.prototype.scrollCellIntoView = function() { if (!this.options.height || !this.activeCell) return - + $(this.dataTableContainer.parentNode).data('oc.scrollbar').gotoElement(this.activeCell) } @@ -605,7 +605,7 @@ Table.prototype.getToolbar = function() { return this.tableContainer.querySelector('div.toolbar') - } + } // EVENT HANDLERS // ============================ @@ -675,13 +675,13 @@ cmd = target.getAttribute('data-cmd') switch (cmd) { - case 'record-add-below': + case 'record-add-below': this.addRecord('below') break - case 'record-add-above': + case 'record-add-above': this.addRecord('above') break - case 'record-delete': + case 'record-delete': this.deleteRecord() break } From a2dec246e56b68b48938da7b6649998cb3d5ca6e Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Sat, 3 Jan 2015 11:30:02 +1100 Subject: [PATCH 14/26] handler -> postbackHandlerName (doesn't do the same thing as traditional 'handler') --- modules/backend/widgets/Table.php | 4 ++-- modules/backend/widgets/table/README.md | 10 +++++----- modules/backend/widgets/table/assets/js/table.js | 4 ++-- modules/backend/widgets/table/partials/_table.htm | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/backend/widgets/Table.php b/modules/backend/widgets/Table.php index c7450b6ca..3a3fe8191 100644 --- a/modules/backend/widgets/Table.php +++ b/modules/backend/widgets/Table.php @@ -100,7 +100,7 @@ class Table extends WidgetBase $this->vars['recordsKeyFrom'] = $this->recordsKeyFrom; $this->vars['recordsPerPage'] = $this->getConfig('recordsPerPage', false) ?: 'false'; - $this->vars['handler'] = $this->getConfig('handler', 'onSave'); + $this->vars['postbackHandlerName'] = $this->getConfig('postbackHandlerName', 'onSave'); $this->vars['adding'] = $this->getConfig('adding', true); $this->vars['deleting'] = $this->getConfig('deleting', true); $this->vars['toolbar'] = $this->getConfig('toolbar', true); @@ -153,7 +153,7 @@ class Table extends WidgetBase return $result; } - protected function isClientDataSource() + protected function isClientDataSource() { return $this->dataSource instanceof \Backend\Classes\TableClientMemoryDataSource; } diff --git a/modules/backend/widgets/table/README.md b/modules/backend/widgets/table/README.md index 2a5b808d9..bcfe4076d 100644 --- a/modules/backend/widgets/table/README.md +++ b/modules/backend/widgets/table/README.md @@ -78,8 +78,8 @@ The options below are listed in the JavaScript notation. Corresponding data attr - `columns` - column definitions in JSON format, see the server-side column definition format below. - `rowSorting` - enables the drag & drop row sorting. The sorting cannot be used with the pagination (`recordsPerPage` is not `null` or `false`). - `keyColumn` - specifies the name of the key column. The default value is **id**. -- `postback` - post the client-memory data source data to the server automatically when the parent form gets submitted. The default value is `true`. The option is used only with client-memory data sources. When enabled, the data source data is available in the widget's server-side data source: `$table->getDataSource()->getRecords();` The data postback occurs only of the request handler name matches the `handler` option value. -- `handler` - AJAX data handler name for the automatic data postback. The data will be posted only when the AJAX request posts data matching this handler name. The default value is **onSave**. +- `postback` - post the client-memory data source data to the server automatically when the parent form gets submitted. The default value is `true`. The option is used only with client-memory data sources. When enabled, the data source data is available in the widget's server-side data source: `$table->getDataSource()->getRecords();` The data postback occurs only of the request handler name matches the `postbackHandlerName` option value. +- `postbackHandlerName` - AJAX data handler name for the automatic data postback. The data will be posted only when the AJAX request posts data matching this handler name. The default value is **onSave**. - `adding` - determines whether users can add new records. Default value is **true**. - `deleting` - determines whether users can delete records. Default value is **true**. - `toolbar` - determines whether the toolbar is visible. The default value is **true**. @@ -170,7 +170,7 @@ The widget is configured with YAML file. Required parameters: * `dataSource` - The data source class. Should specify the full qualified data source class name or alias. See the data source aliases below. * `keyFrom` - name of the key column. The default value is **id**. * `recordsPerPage` - number of records per page. If not specified, the pagination will be disabled. -* `handler` - AJAX data handler name for the automatic data postback. The data will be posted only when the AJAX requests posts data to this handler. The default value is **onSave**. This parameter is applicable only with client-memory data sources. +* `postbackHandlerName` - AJAX data handler name for the automatic data postback. The data will be posted only when the AJAX requests posts data to this handler. The default value is **onSave**. This parameter is applicable only with client-memory data sources. * `adding` - indicates if record deleting is allowed, default is **true**. * `deleting` - indicates if record deleting is allowed, default is **true**. * `toolbar` - specifies if the toolbar should be visible, default is **true**. @@ -247,11 +247,11 @@ $dataSource->purge(); The server-side data sources (PHP) automatically maintain the actual data, but that mechanism for the client-memory and server-memory data sources is different. -In case of the client-memory data source, the table widget adds the data records to the POST, when the form is saved (see `postback` and `handler` options). On the server side the data is inserted to the data source by the table widget. +In case of the client-memory data source, the table widget adds the data records to the POST, when the form is saved (see `postback` and `postbackHandlerName` options). On the server side the data is inserted to the data source by the table widget. The server-memory data source always automatically maintain its contents in synch with the client using AJAX, and POSTing data is not required. -In PHP reading data from a data source of any type looks like this (it should be in the AJAX handler that saves the data, for the client-memory data source the handler name should match the `handler` option value): +In PHP reading data from a data source of any type looks like this (it should be in the AJAX handler that saves the data, for the client-memory data source the handler name should match the `postbackHandlerName` option value): ``` public function onSave() diff --git a/modules/backend/widgets/table/assets/js/table.js b/modules/backend/widgets/table/assets/js/table.js index f835a2d79..1fe291089 100644 --- a/modules/backend/widgets/table/assets/js/table.js +++ b/modules/backend/widgets/table/assets/js/table.js @@ -664,7 +664,7 @@ } Table.prototype.onFormSubmit = function(ev, data) { - if (data.handler == this.options.handler) { + if (data.handler == this.options.postbackHandlerName) { this.unfocusTable() data.options.data[this.options.alias + 'TableData'] = this.dataSource.getAllData() } @@ -844,7 +844,7 @@ recordsPerPage: false, data: null, postback: true, - handler: 'onSave', + postbackHandlerName: 'onSave', adding: true, deleting: true, toolbar: true, diff --git a/modules/backend/widgets/table/partials/_table.htm b/modules/backend/widgets/table/partials/_table.htm index 352b18a73..06f50d0f8 100644 --- a/modules/backend/widgets/table/partials/_table.htm +++ b/modules/backend/widgets/table/partials/_table.htm @@ -4,7 +4,7 @@ class="control-table" data-columns="" data-data="" - data-handler="" + data-postback-handler-name="" data-adding="" data-deleting="" data-toolbar="" From 29b4f8bb179fae2769297fcc55c18d2144087b2c Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Sat, 3 Jan 2015 11:49:25 +1100 Subject: [PATCH 15/26] Elaborate on client side data access --- modules/backend/widgets/table/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/backend/widgets/table/README.md b/modules/backend/widgets/table/README.md index bcfe4076d..cb66bbec5 100644 --- a/modules/backend/widgets/table/README.md +++ b/modules/backend/widgets/table/README.md @@ -245,9 +245,9 @@ $dataSource->purge(); ## Reading data from the data source -The server-side data sources (PHP) automatically maintain the actual data, but that mechanism for the client-memory and server-memory data sources is different. +The server-side data sources (PHP) automatically maintain the actual data, but that mechanism for the client-memory and server-memory data sources is different. -In case of the client-memory data source, the table widget adds the data records to the POST, when the form is saved (see `postback` and `postbackHandlerName` options). On the server side the data is inserted to the data source by the table widget. +In case of the client-memory data source, the table widget adds the data records to the POST, when the form is saved using the AJAX Framework (see `postback` and `postbackHandlerName` options). The table data will be injected automatically to the AJAX request when the `postback` value is `true` and the `postbackHandlerName` matches the exact handler name of the request. On the server side the data is inserted to the data source and can be accessed using the PHP example below. The server-memory data source always automatically maintain its contents in synch with the client using AJAX, and POSTing data is not required. From 7dd147a62a9f29267f9abf0837e2b9fad5cbd128 Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Sat, 3 Jan 2015 11:57:50 +1100 Subject: [PATCH 16/26] Create initial DataTable form widget --- .../backend/classes/TableDataSourceBase.php | 4 +- modules/backend/formwidgets/DataTable.php | 137 ++++++++++++++++++ .../datatable/partials/_datatable.htm | 8 + 3 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 modules/backend/formwidgets/DataTable.php create mode 100644 modules/backend/formwidgets/datatable/partials/_datatable.htm diff --git a/modules/backend/classes/TableDataSourceBase.php b/modules/backend/classes/TableDataSourceBase.php index 867747b54..21f5e273c 100644 --- a/modules/backend/classes/TableDataSourceBase.php +++ b/modules/backend/classes/TableDataSourceBase.php @@ -65,14 +65,14 @@ abstract class TableDataSourceBase /** * Returns a set of records from the data source. * @param integer $count Specifies the number of records to return. - * @return array Returns the records. + * @return array Returns the records. * If there are no more records, returns an empty array. */ public function readRecords($count = 10) { $result = $this->getRecords($this->offset, $count); $this->offset += count($result); - + return $result; } } \ No newline at end of file diff --git a/modules/backend/formwidgets/DataTable.php b/modules/backend/formwidgets/DataTable.php new file mode 100644 index 000000000..2b00ce688 --- /dev/null +++ b/modules/backend/formwidgets/DataTable.php @@ -0,0 +1,137 @@ +size = $this->getConfig('size', $this->size); + $this->table = $this->makeTableWidget(); + $this->table->bindToController(); + } + + /** + * @return Backend\Widgets\Table The table to be displayed. + */ + public function getTable() + { + return $this->table; + } + + /** + * {@inheritDoc} + */ + public function render() + { + $this->prepareVars(); + return $this->makePartial('datatable'); + } + + /** + * Prepares the list data + */ + public function prepareVars() + { + $this->populateTableWidget(); + $this->vars['table'] = $this->table; + $this->vars['size'] = $this->size; + } + + /** + * {@inheritDoc} + */ + public function getSaveData($value) + { + $dataSource = $this->table->getDataSource(); + + $result = []; + while ($records = $dataSource->readRecords()) { + $result += $records; + } + + return $result; + } + + /* + * Populate data + */ + protected function populateTableWidget() + { + $dataSource = $this->table->getDataSource(); + $records = $this->getLoadData() ?: []; + traceLog($records); + $dataSource->initRecords((array) $records); + } + + protected function makeTableWidget() + { + $config = $this->makeConfig((array) $this->config); + $config->dataSource = 'client'; + $config->alias = $this->alias . 'Table'; + + $table = new Table($this->controller, $config); + + $table->bindEvent('table.getDropdownOptions', [$this, 'getDataTableOptions']); + + return $table; + } + + /** + * Looks at the model for getXXXDataTableOptions or getDataTableOptions methods + * to obtain values for autocomplete field types. + * @param string $field Table field name + * @param string $data Data for the entire table + * @return array + */ + public function getDataTableOptions($field, $data) + { + $methodName = 'get'.studly_case($this->fieldName).'DataTableOptions'; + + if (!$this->model->methodExists($methodName) && !$this->model->methodExists('getDataTableOptions')) { + throw new ApplicationException(Lang::get('backend::lang.model.missing_method', ['class' => get_class($this->model), 'method' => 'getDataTableOptions'])); + } + + if ($this->model->methodExists($methodName)) { + $result = $this->model->$methodName($field, $data); + } + else { + $result = $this->model->getDataTableOptions($this->fieldName, $field, $data); + } + + if (!is_array($result)) { + $result = []; + } + + return $result; + } + +} diff --git a/modules/backend/formwidgets/datatable/partials/_datatable.htm b/modules/backend/formwidgets/datatable/partials/_datatable.htm new file mode 100644 index 000000000..cb73e4851 --- /dev/null +++ b/modules/backend/formwidgets/datatable/partials/_datatable.htm @@ -0,0 +1,8 @@ +
+ + render() ?> + +
+ From 04c6fdc7f3db5893212219d27410c2ab829ebb79 Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Sat, 3 Jan 2015 12:06:12 +1100 Subject: [PATCH 17/26] Minor --- .../table/assets/js/table.datasource.client.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/modules/backend/widgets/table/assets/js/table.datasource.client.js b/modules/backend/widgets/table/assets/js/table.datasource.client.js index edde54f1b..103649c37 100644 --- a/modules/backend/widgets/table/assets/js/table.datasource.client.js +++ b/modules/backend/widgets/table/assets/js/table.datasource.client.js @@ -25,7 +25,7 @@ if (dataString === null || dataString === undefined) throw new Error('The required data-data attribute is not found on the table control element.') - + this.data = JSON.parse(dataString) }; @@ -71,11 +71,10 @@ Client.prototype.createRecord = function(recordData, placement, relativeToKey, offset, count, onSuccess) { if (placement === 'bottom') { // Add record to the bottom of the dataset - this.data.push(recordData) - } else if (placement == 'above' || placement == 'below') { + } + else if (placement == 'above' || placement == 'below') { // Add record above or below the passed record key - var recordIndex = this.getIndexOfKey(relativeToKey) if (placement == 'below') recordIndex ++ @@ -98,8 +97,10 @@ if (recordIndex !== -1) { recordData[this.tableObj.options.keyColumn] = key this.data[recordIndex] = recordData - } else + } + else { throw new Error('Record with they key '+key+ ' is not found in the data set') + } } /* @@ -124,8 +125,10 @@ this.data.push(newRecordData) this.getRecords(offset, count, onSuccess) - } else + } + else { throw new Error('Record with they key '+key+ ' is not found in the data set') + } } Client.prototype.getIndexOfKey = function(key) { From 54adc840cbd775d4ff095183a3c7459af19eb274 Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Sat, 3 Jan 2015 12:07:04 +1100 Subject: [PATCH 18/26] Allow key column to be a string value (like a code). ping @alekseybobkov --- .../widgets/table/assets/js/table.datasource.client.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/backend/widgets/table/assets/js/table.datasource.client.js b/modules/backend/widgets/table/assets/js/table.datasource.client.js index 103649c37..d53b1c7c5 100644 --- a/modules/backend/widgets/table/assets/js/table.datasource.client.js +++ b/modules/backend/widgets/table/assets/js/table.datasource.client.js @@ -135,8 +135,8 @@ var keyColumn = this.tableObj.options.keyColumn return this.data.map(function(record) { - return record[keyColumn] - }).indexOf(parseInt(key)) + return record[keyColumn] + "" + }).indexOf(key + "") } Client.prototype.getAllData = function() { From 03bf0c8206ffaca54c75973f61718f36b5e68a00 Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Sat, 3 Jan 2015 12:33:32 +1100 Subject: [PATCH 19/26] These are useful helpers, make them public --- modules/cms/classes/Controller.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/cms/classes/Controller.php b/modules/cms/classes/Controller.php index c0ac0648c..c39348a8f 100644 --- a/modules/cms/classes/Controller.php +++ b/modules/cms/classes/Controller.php @@ -1025,7 +1025,7 @@ class Controller extends BaseController * Searches the layout and page components by an alias * @return ComponentBase The component object, if found */ - protected function findComponentByName($name) + public function findComponentByName($name) { if (isset($this->page->components[$name])) { return $this->page->components[$name]; @@ -1047,7 +1047,7 @@ class Controller extends BaseController * Searches the layout and page components by an AJAX handler * @return ComponentBase The component object, if found */ - protected function findComponentByHandler($handler) + public function findComponentByHandler($handler) { foreach ($this->page->components as $component) { if (method_exists($component, $handler)) { @@ -1068,7 +1068,7 @@ class Controller extends BaseController * Searches the layout and page components by a partial file * @return ComponentBase The component object, if found */ - protected function findComponentByPartial($partial) + public function findComponentByPartial($partial) { foreach ($this->page->components as $component) { $fileName = ComponentPartial::getFilePath($component, $partial); From fa250927d00fb9adfb1c8b48a70f87b172722631 Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Sat, 3 Jan 2015 12:51:09 +1100 Subject: [PATCH 20/26] New events for components: runAjaxHandler + beforeRunAjaxHandler --- modules/cms/classes/ComponentBase.php | 32 +++++++++++++++++++++++++++ modules/cms/classes/Controller.php | 4 ++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/modules/cms/classes/ComponentBase.php b/modules/cms/classes/ComponentBase.php index 84113a359..e62d38260 100644 --- a/modules/cms/classes/ComponentBase.php +++ b/modules/cms/classes/ComponentBase.php @@ -2,6 +2,7 @@ use Str; use Lang; +use Event; use Config; use Cms\Classes\CodeBase; use Cms\Classes\CmsException; @@ -167,6 +168,37 @@ abstract class ComponentBase extends Extendable return $this->alias; } + /** + * Executes the event cycle when running an AJAX handler. + * @return boolean Returns true if the handler was found. Returns false otherwise. + */ + public function runAjaxHandler($handler) + { + /* + * Extensibility + */ + if ( + ($event = $this->fireEvent('component.beforeRunAjaxHandler', [$handler], true)) || + ($event = Event::fire('cms.component.beforeRunAjaxHandler', [$this, $handler], true)) + ) { + return $event; + } + + $result = $this->$handler(); + + /* + * Extensibility + */ + if ( + ($event = $this->fireEvent('component.runAjaxHandler', [$handler, $result], true)) || + ($event = Event::fire('cms.component.runAjaxHandler', [$this, $handler, $result], true)) + ) { + return $event; + } + + return $result; + } + // // External properties // diff --git a/modules/cms/classes/Controller.php b/modules/cms/classes/Controller.php index c39348a8f..0ff69bdc3 100644 --- a/modules/cms/classes/Controller.php +++ b/modules/cms/classes/Controller.php @@ -538,7 +538,7 @@ class Controller extends BaseController if ($componentObj && method_exists($componentObj, $handlerName)) { $this->componentContext = $componentObj; - $result = $componentObj->$handlerName(); + $result = $componentObj->runAjaxHandler($handlerName); return ($result) ?: true; } } @@ -561,7 +561,7 @@ class Controller extends BaseController */ if (($componentObj = $this->findComponentByHandler($handler)) !== null) { $this->componentContext = $componentObj; - $result = $componentObj->$handler(); + $result = $componentObj->runAjaxHandler($handler); return ($result) ?: true; } } From be702900d7df556bf910c7c0d5c6efd7dc9422c8 Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Sat, 3 Jan 2015 13:20:40 +1100 Subject: [PATCH 21/26] Rem debug code --- modules/backend/formwidgets/DataTable.php | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/backend/formwidgets/DataTable.php b/modules/backend/formwidgets/DataTable.php index 2b00ce688..c41b0f03a 100644 --- a/modules/backend/formwidgets/DataTable.php +++ b/modules/backend/formwidgets/DataTable.php @@ -88,7 +88,6 @@ class DataTable extends FormWidgetBase { $dataSource = $this->table->getDataSource(); $records = $this->getLoadData() ?: []; - traceLog($records); $dataSource->initRecords((array) $records); } From ae8289735c7cb956aaf2bf748535654a84944929 Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Sat, 3 Jan 2015 15:15:52 +1100 Subject: [PATCH 22/26] Rem unneeded file --- .../richeditor/assets/css/iframe.css | 207 ------------------ 1 file changed, 207 deletions(-) delete mode 100644 modules/backend/formwidgets/richeditor/assets/css/iframe.css diff --git a/modules/backend/formwidgets/richeditor/assets/css/iframe.css b/modules/backend/formwidgets/richeditor/assets/css/iframe.css deleted file mode 100644 index 20406e352..000000000 --- a/modules/backend/formwidgets/richeditor/assets/css/iframe.css +++ /dev/null @@ -1,207 +0,0 @@ -html { - margin: 0; - padding: 0; -} -body { - margin: 0; - padding: 10px; - font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif; - color: #333; -} - -code, -pre { - font-family: Menlo, Monaco, monospace, sans-serif; -} - -div, -p, -ul, -ol, -table, -dl, -blockquote, -td, -th, -pre { - font-size: 14px; - line-height: 1.5rem; -} -div { - border: 1px dashed #bbb !important; -} -a { - color: #15c; - text-decoration: underline; -} -.redactor_placeholder { - color: #999 !important; - display: block !important; - margin-bottom: 10px !important; -} - -object, -embed, -video, -img { - max-width: 100%; - width: auto; -} -video, -img { - height: auto; -} - -div, -p, -ul, -ol, -table, -dl, -blockquote, -pre { - margin: 0; - margin-bottom: 15px; - border: none; - background: none; - box-shadow: none; -} -iframe, -object, -hr { - margin-bottom: 15px; -} -blockquote { - margin-left: 3em; - color: #777; - font-style: italic; -} -ul, -ol { - padding-left: 2em; -} -ul ul, -ol ol, -ul ol, -ol ul { - margin: 2px; - padding: 0; - padding-left: 2em; - border: none; -} -dl dt { font-weight: bold; } -dd { margin-left: 1em;} - -table { - border-collapse: collapse; - font-size: 1em; -} -table td { - padding: 5px; - border: 1px solid #ddd; - vertical-align: top; -} -table thead td { - border-bottom: 2px solid #000; - font-weight: bold; -} -code { - background-color: #d8d7d7; -} -pre { - overflow: auto; - padding: 1em; - border: 1px solid #ddd; - border-radius: 3px; - background: #f8f8f8; - white-space: pre; - font-size: 90%; -} -hr { - display: block; - height: 1px; - border: 0; - border-top: 1px solid #ccc; -} - -h1, -h2, -h3, -h4, -h5 { - margin: 0; - padding: 0; - background: none; - color: #333; - font-weight: bold; -} - -h1 { - margin-bottom: 10px; - font-size: 36px; - line-height: 40px; -} -h2 { - margin-bottom: 15px; - font-size: 30px; - line-height: 38px; -} -h3 { - margin-bottom: 10px; - font-size: 24px; - line-height: 30px; -} -h4 { - margin-bottom: 10px; - font-size: 18px; - line-height: 24px; -} -h5 { - margin-bottom: 10px; - font-size: 1em; -} -table { - width: 100%; -} - -body.redactor_editor_wym { - background: #f4f4f4; -} -.redactor_editor_wym div, -.redactor_editor_wym p, -.redactor_editor_wym ul, -.redactor_editor_wym ol, -.redactor_editor_wym table, -.redactor_editor_wym dl, -.redactor_editor_wym pre, -.redactor_editor_wym h1, -.redactor_editor_wym h2, -.redactor_editor_wym h3, -.redactor_editor_wym h4, -.redactor_editor_wym h5, -.redactor_editor_wym blockquote { - margin: 0 0 10px 0; - padding: 7px 10px; - border: 1px solid #e4e4e4; - background-color: #fff; -} -.redactor_editor_wym div { - border: 1px dashed #bbb !important; -} -.redactor_editor_wym pre { - border: 2px dashed #e4e4e4 !important; - background-color: #fafafa !important; -} -.redactor_editor_wym code { - background-color: #f4f4f4 !important; -} -.redactor_editor_wym ul, -.redactor_editor_wym ol { - padding-left: 2em !important; -} -.redactor_editor_wym ul li ul, -.redactor_editor_wym ul li ol, -.redactor_editor_wym ol li ol, -.redactor_editor_wym ol li ul { - border: none !important; -} From df3e66246f0a33148354a6cce92db01ed71da96e Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Sat, 3 Jan 2015 15:15:57 +1100 Subject: [PATCH 23/26] Fixes #839 - When rendering partials from component PHP code, be firm about the context --- modules/cms/classes/ComponentBase.php | 10 ++++++++++ modules/cms/classes/Controller.php | 28 +++++++++++++++++++++------ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/modules/cms/classes/ComponentBase.php b/modules/cms/classes/ComponentBase.php index e62d38260..1c6dcd60b 100644 --- a/modules/cms/classes/ComponentBase.php +++ b/modules/cms/classes/ComponentBase.php @@ -168,6 +168,16 @@ abstract class ComponentBase extends Extendable return $this->alias; } + /** + * Renders a requested partial in context of this component, + * see Cms\Classes\Controller@renderPartial for usage. + */ + public function renderPartial() + { + $this->controller->setComponentContext($this); + return call_user_func_array([$this->controller, 'renderPartial'], func_get_args()); + } + /** * Executes the event cycle when running an AJAX handler. * @return boolean Returns true if the handler was found. Returns false otherwise. diff --git a/modules/cms/classes/Controller.php b/modules/cms/classes/Controller.php index 0ff69bdc3..50c18ebcf 100644 --- a/modules/cms/classes/Controller.php +++ b/modules/cms/classes/Controller.php @@ -84,11 +84,6 @@ class Controller extends BaseController */ protected $pageContents; - /** - * @var string Alias name of an executing component. - */ - protected $componentContext; - /** * @var array A list of variables to pass to the page. */ @@ -99,8 +94,19 @@ class Controller extends BaseController */ protected $statusCode = 200; + /** + * @var self Cache of self + */ protected static $instance = null; + /** + * @var Cms\Classes\ComponentBase Object of the active component, used internally. + */ + protected $componentContext; + + /** + * @var array Component partial stack, used internally. + */ protected $partialComponentStack = []; /** @@ -701,7 +707,7 @@ class Controller extends BaseController } elseif (($componentObj = $this->findComponentByPartial($partialName)) === null) { if ($throwException) { - throw new CmsException(Lang::get('cms::lang.partial.not_found', ['name'=>$name])); + throw new CmsException(Lang::get('cms::lang.partial.not_found', ['name'=>$partialName])); } else { return false; @@ -1095,6 +1101,16 @@ class Controller extends BaseController return null; } + /** + * Set the component context manually, used by Components when calling renderPartial. + * @param ComponentBase $component + * @return void + */ + public function setComponentContext(ComponentBase $component) + { + $this->componentContext = $component; + } + /** * Sets component property values from partial parameters. * The property values should be defined as {{ param }}. From c1e065d580b7f4df92bdd023f36f21c929faf66e Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Sat, 3 Jan 2015 15:27:18 +1100 Subject: [PATCH 24/26] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 997c3606f..a7c277ca8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ * **Build 17x** (2014-12-xx) - Improved asset caching (`cms.enableAssetCache`), when enabled the server will send a *304 Not Modified* header. + - Introduced new *Table* widget and *DataTable* form widget. + - There is now a simpler way for sending mail via `Mail::sendTo()`. * **Build 171** (2014-12-17) - Add new methods `propertyName()` and `paramName()` to Component base class for accessing names of external properties. From 85b97c5419dce9ffcb446433bfc9f2876e848260 Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Sat, 3 Jan 2015 15:48:07 +1100 Subject: [PATCH 25/26] Refs #850 - Minor code clean --- modules/backend/formwidgets/DatePicker.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/backend/formwidgets/DatePicker.php b/modules/backend/formwidgets/DatePicker.php index dc9cc3ccd..1e283aaff 100644 --- a/modules/backend/formwidgets/DatePicker.php +++ b/modules/backend/formwidgets/DatePicker.php @@ -126,7 +126,8 @@ class DatePicker extends FormWidgetBase return null; } - if ($this->mode == 'datetime' && $timeValue = post(self::TIME_PREFIX.$this->formField->getName(false))) { + $timeValue = post(self::TIME_PREFIX . $this->formField->getName(false)); + if ($this->mode == 'datetime' && $timeValue) { $value .= ' ' . $timeValue . ':00'; } elseif ($this->mode == 'time') { From 31eae5b94059eb93d89982f39493993509e02e24 Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Sat, 3 Jan 2015 16:00:13 +1100 Subject: [PATCH 26/26] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7c277ca8..e3a4630a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ - Improved asset caching (`cms.enableAssetCache`), when enabled the server will send a *304 Not Modified* header. - Introduced new *Table* widget and *DataTable* form widget. - There is now a simpler way for sending mail via `Mail::sendTo()`. + - The List Filter query can now be extended with controller override `listFilterExtendQuery()`. * **Build 171** (2014-12-17) - Add new methods `propertyName()` and `paramName()` to Component base class for accessing names of external properties.