Changes for page Message Sender Macro
Last modified by superadmin on 2017/11/28 14:52
From empty
To version 1.1
edited by superadmin
on 2017/11/28 14:52
on 2017/11/28 14:52
Change comment: Install extension [org.xwiki.platform:xwiki-platform-messagestream-ui/9.9]
Summary
-
Page properties (5 modified, 0 added, 0 removed)
-
Objects (0 modified, 6 added, 0 removed)
Details
- Page properties
-
- Title
-
... ... @@ -1,0 +1,1 @@ 1 +Message Sender Macro - Parent
-
... ... @@ -1,0 +1,1 @@ 1 +Main.WebHome - Author
-
... ... @@ -1,1 +1,1 @@ 1 - XWiki.XWikiGuest1 +xwiki:XWiki.superadmin - Hidden
-
... ... @@ -1,1 +1,1 @@ 1 - false1 +true - Content
-
... ... @@ -1,0 +1,1 @@ 1 +{{messageSender/}}
- XWiki.JavaScriptExtension[0]
-
- Caching policy
-
... ... @@ -1,0 +1,1 @@ 1 +long - Code
-
... ... @@ -1,0 +1,138 @@ 1 +#set ($userSuggestScope = 'local') 2 +#if ($services.wiki.user && $services.wiki.user.userScope != "LOCAL_ONLY") 3 + #set ($userSuggestScope = 'global') 4 +#end 5 +var XWiki = (function (XWiki) { 6 +// Start XWiki augmentation. 7 +/** 8 + * Extends the UserPicker in order to display the selected user/group inline after the target text input. 9 + */ 10 +var CustomUserPicker = Class.create(XWiki.widgets.UserPicker, { 11 + // @Override 12 + _createSelectionManager: function($super, options) { 13 + var selectionManager = $super(Object.extend(options, { 14 + listInsertionPosition : 'after', 15 + acceptFreeText : false 16 + })); 17 + // Overwrite the way the selected item is displayed. 18 + selectionManager.displayItem = function(suggestion) { 19 + var targetInfo = new Element('span').update(suggestion.info).insert(this.createDeleteTool()); 20 + var targetClass = this.suggest.sources[0].script.indexOf('uorg=group') > 0 ? 'target-group' : 'target-user'; 21 + return new Element('li', {'class': targetClass}).insert(targetInfo).insert(this.createItemInput(suggestion)); 22 + }.bind(selectionManager); 23 + return selectionManager; 24 + } 25 +}); 26 + 27 +XWiki.MessageStream = Class.create({ 28 + targetsWithName : ['user', 'group'], 29 + suggestParameters : { 30 + user : { 31 + script: '$doc.getURL("get", "xpage=uorgsuggest&uorg=user&wiki=${userSuggestScope}")&', 32 + noresults: "$escapetool.javascript($services.localization.render('core.widgets.userPicker.noResults'))" 33 + }, 34 + group : { 35 + script: "$doc.getURL('get', 'xpage=uorgsuggest&uorg=group')&", 36 + noresults: "$escapetool.javascript($services.localization.render('core.widgets.groupPicker.noResults'))" 37 + } 38 + }, 39 + initialize : function() { 40 + this.prepareForms(); 41 + this.enhanceSelect(); 42 + }, 43 + prepareTargetInput : function(event, element) { 44 + var targetType = element.options[element.selectedIndex].value; 45 + element.className = targetType; 46 + if (!element.__targetNameInput) {return;} 47 + if (this.targetsWithName.indexOf(targetType) < 0) { 48 + element.__targetNameInput.addClassName('hidden'); 49 + if (element.__targetNameInput.__x_suggest) { 50 + element.__targetNameInput.__x_suggest.detach(); 51 + } 52 + } else { 53 + // Focus the text input so that the place-holder value is cleared if present. Otherwise the user picker will treat 54 + // the place-holder value as if it was typed by the user and will automatically select the corresponding suggestion. 55 + element.__targetNameInput.removeClassName('hidden').activate(); 56 + // Defer the creation of the user picker to allow the focus listeners to be called first (in order to clear the 57 + // place-holder value). 58 + this.suggestParameters[targetType] && function() { 59 + new CustomUserPicker(element.__targetNameInput, this.suggestParameters[targetType]); 60 + }.bind(this).defer(); 61 + } 62 + }, 63 + enhanceSelect: function () { 64 + $$('.messagestream select[name="visibilityLevel"]').each(function(element) { 65 + element.addClassName(element.options[element.selectedIndex].value); 66 + element.__targetNameInput = element.up('.messagestream').down('input[name="targetName"]'); 67 + if (element.__targetNameInput && this.targetsWithName.indexOf(element.options[element.selectedIndex].value) < 0) { 68 + element.__targetNameInput.addClassName('hidden'); 69 + } 70 + element.observe('change', this.prepareTargetInput.bindAsEventListener(this, element)); 71 + this.prepareTargetInput(null, element); 72 + }.bind(this)); 73 + }, 74 + prepareForms: function() { 75 + $$('.messagestream form').each(function(msForm) { 76 + msForm.action = msForm.action.replace(/xredirect=.*$/, 'xpage=plain') 77 + msForm.observe('submit', function(event) { 78 + event.stop(); 79 + if (msForm._disabled == true || msForm.down('textarea').value.strip() == '') { 80 + return; 81 + } 82 + new Ajax.Request( 83 + msForm.action, { 84 + parameters: msForm.serialize(true), 85 + onCreate: function() { 86 + msForm._disabled = true; 87 + msForm._notification = new XWiki.widgets.Notification("$services.localization.render('xe.activity.messages.submit.inProgress')", 'inprogress'); 88 + }, 89 + onSuccess: function() { 90 + if (msForm) { 91 + msForm.messagestream_message.value = ''; 92 + } 93 + if (msForm && msForm._notification) { 94 + msForm._notification.hide(); 95 + } 96 + msForm._notification = new XWiki.widgets.Notification("$services.localization.render('xe.activity.messages.submit.success')", 'done'); 97 + 98 + document.fire('xwiki:activity:newActivity', msForm); 99 + }, 100 + onFailure: function(response) { 101 + var failureReason = ''; 102 + if (response.statusText == '' /* No response */ || response.status == 12031 /* In IE */) { 103 + failureReason = 'Server not responding'; 104 + } else { 105 + failureReason = response.statusText; 106 + } 107 + if (msForm) { 108 + msForm._disabled = false 109 + if (msForm._notification) { 110 + msForm._notification.hide(); 111 + } 112 + msForm._notification = new XWiki.widgets.Notification("$services.localization.render('xe.activity.messages.submit.failed'): " + failureReason, 'error'); 113 + } 114 + }, 115 + on1223 : function(response) { /*SUCCESS*/ 116 + response.request.options.onSuccess(response); 117 + }, 118 + on0 : function(response) { /*FAILURE*/ 119 + response.request.options.onFailure(response); 120 + }, 121 + onComplete: function() { 122 + msForm._disabled = false; 123 + }.bind(this) 124 + } 125 + ); 126 + }.bindAsEventListener(this)); 127 + }.bind(this)); 128 + } 129 +}); 130 + 131 +var init = function() { 132 + return new XWiki.MessageStream(); 133 +}; 134 +(XWiki.domIsLoaded && init()) || document.observe('xwiki:dom:loaded', init); 135 + 136 +// End XWiki augmentation. 137 +return XWiki; 138 +}(XWiki || {})); - Name
-
... ... @@ -1,0 +1,1 @@ 1 +User status update - Parse content
-
... ... @@ -1,0 +1,1 @@ 1 +Yes - Use this extension
-
... ... @@ -1,0 +1,1 @@ 1 +onDemand
- XWiki.StyleSheetExtension[0]
-
- Caching policy
-
... ... @@ -1,0 +1,1 @@ 1 +long - Code
-
... ... @@ -1,0 +1,29 @@ 1 +#template('colorThemeInit.vm') 2 + 3 +.messagestream-tools { 4 + position: relative; 5 + margin: .5em 0 1em; 6 +} 7 +.messagestream-tools .accepted-suggestions { 8 + display: inline; 9 +} 10 +.messagestream-tools .accepted-suggestions .target-user, 11 +.messagestream-tools .accepted-suggestions .target-group { 12 + background: none no-repeat scroll left center transparent; 13 + display: inline-block; 14 + margin-right: 1em; 15 + padding: 0 1px 0 18px; 16 +} 17 +.messagestream-tools .accepted-suggestions .target-user { 18 + background-image: url("$xwiki.getSkinFile('icons/silk/user.png')"); 19 +} 20 +.messagestream-tools .accepted-suggestions .target-group { 21 + background-image: url("$xwiki.getSkinFile('icons/silk/group.png')"); 22 +} 23 +.messagestream select { 24 + width: auto; 25 +} 26 +.messagestream input.targetName { 27 + margin-right: .3em; 28 + width: auto; 29 +} - Content Type
-
... ... @@ -1,0 +1,1 @@ 1 +CSS - Name
-
... ... @@ -1,0 +1,1 @@ 1 +Message stream form styling - Parse content
-
... ... @@ -1,0 +1,1 @@ 1 +Yes - Use this extension
-
... ... @@ -1,0 +1,1 @@ 1 +onDemand
- XWiki.WikiMacroClass[0]
-
- Macro code
-
... ... @@ -1,0 +1,185 @@ 1 +{{velocity output='false'}} 2 +#* Duplicate code (from Main.Activity) START *# 3 +## 4 +## User status configuration 5 +## ------------------------------------------------------------- 6 +#set ($config = 'XWiki.MessageStreamConfig') 7 +#set ($configClass = $xwiki.getDocument($config).getxWikiClass()) 8 +#set ($isMessageStreamActive = $services.messageStream.isActive()) 9 + 10 +#set ($currentUser = $services.model.serialize($xcontext.userReference, 'default')) 11 + 12 +#set ($activityActionsMap = { 13 + 'publicMessage': 'icons/silk/user_comment.png', 14 + 'personalMessage': 'icons/silk/user_comment.png', 15 + 'directMessage': 'icons/silk/user_go.png', 16 + 'groupMessage': 'icons/silk/group_go.png' 17 +}) 18 +## 19 +#** 20 + * Display user avatar and action message 21 + *# 22 +#macro(activitySnapshot $eventUser $eventType) 23 + <span class='activitySnapshot'> 24 + #if ($eventUser != 'XWiki.XWikiGuest') 25 + <a href="$xwiki.getURL($eventUser)">#smallUserAvatar("$!eventUser")</a> 26 + #else 27 + #smallUserAvatar("$!eventUser") 28 + #end 29 + <img class='activityActionAvatar' src="$xwiki.getSkinFile($activityActionsMap.get($eventType), true)" alt="$services.localization.render("xe.activity.action.${eventType}", [$relatedEventsNo])" title="$services.localization.render("xe.activity.action.${eventType}", [$relatedEventsNo])" /> 30 + </span> 31 +#end 32 +## 33 +#* Duplicate code END *# 34 +## 35 +## Skin Extensions 36 +##-------------------------------------------------------------- 37 +#set ($discard = $xwiki.jsfx.use('uicomponents/suggest/suggestPicker.js')) 38 +#set ($discard = $xwiki.jsfx.use('uicomponents/widgets/userpicker/userPicker.js')) 39 +#set ($discard = $xwiki.ssx.use('Main.Activity')) 40 +#set ($discard = $xwiki.ssx.use('Main.MessageSenderMacro')) 41 +#set ($discard = $xwiki.jsx.use('Main.MessageSenderMacro')) 42 +{{/velocity}} 43 + 44 +{{velocity}} 45 +#if ($isMessageStreamActive) 46 + #set ($xredirect = $doc.getURL($xcontext.action, $!{request.queryString})) 47 + #set ($errorMessageKeyPrefix = "messageSender.post.error.") 48 + #set ($errorMessage = $request.session.getAttribute("${errorMessageKeyPrefix}${xredirect}")) 49 + #if ("$!errorMessage" != '') 50 + ## Clean the error and display the message. 51 + #set ($discard = $request.session.removeAttribute("${errorMessageKeyPrefix}${xredirect}")) 52 + {{error}}$errorMessage{{/error}} 53 + 54 + ## 55 + ## Handle postMessage action here so that the macro can be self contained. 56 + ## 57 + #elseif ("$!{request.xaction}" != '') 58 + #if ("$!{request.xaction}" == 'postMessage') 59 + #if(!$services.csrf.isTokenValid(${request.form_token})) 60 + #set($redirectURL = $services.csrf.getResubmissionURL()) 61 + $response.sendRedirect($redirectURL) 62 + #else 63 + #set ($message = "$!{request.messagestream_message.trim()}") 64 + #if ($message == '') 65 + ## Do nothing with empty messages 66 + #if ("$!{request.xredirect}" != '') 67 + $response.sendRedirect(${request.xredirect}) 68 + #end 69 + #else 70 + #set ($success = false) 71 + #if (!$isGuest) 72 + #set ($messageType = "$!{request.visibilityLevel}") 73 + #if ($messageType == 'everyone') 74 + #set ($success = $services.messageStream.postPublicMessage($message)) 75 + #elseif ($messageType == 'followers') 76 + #set ($success = $services.messageStream.postPersonalMessage($message)) 77 + #elseif ($messageType == 'group') 78 + #set ($success = $services.messageStream.postMessageToGroup($message, $services.model.resolveDocument("$!{request.targetName}"))) 79 + #elseif ($messageType == 'user') 80 + #set ($success = $services.messageStream.postDirectMessageToUser($message, $services.model.resolveDocument("$!{request.targetName}"))) 81 + #end 82 + #end 83 + #if (!$success) 84 + #if ($request.xpage == 'plain') 85 + #if ($isGuest) 86 + $response.setStatus(401)## Unauthorized 87 + #else 88 + $response.setStatus(403)## Forbidden 89 + #end 90 + $services.localization.render('xe.activity.messages.submit.failed') 91 + #elseif ("$!{request.xredirect}" != '') 92 + ## Pass the error message in the xredirect so that we display it in the calling page and not in the macro page. 93 + $request.session.setAttribute("${errorMessageKeyPrefix}${request.xredirect}", $services.localization.render('xe.activity.messages.submit.failed')) 94 + $response.sendRedirect($request.xredirect) 95 + #else 96 + {{error}}$services.localization.render('xe.activity.messages.submit.failed'){{/error}} 97 + 98 + #end 99 + #elseif ("$!{request.xredirect}" != '') 100 + $response.sendRedirect(${request.xredirect}) 101 + #elseif ($request.xpage == 'plain') 102 + ## Just print something for confirmation. 103 + $services.localization.render('xe.activity.messages.submit.success') 104 + #end 105 + #end 106 + #end 107 + #end 108 + #end 109 + ## 110 + ## Display the UI. Don't display it for AJAX calls and guests. 111 + ## 112 + #if ($request.xpage != 'plain' && !$isGuest) 113 + ## When this macro is displayed in edit/inline mode, we disable the inputs and no longer display the form (because it would clash with the main form of inline edit). 114 + #set ($inEditMode = ($xcontext.action == 'inline' || $xcontext.action == 'edit')) 115 + #set ($actionQueryString = "xredirect=$escapetool.url($xredirect)") 116 + {{html}} 117 + ## Wrap the form in a div so that the layout is preserved in inline mode (where the form is stripped by the rendering). 118 + <div class='messagestream activityUser xform'> 119 + #if (!$inEditMode) 120 + <form action="${xwiki.getURL('Main.MessageSenderMacro', 'view', $!{actionQueryString})}" method='post'> 121 + #end 122 + <div class='activityContent'> 123 + #if(!$inEditMode) 124 + ## CSRF prevention 125 + <input type="hidden" name="form_token" value="$!{services.csrf.getToken()}" /> 126 + <input type='hidden' name='xaction' value='postMessage' /> 127 + #end 128 + #activitySnapshot($xcontext.user, 'personalMessage') 129 + <div class='messagestream-data'> 130 + <textarea name='messagestream_message' rows='3' cols='40'#if($inEditMode) disabled='disabled'#end></textarea> 131 + </div> 132 + <div class='messagestream-tools'> 133 + #set ($possibleTargets = $xcontext.macro.params.get('visibilityOptions').split('\s*,\s*')) 134 + #if (!$possibleTargets) 135 + #set ($possibleTargets = $configClass.get('visibilityLevel').getListValues()) 136 + #end 137 + ## 138 + #set ($targetName = $xcontext.macro.params.get('visibilityParameter')) 139 + ## 140 + #set ($defaultTarget = $xcontext.macro.params.get('visibility')) 141 + #if (!$defaultTarget) 142 + #if ($doc.getObject('XWiki.XWikiGroups')) 143 + #set ($defaultTarget = 'group') 144 + #set ($targetName = $doc.prefixedFullName) 145 + #elseif ($doc.getObject('XWiki.XWikiUsers')) 146 + #if ($doc.prefixedFullName == $currentUser) 147 + #set ($defaultTarget = 'followers') 148 + #else 149 + #set ($defaultTarget = 'user') 150 + #set ($targetName = $doc.prefixedFullName) 151 + #end 152 + #else 153 + #set ($defaultTarget = 'everyone') 154 + #end 155 + #end 156 + <label>$services.localization.render('xe.activity.messages.visibility') 157 + <select name='visibilityLevel'#if($inEditMode) disabled='disabled'#end> 158 + #foreach ($target in $possibleTargets) 159 + <option value="${target}"#if ($defaultTarget == $target) selected='selected'#end>$services.localization.render("XWiki.MessageStreamConfig_visibilityLevel_${target}")</option> 160 + #end 161 + </select> 162 + </label> 163 + <label for="targetName$!{targetNameCounter}"> 164 + <span class='hidden'>Name:</span> 165 + <input type="text" name="targetName" id="targetName$!targetNameCounter" class="targetName withTip useTitleAsTip" value="$!targetName" size="15" 166 + title="$services.localization.render('xe.activity.messages.visibility.targetName.tip')" #if ($inEditMode) disabled="disabled"#end/> 167 + </label> 168 + #if (!$targetNameCounter) 169 + #set ($targetNameCounter = 1) 170 + #else 171 + #set ($targetNameCounter = $targetNameCounter + 1) 172 + #end 173 + </div> 174 + <div class='messagestream-buttons'> 175 + <span class='butonwrapper'><input type='submit' value="$services.localization.render('xe.activity.messages.submit')" class='button'#if($inEditMode) disabled='disabled'#end/></span> 176 + </div> 177 + </div> 178 + #if (!$inEditMode) 179 + </form> 180 + #end 181 + </div> 182 + {{/html}} 183 + #end 184 +#end 185 +{{/velocity}} - Macro content type
-
... ... @@ -1,0 +1,1 @@ 1 +No content - Default category
-
... ... @@ -1,0 +1,1 @@ 1 +Social - Macro description
-
... ... @@ -1,0 +1,1 @@ 1 +A control that allows users to enter messages that are handled by the MessageStream module. - Macro id
-
... ... @@ -1,0 +1,1 @@ 1 +messageSender - Macro name
-
... ... @@ -1,0 +1,1 @@ 1 +Message Sender - Supports inline mode
-
... ... @@ -1,0 +1,1 @@ 1 +No - Macro visibility
-
... ... @@ -1,0 +1,1 @@ 1 +Current Wiki
- XWiki.WikiMacroParameterClass[0]
-
- Parameter description
-
... ... @@ -1,0 +1,5 @@ 1 +Default selected visibility when the macro is displayed. 2 + 3 +If not specified, it is determined automatically based on the page where the macro is used. 4 + 5 +Valid values are: 'everyone', 'followers', 'group' or 'user'. - Parameter name
-
... ... @@ -1,0 +1,1 @@ 1 +visibility
- XWiki.WikiMacroParameterClass[1]
-
- Parameter description
-
... ... @@ -1,0 +1,1 @@ 1 +Some visibility levels (like 'user' and 'group') accept a parameter. In the case of the 2 mentioned levels, the value can be a serialized reference of a user or a group document. - Parameter name
-
... ... @@ -1,0 +1,1 @@ 1 +visibilityParameter
- XWiki.WikiMacroParameterClass[2]
-
- Parameter description
-
... ... @@ -1,0 +1,3 @@ 1 +Comma separated list of visibility options that the macro should allow the user to choose from. 2 + 3 +This list should be a sublist of the defualt ones: 'everyone', 'followers', 'group', 'user'. - Parameter name
-
... ... @@ -1,0 +1,1 @@ 1 +visibilityOptions