Question

Photo of Michael Garrison

2

Accessing group information with Liquid for person profile badges

I'm sure there's a way to do what I want to with the person profile badges, but I've hit a wall with trying to pick my way through the Liquid attributes.

Here's the short version: we have five classes that we offer (membership, growing, etc) and we'd like to show a badge on each profile indicating whether they've completed the class.

So I set up a group type of "Class Container", whose sub-groups are of type "Classes", with purpose "Class". The "Classes" groups have Roles of "Expressed Interest", "Signed up", and "Graduate", as well as a Member Attribute of "Class Date". Then I created a container group, and five child groups within it - one for each class.

So far, so good.

Now, there's no badge of type "In specific group" (may I suggest an addition?), so the only option besides using Liquid appeared to be to change the setup and have a different group TYPE for each class so I could use the "In group of type" badge type. That seems awfully clunky- if we wanted to change roles for instance, we'd have to do it five times. And since ideally I'd like to color the icon based on which of the three roles the person "held" in the class, I started looking at the Liquid badge type.

I managed to find Person.Members and iterate the groups they were members of, and establish that the first of the five classes is group with Id of 68 (and with that, the GUID of the group). In this case, Liquid reported

[Id, 68][Guid, d345226f-2cf4-4a6a-893b-512b9ad721df][Classdate, 3/22/2014 (3days)][Classdate_unformatted, 3/22/2014]

But I couldn't seem to use that Id in the Liquid conditional statement to have the icon render properly. Copying built-in badges like Baptism, I tried

{% if Person.Members.Id[68] != empty -%}
                    <div class="badge">
                        <i class="badge-icon fa fa-road" style="color:blue"></i>
                    </div>
                {% else -%}
                    <div class="badge">
                        <i class="badge-icon badge-disabled fa fa-road"></i>
                    </div>
                {% endif -%}

and then tried other conditionals like Person.Members.68, Person.Members.Id.68 and other combinations I could come up with. I also can't find out whether Liquid has access to the "Roles" a person might hold within the group.

Can anyone help me out with the syntax I need to be using, or do I just need to be patient and wait for the Liquid frameword documentation within Rock to be completed?

Thanks

Badges
  • Photo of Jon Edmiston

    0

    I think you may need to create a custom badge for this type of need. Even if you could get everything through the Liquid badge it would generate numerous SQL calls as you iterate through the object graph.

  • Photo of Jon Edmiston

    1

    I think a new badge type of "InGroup" would be the best bet. We could have a setting for the 'DefaultIconColor' and then another setting where you could add role specific colors in the format of {RoleId}|{Color} (e.g. '12|#c4c4c4,34|#267262').  How does that sound?  

  • Photo of Michael Garrison

    1

    Ken,

    Start by creating the person attributes ("Admin Tools" -> "General Settings" -> "Person Attributes"). The "Key" field in my example would be the "ClassOneDate", "ClassTwoDate" etc that you see me programmatically reference - make it anything (unique) you want, but remember what it is- you'll have to use it again later when you're making the badge! I made the Field Type a date, and put them in the "Membership" category, but you can do it however you want. Make a separate attribute for each class.

    Now make the badge ("Admin Tools" -> "General Settings" -> "Person Profile Badges") and make a single new badge. Set the "Badge Type" to "Liquid" and use my codes above as a starting point to copy-n-paste into the "Display Text" field. (replace < with a left bracket and > with a right bracket- it looks like this forum messed up the display of what I pasted). If you have more or fewer than six attributes, then add or remove some number of "if" clauses. Be sure to adjust the style="left:nn%" section of each output - the numbers I used were the best fit for getting six icons to fit across a badge. Also adjust the "size:16%" style to make them larger or smaller as you wish.

    Once the badge is created, view a person's profile. Now click the "blocks" button on the admin toolbar at the bottom of your window, roll over the section to which you wish to add your multi-badge, click the settings gear and check the box next to your custom badge. Then reload the page to see your badge show up.

    Let me know if you have issues with this, and be sure to keep an eye on this thread in case Jon warns us that this isn't advised!

  • Photo of Michael Garrison

    1

    Ken,

    I missed one item and wasn't clear on another, sorry. I should have told you to replace & with an ampersand as well (shift+7), and when I said brackets, I meant shift+, and shift+.

    Check out this snippet to see how it should appear:codesample.png

    Hope that helps!

  • Photo of Michael Garrison

    1

    Ken,

    The ROCK team uses the site's css to bring in Font Awesome for easy rendering of all their icons (and enables us as users to use them too). You can find all the codes here:

    http://fortawesome.github.io/Font-Awesome/icons/

    To your other question, yes you can make the badge look like whatever you want- you're just using liquid conditionals in order for the CMS to know what HTML to output. It's going to be a lot easier if you know HTML, but you might look at something like this (untested) code:

    <div class="badge" style="position:relative;">
      <div style="height:50%;width:20%;border:1px solid black;position:absolute;top:0px;left:0%;background-color:{% if Person.ClassOneDate != empty -%}green{% else -%}antiquewhite{% endif -%}"></div>
      <div style="height:50%;width:20%;border:1px solid black;position:absolute;top:0px;left:20%;background-color:{% if Person.ClassTwoDate != empty -%}green{% else -%}antiquewhite{% endif -%}"></div>
      <div style="height:50%;width:20%;border:1px solid black;position:absolute;top:0px;left:40%;background-color:{% if Person.ClassThreeDate != empty -%}green{% else -%}antiquewhite{% endif -%}"></div>
      <div style="height:50%;width:20%;border:1px solid black;position:absolute;top:0px;left:60%;background-color:{% if Person.ClassFourDate != empty -%}green{% else -%}antiquewhite{% endif -%}"></div>
      <div style="height:50%;width:20%;border:1px solid black;position:absolute;top:0px;left:80%;background-color:{% if Person.ClassFiveDate != empty -%}green{% else -%}antiquewhite{% endif -%}"></div>
      <div style="height:50%;width:20%;border:1px solid black;position:absolute;bottom:0px;left:0%;background-color:{% if Person.OtherOneDate != empty -%}blue{% else -%}antiquewhite{% endif -%}"></div>
      <div style="height:50%;width:20%;border:1px solid black;position:absolute;bottom:0px;left:20%;background-color:{% if Person.OtherTwoDate != empty -%}blue{% else -%}antiquewhite{% endif -%}"></div>
      <div style="height:50%;width:20%;border:1px solid black;position:absolute;bottom:0px;left:40%;background-color:{% if Person.OtherThreeDate != empty -%}blue{% else -%}antiquewhite{% endif -%}"></div>
      <div style="height:50%;width:20%;border:1px solid black;position:absolute;bottom:0px;left:60%;background-color:{% if Person.OtherFourDate != empty -%}blue{% else -%}antiquewhite{% endif -%}"></div>
      <div style="height:50%;width:20%;border:1px solid black;position:absolute;bottom:0px;left:80%;background-color:{% if Person.OtherFiveDate != empty -%}blue{% else -%}antiquewhite{% endif -%}"></div>
     </div>

    This renders something similar to your second example- two rows of 5 columns, in this case. To keep the code simple, the borders are going to be a little different than you've rendered, but it may be close enough for your use. You could look at using specific widths in pixels instead of using percentages - I think with the square default badge shape, you may be looking at the boxes being a little too dense without a little expansion.

    Look up a good HTML5 and/or CSS tutorial though- you're going to find it much easier to design these liquid badges if you understand the HTML you're putting out.

  • Photo of Michael Garrison

    0

    As a direct answer to my initial desire, yes that would do very nicely. I wonder if a badge that robust will be useful to more people than just my case, and whether it could be executed simply enough that people who didn't need the {RoleId}|{Color} feature would not be intimidated. Of course, maybe the color and icon of each role is actually a property of the role, rather than being defined in the badge. But anyway, those decisions are yours to make =)

    If it's not too presumptous, I'll persist in my other inquiry though: whether this data is/will be exposed to Liquid. Because in the meantime, I've started playing with what I'm privately calling a "multibadge", where a single "badge" could indicate states of multiple groups - almost certainly all within a single parent group or at least with a shared "purpose" parameter:

    multibadge.png
    (this way I'm not having to take up the space of 6 badges to communicate some very related data)

    Although I obviously don't have the liquid conditionals set up right now, I've mocked this up using the following markup in a single Liquid badge:

    <div class="badge" style="position:relative;">
    	<i class="badge-icon fa fa-road" style="color:#000;"></i>
    	<i class="fa fa-square-o alert-danger" title="Class 1" style="position:absolute;size:16%;left:0%;bottom:0px;"></i>
    	<i class="fa fa-check-square-o alert-success" title="Class 2" style="position:absolute;size:16%;bottom:0px;left:17%;"></i>
    	<i class="fa fa-square-o alert-danger" title="Class 3" style="position:absolute;size:16%;bottom:0px;left:34%;"></i>
    	<i class="fa fa-square-o alert-danger" title="Class 4" style="position:absolute;size:16%;bottom:0px;left:51%;"></i>
    	<i class="fa fa-square-o alert-danger" title="Class 5" style="position:absolute;size:16%;bottom:0px;left:68%;"></i>
    	<i class="fa fa-check-square-o alert-success" title="Class 6" style="position:absolute;size:16%;bottom:0px;left:85%;"></i>
    </div>

    Now, I'm not asking for something like this to built-in; I have to imagine that something this custom is probably best left to Liquid-type badges, but I'm curious whether the necessary properties are or will be exposed to Liquid to make it possible.

    Thanks for all the work you and your team have put into this exciting project!

  • Photo of Michael Garrison

    0

    I'm assuming documentation for creating custom badges will come later- that sounds pretty significant.

    In the meantime, this thead made me consider a slightly less-powerful option (since it doesn't support roles) using custom attributes instead of groups, which allows me to build exactly the badge I showed above with this code:

    <div class="badge" style="position:relative;">
         <i class="badge-icon fa fa-road" style="color:#000;"></i>
         {% if Person.ClassOneDate != empty -%}
             <i class="fa fa-check-square-o alert-success" title="{{ Person.NickName }} took the &amp;quot;First&amp;quot; class on {{ Person.ClassOneDate }}." style="cursor:default;position:absolute;size:16%;left:0%;bottom:0px;"></i>
         {% else -%}
             <i class="fa fa-square-o alert-danger" title="{{ Person.NickName }} has not taken the &amp;quot;First&amp;quot; class." style="cursor:default;position:absolute;size:16%;left:0%;bottom:0px;"></i>
         {% endif -%}
         {% if Person.ClassTwoDate != empty -%}
             <i class="fa fa-check-square-o alert-success" title="{{ Person.NickName }} took the &amp;quot;Second&amp;quot; class on {{ Person.ClassTwoDate }}." style="cursor:default;position:absolute;size:16%;left:17%;bottom:0px;"></i>
         {% else -%}
             <i class="fa fa-square-o alert-danger" title="{{ Person.NickName }} has not taken the &amp;quot;Second&amp;quot; class." style="cursor:default;position:absolute;size:16%;left:17%;bottom:0px;"></i>
         {% endif -%}
         {% if Person.ClassThreeDate != empty -%}
             <i class="fa fa-check-square-o alert-success" title="{{ Person.NickName }} took the &amp;quot;Third&amp;quot; class on {{ Person.ClassThreeDate }}." style="cursor:default;position:absolute;size:16%;left:34%;bottom:0px;"></i>
         {% else -%}
             <i class="fa fa-square-o alert-danger" title="{{ Person.NickName }} has not taken the &amp;quot;Third&amp;quot; class." style="cursor:default;position:absolute;size:16%;left:34%;bottom:0px;"></i>
         {% endif -%}
         {% if Person.ClassFourDate != empty -%}
             <i class="fa fa-check-square-o alert-success" title="{{ Person.NickName }} took the &amp;quot;Fourth&amp;quot; class on {{ Person.ClassFourDate }}." style="cursor:default;position:absolute;size:16%;left:51%;bottom:0px;"></i>
         {% else -%}
             <i class="fa fa-square-o alert-danger" title="{{ Person.NickName }} has not taken the &amp;quot;Fourth&amp;quot; class." style="cursor:default;position:absolute;size:16%;left:51%;bottom:0px;"></i>
         {% endif -%}
         {% if Person.ClassFiveDate != empty -%}
             <i class="fa fa-check-square-o alert-success" title="{{ Person.NickName }} took the &amp;quot;Fifth&amp;quot; class on {{ Person.ClassFiveDate }}." style="cursor:default;position:absolute;size:16%;left:68%;bottom:0px;"></i>
         {% else -%}
             <i class="fa fa-square-o alert-danger" title="{{ Person.NickName }} has not taken the &amp;quot;Fifth&amp;quot; class." style="cursor:default;position:absolute;size:16%;left:68%;bottom:0px;"></i>
         {% endif -%}
         {% if Person.ClassSixDate != empty -%}
             <i class="fa fa-check-square-o alert-success" title="{{ Person.NickName }} took the &amp;quot;Sixth&amp;quot; class on {{ Person.ClassSixDate }}." style="cursor:default;position:absolute;size:16%;left:85%;bottom:0px;"></i>
         {% else -%}
             <i class="fa fa-square-o alert-danger" title="{{ Person.NickName }} has not taken the &amp;quot;Sixth&amp;quot; class." style="cursor:default;position:absolute;size:16%;left:85%;bottom:0px;"></i>
         {% endif -%}
     </div>

    Is this ill-advised due to the number of SQL queries like you were afraid of with the groups? I assume this is no "heavier" than having 6 separate badges...

    Thanks!

    • Ken Roach

      Michael, I'm trying to copy what you've done. Where/how do I add the additional badge icons?

  • Photo of Ken Roach

    0

    Thanks for your helpful reply, Michael.  I added the same fields as yours as Person Attributes:ClassOneDate, ClassTwoDate...  Replaced "&lt;" with "(" and "&gt;" with ")" in the badge display code.  The following now displays on the screen.  What have I missed?  Do I need to add the badge icons "fa fa-check-square-o alert-success" and "fa fa-square-o alert-danger" somewhere?

    badge-4.JPG

  • Photo of Ken Roach

    0

    Brilliant.  Works now!  Badges are awesome.
    Out of curiosity - where is the "badge-icon fa fa-road" coming from?  Literally, where is it stored?  Where is the class code defined?  Can other classes of badges be written like this?  How could the "fa-road" be replaced with a similar "progress bar" badge of a different design? Even a very basic design, like this:

    badge-5.JPG

    What about a multi level one, containing two progress lines?  One line for things like, "Has attended class 1, 2, 3 etc", the other line for things like, "Has accepted Christ, Done Foundations Course, Is Baptised, Is in Life Group, Is in Serving Group."  I.e. compressing a range of what might be shown in individual badges into one summary badge.

    badge-6.JPG

     

  • Photo of Don Smallman

    0

    What if I just want to create a new badge to display a new extended atribute I just created?