Float replies that aren't a solution, but are important, within a topic
Saw a Product Idea for this, so I thought I'd share my custom solution. Perhaps not for the faint of heart, but when you get it working it'll be fun :)
This adds an option to all the replies in a topic, which lets you float them to the top. Like Solutions, but not marked as such. Sometimes you want to float a reply to make it easier to find and stand out, without implying that it's a solution.
Looks like this:
You will need three things for this:
- Component that shows the floated reply
- Option in the reply's message options to float it
- Endpoint to make the magic work
And they are these:
One:
(I removed my CSS, but just reply here if you'd like to have it and I'll send it over. It'd just take a lot of space here).
<#assign topic_id = page.context.message.uniqueId/> <#-- insert your preferred method of testing a user's role here --> if user has role: <#assign usercanUnfloat = true/> else <#assign usercanUnfloat = false/> /if <#-- ask Lithium to add a metadata field for messages --> <#assign float_ids = restadmin("/messages/id/${topic_id}/metadata/key/spotify.floated_replies").value/> <#if float_ids != ""> <#-- if this topic has floated replies --> <#list float_ids?split(",") as msg_id> <#if msg_id != ""> <#assign query_msg = restadmin("2.0","/search?q=" + "SELECT view_href,author.id,author.login,current_revision.last_edit_time,search_snippet,body FROM messages WHERE id = '${msg_id}'"?url) /> <#list query_msg.data.items as q> <#assign author_id = q.author.id/> <#assign author_login = q.author.login/> <#assign msg_url = q.view_href/> <#assign msg_post_time_date = q.current_revision.last_edit_time?number_to_datetime?datetime?string[cust_user_date_format]/> <#assign msg_post_time_time = q.current_revision.last_edit_time?number_to_datetime?datetime?string[cust_user_time_format]/> <#attempt> <#assign msg_body = q.search_snippet/> <#recover> <#assign msg_body = q.body/> </#attempt> <#assign query_author = restadmin("2.0","/search?q=" + "SELECT view_href,rank,avatar.message FROM users WHERE id = '${author_id}'"?url) /> <#list query_author.data.items as a> <#assign author_url = a.view_href/> <#assign author_avatar = a.avatar.message/> <#assign author_rank_name = a.rank.name/> <#if a.rank.bold == true> <#assign author_rank_bold = "bold"/> <#else> <#assign author_rank_bold = "normal"/> </#if> <#assign author_rank_color = a.rank.color/> <#attempt> <#assign author_rank_icon_url = a.rank.icon_left/> <#assign show_icon = true/> <#recover> <#assign show_icon = false/> </#attempt> <div class="cust-floater-container"> <div class="cust-floater-message"> <div class="lia-quilt-column lia-quilt-column-24 lia-quilt-column-single lia-quilt-column-header-content"> <div class="lia-quilt-column-alley lia-quilt-column-alley-single"> <div class="lia-message-author-avatar lia-component-user-avatar"> <div class="UserAvatar lia-user-avatar lia-component-common-widget-user-avatar"> <a class="UserAvatar lia-link-navigation" tabindex="-1" target="_self" href="${author_url}"><img class="lia-user-avatar-message" title="${author_login}" alt="${author_login}" src="${author_avatar}"></a> </div> </div> <div class="lia-message-author-username lia-component-user-name"> <span class="UserName lia-user-name lia-user-rank-${author_rank_name?replace(' ','-')}"> <a class="lia-link-navigation lia-page-link lia-user-name-link" style="color:#${author_rank_color}" target="_self" href="${author_url}"><span class="">${author_login}</span></a> </span> </div> <div class="lia-message-author-rank lia-component-author-rank-name">${author_rank_name}</div> <p class="lia-message-dates lia-message-post-date lia-component-post-date-last-edited"> <span class="DateTime lia-message-posted-on lia-component-common-widget-date"> <span class="local-date">${msg_post_time_date}</span> <span class="local-time">${msg_post_time_time}</span> </span> </p> <#-- button to let users un-float this reply --> <#if usercanUnfloat == true> <div class="lia-message-unfloat"> <#-- create an endpoint that will edit the topic's metadata field and remove the id of this floated reply --> <a class="lia-link-navigation lia-page-link" href="ENDPOINT_URL_HERE?msgId=${msg_id}&topicId=${topic_id}&do=remove&url=${http.request.url}">Un-Float as Top Answer</a> </div> </#if> </div> </div> <div class="lia-message-body-wrapper lia-component-message-view-widget-body"> <div id="bodydisplay" class="lia-message-body"> <div class="lia-message-body-content"> ${msg_body} </div> </div> <#-- the floated reply shows a snippet, just in case the floated reply is one looong post. This links to the full reply. --> <div class="cust-readmore"><a href="${msg_url}">Read more</a></div> </div> </div> </div> </#list> </#list> </#if> </#list> </#if>
Two:
(I added this to the Forum Topic Page and the Idea Page. You might need to tweak the JavaScript to work with your specific layout and classes)
<#-- insert your preferred method of testing a user's role here --> <#-- if user has role: --> <#if userIsAdminMod == true> <#attempt> <#assign topic_id = page.context.message.uniqueId/> <#assign float_ids = restadmin("/messages/id/${topic_id}/metadata/key/spotify.floated_replies").value/> <@liaAddScript> <#if float_ids == ""> var arFloats = new Array(); <#else> var arFloats = [${float_ids?trim}]; </#if> $(document).ready(function() { $(".lia-component-reply-list .lia-message-view, .CommentList .lia-message-view").each(function () { var obj_msg = $(this); var obj_href = obj_msg.attr('class'); var UidIndex = obj_href.indexOf("message-uid-"); if(UidIndex != -1) { UidIndex = UidIndex + 12; var msg_id = obj_href.slice(UidIndex, obj_href.length); } else { var msg_id = 0; } if(arFloats.indexOf(parseInt(msg_id)) == -1) { var action_do = 'add'; var action_text = 'Float'; } else { var action_do = 'remove'; var action_text = 'Un-Float'; } var obj_add = '<li><a class="lia-link-navigation cust-action-float-message" rel="nofollow" href="/spotify/plugins/custom/spotify/spotify/end_float_reply?msgId=' + msg_id + '&topicId=${topic_id}&do=' + action_do +'&url=${http.request.url}">' + action_text + ' as Top Answer</a></li>' + '<li class="cust-item-float-sep" aria-hidden="true"><span class="lia-separator lia-component-common-widget-link-separator"><span class="lia-separator-post"></span><span class="lia-separator-pre"></span></span></li>'; obj_msg.find(".lia-component-forums-action-highlight-message").each(function() { obj_menu_item = $(this).parent('li'); obj_menu_item.before( obj_add ); }); }); }); </@liaAddScript> <#recover> </#attempt> </#if>
Three:
(The endpoint that makes it all work. Turned out smaller than I thought it would).
<#-- insert your preferred method of testing a user's role here --> <#-- if user has role: --> <#if userIsAdminMod == true> <#assign status = ""/> <#assign msg_id = http.request.parameters.name.get("msgId", "")?string /> <#assign topic_id = http.request.parameters.name.get("topicId", "")?string /> <#assign action = http.request.parameters.name.get("do", "")?string /> <#assign return_url = http.request.parameters.name.get("url", "")?string /> <#if msg_id != "" && topic_id != "" && action != ""> <#assign float_ids = restadmin("/messages/id/${topic_id}/metadata/key/spotify.floated_replies").value/> <#assign float_ids_seq = []/> <#if action == "add"> <#if float_ids == ""> <#assign float_ids_new = msg_id/> <#else> <#list float_ids?split(",") as f_id> <#if f_id != "" && f_id?number != msg_id?number> <#assign float_ids_seq = float_ids_seq + [f_id]/> </#if> </#list> <#assign float_ids_seq = float_ids_seq + [msg_id]/> <#if (float_ids_seq?size > 2)> <#assign float_ids_seq_new = []/> <#list float_ids_seq?reverse as f_id> <#if (f_id_index < 2)> <#assign float_ids_seq_new = float_ids_seq_new + [f_id]/> </#if> </#list> <#assign float_ids_new = float_ids_seq_new?join(",")/> <#else> <#assign float_ids_new = float_ids_seq?join(",")/> </#if> </#if> <#elseif action == "remove"> <#list float_ids?split(",")?reverse as f_id> <#if f_id != "" && f_id?number != msg_id?number> <#assign float_ids_seq = float_ids_seq + [f_id]/> </#if> </#list> <#if (float_ids_seq?size > 0)> <#assign float_ids_new = float_ids_seq?join(",")/> <#else> <#assign float_ids_new = ""/> </#if> </#if> <#if float_ids_new??> <#assign result = restadmin("/messages/id/${topic_id}/metadata/key/spotify.floated_replies/set?value=${float_ids_new}")/> </#if> </#if> <script> <#if result?? && result.error?has_content> history.replaceState( {} , 'Float Message', '${return_url}' ); window.history.back(); <#else> history.replaceState( {} , 'Float Message', '${return_url}' ); window.history.back(); </#if> </script> </#if>