Ticket #8519: 8519.patch
| File 8519.patch, 28.4 KB (added by , 4 years ago) |
|---|
-
Gruntfile.js
diff --git Gruntfile.js Gruntfile.js index 16635088d..bb010cd0c 100644
module.exports = function( grunt ) { 39 39 '!bp-groups/css/blocks/group.css', 40 40 '!bp-members/css/blocks/members.css', 41 41 '!bp-groups/css/blocks/groups.css', 42 '!bp-core/css/blocks/login-form.css' 42 '!bp-core/css/blocks/login-form.css', 43 '!bp-activity/css/blocks/latest-activities.css' 43 44 ], 44 45 45 46 autoprefixer = require('autoprefixer'); … … module.exports = function( grunt ) { 158 159 flatten: true, 159 160 src: ['bp-core/sass/blocks/*.scss'], 160 161 dest: SOURCE_DIR + 'bp-core/css/blocks/' 162 }, 163 activity_blocks: { 164 cwd: SOURCE_DIR, 165 extDot: 'last', 166 expand: true, 167 ext: '.css', 168 flatten: true, 169 src: ['bp-activity/sass/blocks/*.scss'], 170 dest: SOURCE_DIR + 'bp-activity/css/blocks/' 161 171 } 162 172 }, 163 173 rtlcss: { -
src/bp-activity/bp-activity-blocks.php
diff --git src/bp-activity/bp-activity-blocks.php src/bp-activity/bp-activity-blocks.php index 116badd6a..fcaf9d4c1 100644
11 11 if ( ! defined( 'ABSPATH' ) ) { 12 12 exit; 13 13 } 14 15 /** 16 * Callback function to render the Latest Activities Block. 17 * 18 * @since 9.0.0 19 * 20 * @param array $attributes The block attributes. 21 * @return string HTML output. 22 */ 23 function bp_activity_render_latest_activities_block( $attributes = array() ) { 24 $block_args = wp_parse_args( 25 $attributes, 26 array( 27 'title' => __( 'Latest updates', 'buddypress' ), 28 'maxActivities' => 5, 29 'type' => array( 'activity_update' ), 30 'postId' => 0, 31 ) 32 ); 33 34 $max_activities = (int) $block_args['maxActivities']; 35 36 // Should we get a specific member's activities? 37 $member_id = 0; 38 if ( $block_args['postId'] ) { 39 $member_id = (int) get_post_field( 'post_author', $block_args['postId'] ); 40 } else { 41 $member_id = bp_displayed_user_id(); 42 } 43 44 // Set the widget's wrapper attributes. 45 $types = (array) $block_args['type']; 46 $classnames = array_map( 'sanitize_html_class', array_merge( $types, array( 'bp-latest-activities', 'buddypress', 'widget' ) ) ); 47 $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => implode( ' ', $classnames ) ) ); 48 49 // Set the Block's title. 50 $widget_content = sprintf( '<h2 class="widget-title">%s</h2>', esc_html( $block_args['title'] ) ); 51 52 // Avoid conflicts with other activity loops. 53 $reset_activities_template = null; 54 if ( ! empty( $GLOBALS['activities_template'] ) ) { 55 $reset_activities_template = $GLOBALS['activities_template']; 56 } 57 58 $widget_args = array( 59 'max' => $max_activities, 60 'scope' => 'all', 61 'user_id' => $member_id, 62 'object' => false, 63 'action' => implode( ',', $types ), 64 'primary_id' => 0, 65 'secondary_id' => 0, 66 ); 67 68 // Build the activity loop. 69 if ( 'nouveau' === bp_get_theme_compat_id() ) { 70 $bp_nouveau = bp_nouveau(); 71 72 // Globalize the activity widget arguments. 73 $bp_nouveau->activity->widget_args = $widget_args; 74 75 ob_start(); 76 bp_get_template_part( 'activity/widget' ); 77 $widget_content .= ob_get_clean(); 78 79 // Reset the global. 80 $bp_nouveau->activity->widget_args = array(); 81 } else { 82 $activity_loop = sprintf( '<div class="widget-error"><p>%s</p></div>', esc_html__( 'Sorry, there was no activity found. Please try a different filter.', 'buddypress' ) ); 83 84 if ( bp_has_activities( $widget_args ) ) { 85 $activity_loop = ''; 86 87 while ( bp_activities() ) { 88 bp_the_activity(); 89 90 $activity_footer = ''; 91 $activity_classes = 'activity-item'; 92 if ( bp_activity_has_content() ) { 93 $activity_content = bp_get_activity_content_body(); 94 $activity_footer = sprintf( 95 '<footer> 96 <cite> 97 <a href="%1$s" class="bp-tooltip" data-bp-tooltip="%2$s"> 98 %3$s 99 </a> 100 </cite> 101 %4$s 102 </footer>', 103 bp_get_activity_user_link(), 104 bp_get_activity_member_display_name(), 105 bp_get_activity_avatar( 106 array( 107 'type' => 'thumb', 108 'width' => '40', 109 'height' => '40', 110 ) 111 ), 112 bp_insert_activity_meta() 113 ); 114 } else { 115 $activity_classes .= ' mini'; 116 $activity_content = bp_get_activity_action(); 117 } 118 119 $activity_loop .= sprintf( 120 '<blockquote> 121 <div class="%1$s">%2$s</div> 122 %3$s 123 </blockquote>', 124 $activity_classes, 125 $activity_content, 126 $activity_footer 127 ); 128 } 129 } 130 131 $widget_content .= sprintf( 132 '<div class="activity-list item-list"> 133 %1$s 134 </div>', 135 $activity_loop 136 ); 137 } 138 139 // Adds a container to make sure the block is styled even when used into the Columns parent block. 140 $widget_content = sprintf( '<div class="bp-latest-activities-block">%s</div>', "\n" . $widget_content . "\n" ); 141 142 // Reset the global template loop. 143 $GLOBALS['activities_template'] = $reset_activities_template; 144 145 // Only add a block wrapper if not loaded into a Widgets sidebar. 146 if ( ! did_action( 'dynamic_sidebar_before' ) ) { 147 return sprintf( 148 '<div %1$s>%2$s</div>', 149 $wrapper_attributes, 150 $widget_content 151 ); 152 } 153 154 return $widget_content; 155 } -
src/bp-activity/classes/class-bp-activity-component.php
diff --git src/bp-activity/classes/class-bp-activity-component.php src/bp-activity/classes/class-bp-activity-component.php index 398550378..d54966b49 100644
class BP_Activity_Component extends BP_Component { 207 207 'search_string' => __( 'Search Activity...', 'buddypress' ), 208 208 'global_tables' => $global_tables, 209 209 'meta_tables' => $meta_tables, 210 'block_globals' => array( 211 'bp/latest-activities' => array( 212 'widget_classnames' => array( 'wp-block-bp-latest-activities', 'buddypress' ), 213 ) 214 ), 210 215 ); 211 216 212 217 parent::setup_globals( $args ); … … class BP_Activity_Component extends BP_Component { 483 488 * description. 484 489 */ 485 490 public function blocks_init( $blocks = array() ) { 486 parent::blocks_init( 487 array( 488 'bp/embed-activity' => array( 489 'name' => 'bp/embed-activity', 490 'editor_script' => 'bp-embed-activity-block', 491 'editor_script_url' => plugins_url( 'js/blocks/embed-activity.js', dirname( __FILE__ ) ), 492 'editor_script_deps' => array( 493 'wp-blocks', 494 'wp-element', 495 'wp-i18n', 496 'wp-components', 497 'wp-block-editor', 498 'wp-data', 499 'wp-compose', 500 'bp-block-data', 491 $blocks = array( 492 'bp/latest-activities' => array( 493 'name' => 'bp/latest-activities', 494 'editor_script' => 'bp-latest-activities-block', 495 'editor_script_url' => plugins_url( 'js/blocks/latest-activities.js', dirname( __FILE__ ) ), 496 'editor_script_deps' => array( 497 'wp-blocks', 498 'wp-element', 499 'wp-components', 500 'wp-i18n', 501 'wp-block-editor', 502 'bp-block-data', 503 'bp-block-components', 504 ), 505 'style' => 'bp-latest-activities-block', 506 'style_url' => plugins_url( 'css/blocks/latest-activities.css', dirname( __FILE__ ) ), 507 'attributes' => array( 508 'title' => array( 509 'type' => 'string', 510 'default' => __( 'Latest updates', 'buddypress' ), 511 ), 512 'maxActivities' => array( 513 'type' => 'number', 514 'default' => 5, 515 ), 516 'type' => array( 517 'type' => 'array', 518 'default' => array( 'activity_update' ), 519 ), 520 'postId' => array( 521 'type' => 'number', 522 'default' => 0, 501 523 ), 502 524 ), 503 ) 525 'render_callback' => 'bp_activity_render_latest_activities_block', 526 ), 504 527 ); 528 529 if ( bp_is_active( $this->id, 'embeds' ) ) { 530 $blocks['bp/embed-activity'] = array( 531 'name' => 'bp/embed-activity', 532 'editor_script' => 'bp-embed-activity-block', 533 'editor_script_url' => plugins_url( 'js/blocks/embed-activity.js', dirname( __FILE__ ) ), 534 'editor_script_deps' => array( 535 'wp-blocks', 536 'wp-element', 537 'wp-i18n', 538 'wp-components', 539 'wp-block-editor', 540 'wp-data', 541 'wp-compose', 542 'bp-block-data', 543 ), 544 ); 545 } 546 547 parent::blocks_init( $blocks ); 505 548 } 506 549 } -
new file src/bp-activity/css/blocks/latest-activities-rtl.css
diff --git src/bp-activity/css/blocks/latest-activities-rtl.css src/bp-activity/css/blocks/latest-activities-rtl.css new file mode 100644 index 000000000..7eaa9c840
- + 1 .bp-latest-activities .components-flex.components-select-control select[multiple] { 2 height: auto; 3 padding: 0 8px; 4 } 5 6 .bp-latest-activities .components-flex.components-select-control select[multiple] + .components-input-control__suffix svg { 7 display: none; 8 } 9 10 .bp-latest-activities-block a, 11 .entry .entry-content .bp-latest-activities-block a { 12 border: none; 13 text-decoration: none; 14 } 15 16 .bp-latest-activities-block .activity-list.item-list blockquote { 17 padding: 0; 18 border: none; 19 } 20 21 .bp-latest-activities-block .activity-list.item-list blockquote .activity-item:not(.mini) { 22 position: relative; 23 box-shadow: -1px 0 4px rgba(0, 0, 0, 0.15); 24 padding: 0 1em; 25 } 26 27 .bp-latest-activities-block .activity-list.item-list blockquote .activity-item:not(.mini):after, .bp-latest-activities-block .activity-list.item-list blockquote .activity-item:not(.mini):before { 28 position: absolute; 29 right: 15px; 30 display: block; 31 width: 0; 32 height: 0; 33 border-style: solid; 34 border-color: transparent; 35 content: ""; 36 } 37 38 .bp-latest-activities-block .activity-list.item-list blockquote .activity-item:not(.mini):before { 39 bottom: -18px; 40 border-top-color: rgba(0, 0, 0, 0.15); 41 border-width: 9px; 42 right: 14px; 43 } 44 45 .bp-latest-activities-block .activity-list.item-list blockquote .activity-item:not(.mini):after { 46 bottom: -16px; 47 border-top-color: #fff; 48 border-width: 8px; 49 } 50 51 .bp-latest-activities-block .activity-list.item-list blockquote .activity-item.mini .avatar { 52 display: inline-block; 53 width: 20px; 54 height: 20px; 55 vertical-align: middle; 56 margin-left: 2px; 57 } 58 59 .bp-latest-activities-block .activity-list.item-list footer { 60 display: flex; 61 align-items: center; 62 } 63 64 .bp-latest-activities-block .activity-list.item-list footer img.avatar { 65 display: inline-block; 66 border: none; 67 margin-left: 0.5em; 68 } 69 70 .bp-latest-activities-block .activity-list.item-list footer .activity-time-since { 71 font-size: 90%; 72 } 73 74 .bp-latest-activities-block .widget-error { 75 border-right: solid 4px #0b80a4; 76 box-shadow: -1px 0 4px rgba(0, 0, 0, 0.15); 77 } 78 79 .bp-latest-activities-block .widget-error p { 80 padding: 0 1em; 81 } -
new file src/bp-activity/css/blocks/latest-activities.css
diff --git src/bp-activity/css/blocks/latest-activities.css src/bp-activity/css/blocks/latest-activities.css new file mode 100644 index 000000000..63759731c
- + 1 .bp-latest-activities .components-flex.components-select-control select[multiple] { 2 height: auto; 3 padding: 0 8px; 4 } 5 6 .bp-latest-activities .components-flex.components-select-control select[multiple] + .components-input-control__suffix svg { 7 display: none; 8 } 9 10 .bp-latest-activities-block a, 11 .entry .entry-content .bp-latest-activities-block a { 12 border: none; 13 text-decoration: none; 14 } 15 16 .bp-latest-activities-block .activity-list.item-list blockquote { 17 padding: 0; 18 border: none; 19 } 20 21 .bp-latest-activities-block .activity-list.item-list blockquote .activity-item:not(.mini) { 22 position: relative; 23 box-shadow: 1px 0 4px rgba(0, 0, 0, 0.15); 24 padding: 0 1em; 25 } 26 27 .bp-latest-activities-block .activity-list.item-list blockquote .activity-item:not(.mini):after, .bp-latest-activities-block .activity-list.item-list blockquote .activity-item:not(.mini):before { 28 position: absolute; 29 left: 15px; 30 display: block; 31 width: 0; 32 height: 0; 33 border-style: solid; 34 border-color: transparent; 35 content: ""; 36 } 37 38 .bp-latest-activities-block .activity-list.item-list blockquote .activity-item:not(.mini):before { 39 bottom: -18px; 40 border-top-color: rgba(0, 0, 0, 0.15); 41 border-width: 9px; 42 left: 14px; 43 } 44 45 .bp-latest-activities-block .activity-list.item-list blockquote .activity-item:not(.mini):after { 46 bottom: -16px; 47 border-top-color: #fff; 48 border-width: 8px; 49 } 50 51 .bp-latest-activities-block .activity-list.item-list blockquote .activity-item.mini .avatar { 52 display: inline-block; 53 width: 20px; 54 height: 20px; 55 vertical-align: middle; 56 margin-right: 2px; 57 } 58 59 .bp-latest-activities-block .activity-list.item-list footer { 60 display: flex; 61 align-items: center; 62 } 63 64 .bp-latest-activities-block .activity-list.item-list footer img.avatar { 65 display: inline-block; 66 border: none; 67 margin-right: 0.5em; 68 } 69 70 .bp-latest-activities-block .activity-list.item-list footer .activity-time-since { 71 font-size: 90%; 72 } 73 74 .bp-latest-activities-block .widget-error { 75 border-left: solid 4px #0b80a4; 76 box-shadow: 1px 0 4px rgba(0, 0, 0, 0.15); 77 } 78 79 .bp-latest-activities-block .widget-error p { 80 padding: 0 1em; 81 } -
new file src/bp-activity/js/blocks/latest-activities.js
diff --git src/bp-activity/js/blocks/latest-activities.js src/bp-activity/js/blocks/latest-activities.js new file mode 100644 index 000000000..614751c24
- + 1 // modules are defined as an array 2 // [ module function, map of requires ] 3 // 4 // map of requires is short require name -> numeric require 5 // 6 // anything defined in a previous bundle is accessed via the 7 // orig method which is the require for previous bundles 8 parcelRequire = (function (modules, cache, entry, globalName) { 9 // Save the require from previous bundle to this closure if any 10 var previousRequire = typeof parcelRequire === 'function' && parcelRequire; 11 var nodeRequire = typeof require === 'function' && require; 12 13 function newRequire(name, jumped) { 14 if (!cache[name]) { 15 if (!modules[name]) { 16 // if we cannot find the module within our internal map or 17 // cache jump to the current global require ie. the last bundle 18 // that was added to the page. 19 var currentRequire = typeof parcelRequire === 'function' && parcelRequire; 20 if (!jumped && currentRequire) { 21 return currentRequire(name, true); 22 } 23 24 // If there are other bundles on this page the require from the 25 // previous one is saved to 'previousRequire'. Repeat this as 26 // many times as there are bundles until the module is found or 27 // we exhaust the require chain. 28 if (previousRequire) { 29 return previousRequire(name, true); 30 } 31 32 // Try the node require function if it exists. 33 if (nodeRequire && typeof name === 'string') { 34 return nodeRequire(name); 35 } 36 37 var err = new Error('Cannot find module \'' + name + '\''); 38 err.code = 'MODULE_NOT_FOUND'; 39 throw err; 40 } 41 42 localRequire.resolve = resolve; 43 localRequire.cache = {}; 44 45 var module = cache[name] = new newRequire.Module(name); 46 47 modules[name][0].call(module.exports, localRequire, module, module.exports, this); 48 } 49 50 return cache[name].exports; 51 52 function localRequire(x){ 53 return newRequire(localRequire.resolve(x)); 54 } 55 56 function resolve(x){ 57 return modules[name][1][x] || x; 58 } 59 } 60 61 function Module(moduleName) { 62 this.id = moduleName; 63 this.bundle = newRequire; 64 this.exports = {}; 65 } 66 67 newRequire.isParcelRequire = true; 68 newRequire.Module = Module; 69 newRequire.modules = modules; 70 newRequire.cache = cache; 71 newRequire.parent = previousRequire; 72 newRequire.register = function (id, exports) { 73 modules[id] = [function (require, module) { 74 module.exports = exports; 75 }, {}]; 76 }; 77 78 var error; 79 for (var i = 0; i < entry.length; i++) { 80 try { 81 newRequire(entry[i]); 82 } catch (e) { 83 // Save first error but execute all entries 84 if (!error) { 85 error = e; 86 } 87 } 88 } 89 90 if (entry.length) { 91 // Expose entry point to Node, AMD or browser globals 92 // Based on https://github.com/ForbesLindesay/umd/blob/master/template.js 93 var mainExports = newRequire(entry[entry.length - 1]); 94 95 // CommonJS 96 if (typeof exports === "object" && typeof module !== "undefined") { 97 module.exports = mainExports; 98 99 // RequireJS 100 } else if (typeof define === "function" && define.amd) { 101 define(function () { 102 return mainExports; 103 }); 104 105 // <script> 106 } else if (globalName) { 107 this[globalName] = mainExports; 108 } 109 } 110 111 // Override the current require with this new one 112 parcelRequire = newRequire; 113 114 if (error) { 115 // throw error from earlier, _after updating parcelRequire_ 116 throw error; 117 } 118 119 return newRequire; 120 })({"DIzr":[function(require,module,exports) { 121 "use strict"; 122 123 Object.defineProperty(exports, "__esModule", { 124 value: true 125 }); 126 exports.default = void 0; 127 128 /** 129 * WordPress dependencies. 130 */ 131 var _wp = wp, 132 InspectorControls = _wp.blockEditor.InspectorControls, 133 _wp$components = _wp.components, 134 Disabled = _wp$components.Disabled, 135 PanelBody = _wp$components.PanelBody, 136 RangeControl = _wp$components.RangeControl, 137 SelectControl = _wp$components.SelectControl, 138 TextControl = _wp$components.TextControl, 139 _wp$element = _wp.element, 140 Fragment = _wp$element.Fragment, 141 createElement = _wp$element.createElement, 142 __ = _wp.i18n.__; 143 /** 144 * BuddyPress dependencies. 145 */ 146 147 var _bp = bp, 148 ServerSideRender = _bp.blockComponents.ServerSideRender, 149 _bp$blockData = _bp.blockData, 150 currentPostId = _bp$blockData.currentPostId, 151 activityTypes = _bp$blockData.activityTypes; 152 153 var editDynamicActivitiesBlock = function editDynamicActivitiesBlock(_ref) { 154 var attributes = _ref.attributes, 155 setAttributes = _ref.setAttributes; 156 var postId = attributes.postId, 157 maxActivities = attributes.maxActivities, 158 type = attributes.type, 159 title = attributes.title; 160 var post = currentPostId(); 161 var types = activityTypes(); 162 163 if (!postId && post) { 164 setAttributes({ 165 postId: post 166 }); 167 } 168 169 return createElement(Fragment, null, createElement(InspectorControls, null, createElement(PanelBody, { 170 title: __('Settings', 'buddypress'), 171 initialOpen: true, 172 className: "bp-latest-activities" 173 }, createElement(TextControl, { 174 label: __('Title', 'buddypress'), 175 value: title, 176 onChange: function onChange(text) { 177 setAttributes({ 178 title: text 179 }); 180 } 181 }), createElement(RangeControl, { 182 label: __('Maximum amount to display', 'buddypress'), 183 value: maxActivities, 184 onChange: function onChange(value) { 185 return setAttributes({ 186 maxActivities: value 187 }); 188 }, 189 min: 1, 190 max: 10, 191 required: true 192 }), createElement(SelectControl, { 193 multiple: true, 194 label: __('Type', 'buddypress'), 195 value: type, 196 options: types, 197 onChange: function onChange(option) { 198 setAttributes({ 199 type: option 200 }); 201 } 202 }))), createElement(Disabled, null, createElement(ServerSideRender, { 203 block: "bp/latest-activities", 204 attributes: attributes 205 }))); 206 }; 207 208 var _default = editDynamicActivitiesBlock; 209 exports.default = _default; 210 },{}],"yqpU":[function(require,module,exports) { 211 "use strict"; 212 213 Object.defineProperty(exports, "__esModule", { 214 value: true 215 }); 216 exports.default = void 0; 217 218 /** 219 * WordPress dependencies. 220 */ 221 var _wp = wp, 222 createBlock = _wp.blocks.createBlock; 223 /** 224 * Transforms Nouveau Activity Widget to Activity Block. 225 * 226 * @type {Object} 227 */ 228 229 var transforms = { 230 from: [{ 231 type: 'block', 232 blocks: ['core/legacy-widget'], 233 isMatch: function isMatch(_ref) { 234 var idBase = _ref.idBase, 235 instance = _ref.instance; 236 237 if (!(instance !== null && instance !== void 0 && instance.raw)) { 238 return false; 239 } 240 241 return idBase === 'bp_latest_activities'; 242 }, 243 transform: function transform(_ref2) { 244 var instance = _ref2.instance; 245 var regex = /i:\d*;s:\d*:"(.*?)";/gmi; 246 var types = []; 247 var matches; 248 249 while ((matches = regex.exec(instance.raw.type)) !== null) { 250 if (matches.index === regex.lastIndex) { 251 regex.lastIndex++; 252 } 253 254 matches.forEach(function (match, groupIndex) { 255 if (1 === groupIndex) { 256 types.push(match); 257 } 258 }); 259 } 260 261 return createBlock('bp/latest-activities', { 262 title: instance.raw.title, 263 maxActivities: parseInt(instance.raw.max, 10), 264 type: types 265 }); 266 } 267 }] 268 }; 269 var _default = transforms; 270 exports.default = _default; 271 },{}],"q3eE":[function(require,module,exports) { 272 "use strict"; 273 274 var _edit = _interopRequireDefault(require("./latest-activities/edit")); 275 276 var _transforms = _interopRequireDefault(require("./latest-activities/transforms")); 277 278 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 279 280 /** 281 * WordPress dependencies. 282 */ 283 var _wp = wp, 284 registerBlockType = _wp.blocks.registerBlockType, 285 __ = _wp.i18n.__; 286 /** 287 * Internal dependencies. 288 */ 289 290 registerBlockType('bp/latest-activities', { 291 title: __('Latest Activities', 'buddypress'), 292 description: __('Display the latest updates of the post author (when used into a page or post), of the displayed user (when viewing their profile) or of your community.', 'buddypress'), 293 icon: { 294 background: '#fff', 295 foreground: '#d84800', 296 src: 'buddicons-activity' 297 }, 298 category: 'buddypress', 299 attributes: { 300 title: { 301 type: 'string', 302 default: __('Latest updates', 'buddypress') 303 }, 304 maxActivities: { 305 type: 'number', 306 default: 5 307 }, 308 type: { 309 type: 'array', 310 default: ['activity_update'] 311 }, 312 postId: { 313 type: 'number', 314 default: 0 315 } 316 }, 317 edit: _edit.default, 318 transforms: _transforms.default 319 }); 320 },{"./latest-activities/edit":"DIzr","./latest-activities/transforms":"yqpU"}]},{},["q3eE"], null) 321 No newline at end of file -
new file src/bp-activity/sass/blocks/latest-activities.scss
diff --git src/bp-activity/sass/blocks/latest-activities.scss src/bp-activity/sass/blocks/latest-activities.scss new file mode 100644 index 000000000..345258ee6
- + 1 .bp-latest-activities { 2 3 .components-flex.components-select-control { 4 5 select[multiple] { 6 height: auto; 7 padding: 0 8px; 8 9 + .components-input-control__suffix svg { 10 display: none; 11 } 12 } 13 } 14 } 15 16 .bp-latest-activities-block { 17 18 a, 19 .entry .entry-content & a { 20 border: none; 21 text-decoration: none; 22 } 23 24 .activity-list.item-list { 25 26 blockquote { 27 padding: 0; 28 border: none; 29 30 .activity-item { 31 32 &:not(.mini) { 33 position: relative; 34 box-shadow: 1px 0 4px rgba(0, 0, 0, 0.15); 35 padding: 0 1em; 36 37 &:after, 38 &:before { 39 position: absolute; 40 left: 15px; 41 display: block; 42 width: 0; 43 height: 0; 44 border-style: solid; 45 border-color: transparent; 46 content: ""; 47 } 48 49 &:before { 50 bottom: -18px; 51 border-top-color: rgba(0, 0, 0, 0.15); 52 border-width: 9px; 53 left: 14px; 54 } 55 56 &:after { 57 bottom: -16px; 58 border-top-color: #fff; 59 border-width: 8px; 60 } 61 } 62 63 &.mini { 64 65 .avatar { 66 display: inline-block; 67 width: 20px; 68 height: 20px; 69 vertical-align: middle; 70 margin-right: 2px; 71 } 72 } 73 } 74 } 75 76 footer { 77 display: flex; 78 align-items: center; 79 80 img.avatar { 81 display: inline-block; 82 border: none; 83 margin-right: 0.5em; 84 } 85 86 .activity-time-since { 87 font-size: 90%; 88 } 89 } 90 } 91 92 .widget-error { 93 border-left: solid 4px #0b80a4; 94 box-shadow: 1px 0 4px rgba(0, 0, 0, 0.15); 95 96 p { 97 padding: 0 1em; 98 } 99 } 100 } -
new file src/js/bp-activity/js/blocks/latest-activities.js
diff --git src/js/bp-activity/js/blocks/latest-activities.js src/js/bp-activity/js/blocks/latest-activities.js new file mode 100644 index 000000000..11c440455
- + 1 /** 2 * WordPress dependencies. 3 */ 4 const { 5 blocks: { 6 registerBlockType, 7 }, 8 i18n: { 9 __, 10 }, 11 } = wp; 12 13 /** 14 * Internal dependencies. 15 */ 16 import editDynamicActivitiesBlock from './latest-activities/edit'; 17 import transforms from './latest-activities/transforms'; 18 19 registerBlockType( 'bp/latest-activities', { 20 title: __( 'Latest Activities', 'buddypress' ), 21 description: __( 'Display the latest updates of the post author (when used into a page or post), of the displayed user (when viewing their profile) or of your community.', 'buddypress' ), 22 icon: { 23 background: '#fff', 24 foreground: '#d84800', 25 src: 'buddicons-activity', 26 }, 27 category: 'buddypress', 28 attributes: { 29 title: { 30 type: 'string', 31 default: __( 'Latest updates', 'buddypress' ), 32 }, 33 maxActivities: { 34 type: 'number', 35 default: 5 36 }, 37 type: { 38 type: 'array', 39 default: ['activity_update'], 40 }, 41 postId: { 42 type: 'number', 43 default: 0, 44 }, 45 }, 46 edit: editDynamicActivitiesBlock, 47 transforms: transforms, 48 } ); -
new file src/js/bp-activity/js/blocks/latest-activities/edit.js
diff --git src/js/bp-activity/js/blocks/latest-activities/edit.js src/js/bp-activity/js/blocks/latest-activities/edit.js new file mode 100644 index 000000000..942874abe
- + 1 /** 2 * WordPress dependencies. 3 */ 4 const { 5 blockEditor: { 6 InspectorControls, 7 }, 8 components: { 9 Disabled, 10 PanelBody, 11 RangeControl, 12 SelectControl, 13 TextControl, 14 }, 15 element: { 16 Fragment, 17 createElement, 18 }, 19 i18n: { 20 __, 21 }, 22 } = wp; 23 24 /** 25 * BuddyPress dependencies. 26 */ 27 const { 28 blockComponents: { 29 ServerSideRender, 30 }, 31 blockData: { 32 currentPostId, 33 activityTypes, 34 } 35 } = bp; 36 37 const editDynamicActivitiesBlock = ( { attributes, setAttributes } ) => { 38 const { postId, maxActivities, type, title } = attributes; 39 const post = currentPostId(); 40 const types = activityTypes(); 41 42 if ( ! postId && post ) { 43 setAttributes( { postId: post } ); 44 } 45 46 return ( 47 <Fragment> 48 <InspectorControls> 49 <PanelBody title={ __( 'Settings', 'buddypress' ) } initialOpen={ true } className="bp-latest-activities"> 50 <TextControl 51 label={ __( 'Title', 'buddypress' ) } 52 value={ title } 53 onChange={ ( text ) => { 54 setAttributes( { title: text } ); 55 } } 56 /> 57 <RangeControl 58 label={ __( 'Maximum amount to display', 'buddypress' ) } 59 value={ maxActivities } 60 onChange={ ( value ) => 61 setAttributes( { maxActivities: value } ) 62 } 63 min={ 1 } 64 max={ 10 } 65 required 66 /> 67 <SelectControl 68 multiple 69 label={ __( 'Type', 'buddypress' ) } 70 value={ type } 71 options={ types } 72 onChange={ ( option ) => { 73 setAttributes( { type: option } ); 74 } } 75 /> 76 </PanelBody> 77 </InspectorControls> 78 <Disabled> 79 <ServerSideRender block="bp/latest-activities" attributes={ attributes } /> 80 </Disabled> 81 </Fragment> 82 ); 83 }; 84 85 export default editDynamicActivitiesBlock; -
new file src/js/bp-activity/js/blocks/latest-activities/transforms.js
diff --git src/js/bp-activity/js/blocks/latest-activities/transforms.js src/js/bp-activity/js/blocks/latest-activities/transforms.js new file mode 100644 index 000000000..e7f060625
- + 1 /** 2 * WordPress dependencies. 3 */ 4 const { 5 blocks: { 6 createBlock, 7 }, 8 } = wp; 9 10 /** 11 * Transforms Nouveau Activity Widget to Activity Block. 12 * 13 * @type {Object} 14 */ 15 const transforms = { 16 from: [ 17 { 18 type: 'block', 19 blocks: [ 'core/legacy-widget' ], 20 isMatch: ( { idBase, instance } ) => { 21 if ( ! instance?.raw ) { 22 return false; 23 } 24 25 return idBase === 'bp_latest_activities'; 26 }, 27 transform: ( { instance } ) => { 28 const regex = /i:\d*;s:\d*:"(.*?)";/gmi; 29 let types = []; 30 let matches; 31 32 while ( ( matches = regex.exec( instance.raw.type ) ) !== null ) { 33 if ( matches.index === regex.lastIndex ) { 34 regex.lastIndex++; 35 } 36 37 matches.forEach( ( match, groupIndex ) => { 38 if ( 1 === groupIndex ) { 39 types.push( match ); 40 } 41 } ); 42 } 43 44 return createBlock( 'bp/latest-activities', { 45 title: instance.raw.title, 46 maxActivities: parseInt( instance.raw.max, 10 ), 47 type: types, 48 } ); 49 }, 50 }, 51 ], 52 }; 53 54 export default transforms;