Add-on Does this add-on exist? (Profile progression)

DarkGizmo

Well-known member
Is there an add-on for Profile progression? A system that encourages members to fully fill out their profile and introduce themselves to the community?

It's harder to explain, something like "Fill out your date of birth"
"Fill out your signature"
"Add an avatar"

And each step increases your profile completion progress? That way it encourages everyone to fill out their profiles and look like a fully embedded part of the community instead of having the generic letter avatars if they don't fill one out or perhaps maybe not know where to go to do so or how to do it?
 
No plugin for 2.x that I know of. This is a template edit approach.

The result would be:

Screenshot_12.webp


Extra.less:

Code:
.block--progress
{
    .progress-bar
    {
        margin-bottom: @xf-paddingLarge;
        width:100%;
        height:30px;
        overflow:hidden;
        background: @xf-paletteAccent1;
        border-radius:@xf-borderRadiusLarge;
    }
    .progress-width
    {
        position:relative;
        float:left;
        height:100%;
        background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.125) 25%, rgba(0, 0, 0, 0) 25%, rgba(0, 0, 0, 0) 50%, rgba(255, 255, 255, 0.125) 50%, rgba(255, 255, 255, 0.125) 75%, rgba(0, 0, 0, 0) 75%, rgba(0, 0, 0, 0));
        background-size: 35px 35px;
        background-color: @xf-paletteAccent2 !important;
    }
    .progress-percent
    {
        position:absolute;
        top:50%;
        left:50%;
        transform:translate(-50%,-50%);
        margin:0;
        color:white;
    }
    .progress-complete
    {
        text-decoration: line-through;
    }
    .progress-footer
    {
        margin-top: @xf-paddingLarge;
    }
}

Then create a HTML widget, template content being:

Code:
<xf:if is="!{$xf.visitor.Profile.signature} OR !{$xf.visitor.Profile.about} OR {$xf.visitor.getAvatarType()} == 'default' OR {$xf.visitor.message_count} == '0'">
    <div class="block block--progress">
        <div class="block-container">
            <h3 class="block-minorHeader">
                Account progress
            </h3>
            <div class="block-body block-row block-row--minor">
                <xf:if is="{$xf.visitor.Profile.signature}"><xf:set var="$progressSignature" value="25"/></xf:if>
                <xf:if is="{$xf.visitor.Profile.about}"><xf:set var="$progressAbout" value="25"/></xf:if>
                <xf:if is="{$xf.visitor.getAvatarType()} != 'default'"><xf:set var="$progressAvatar" value="25"/></xf:if>
                <xf:if is="{$xf.visitor.message_count} > '0'"><xf:set var="$progressMessage" value="25"/></xf:if>

                <xf:set var="$progressFinal">{{ $progressSignature + $progressAbout + $progressAvatar + $progressMessage }}</xf:set>
                <div class="progress-bar">
                    <div class="progress-width" style="width: {$progressFinal|raw}%;">
                        <p class="progress-percent">{$progressFinal|raw}%</p>
                    </div>
                </div>
                <ul class="progress-rows listPlain">
                    <li class="{{ $xf.visitor.Profile.signature ? 'progress-complete' : 'progress-notComplete' }}"><xf:fa icon="fa-check fa-fw" /> <a href="{{ link('account/signature') }}">Setup a signature</a></li>
                    <li class="{{ $xf.visitor.Profile.about ? 'progress-complete' : 'progress-notComplete' }}"><xf:fa icon="fa-check fa-fw" /> <a href="{{ link('account/account-details') }}">Write a little about yourself</a></li>
                    <li class="{{ $xf.visitor.getAvatarType() != 'default' ? 'progress-complete' : 'progress-notComplete' }}"><xf:fa icon="fa-check fa-fw" /> <a href="{{ link('account/avatar') }}" data-xf-click="overlay">Setup an avatar</a></li>
                    <li class="{{ $xf.visitor.message_count > '0' ? 'progress-complete' : 'progress-notComplete' }}"><xf:fa icon="fa-check fa-fw" /> <a href="{{ link('forums/create-thread') }}" data-xf-click="overlay">Create a thread</a> or <a href="{{ link('whats-new') }}">reply to one</a></li>
                </ul>

                <div class="progress-footer">Having trouble? <a href="{$xf.contactUrl}" data-xf-click="{{ ($xf.options.contactUrl.overlay OR $xf.options.contactUrl.type == 'default') ? 'overlay' : '' }}">{{ phrase('contact_us') }}</a></div>
            </div>
        </div>
    </div>
</xf:if>

Make sure you check "Advanced mode". This checks for signature, about you, avatar and if they've posted a message yet.

This really should be an add-on but... it may do the trick for you for now.
 
I'm in LOVE! If I may jump on and ask another question...............
How could you set that widget up to be shown only on the "accounts" page. This way it's shown to users only when they're filling out details for their account??

Thank you a TON for this, so clean yet so powerfully functional!
 
Just don't select a location for the widget, open the template: account_wrapper.

Right below the line:

<xf:sidenav>

Add:

Code:
<xf:widget key="profile_progress" />

The key being whatever you named it in the widget.
 
Will this work under XF 2.2.x ???

I try a litle bit around with, but I cant see anything (test-account, clear profile). :unsure:

Edit:
seem to some with the template or css wrong - when i Just type in "test" in the HTML Widget Template area, then I can see it at the right positions. When I copy and paste the Template from @Russ than I cant see anything from the widget. I also try to remove the first and last line of Russ widget template code to remove the condition, but it also dont show anything.

Any hints whats wrong?


Edit: it works now - damn ash on my head a bad typo was my fault. :) Works fine at XF 2.2.x
 
Last edited:
Will this work under XF 2.2.x ???

I try a litle bit around with, but I cant see anything (test-account, clear profile). :unsure:

This add-on has most of what you would want, but there is currently no support for optional tasks.
 
Damn ...

and I have now coded it my self in over a hour work. Its not my day today. ;) Thanks for the hint and link!



Thats now my version with the code from @Russ
1635846098115.png

I have a litle bit played around with his code and extended a litle bit for my use case.

My Feature List:
  • User has set a signature
  • User has entered some about at profile
  • User has entered a value for 2 custom fields
  • User has entered a location (and so is insert at membermap)
  • User has set an avatar
  • User has created a thread
  • User has replied to a thread
Its easy extendable with more points for the progress list widget.

Widget HTML code with some comments from me for beginners to know what is to do to expand or change the code:
HTML:
<xf:if is="!{$xf.visitor.Profile.signature} <!-- checks if signatur is empty -->
    OR !{$xf.visitor.Profile.about}  <!-- checks if about text field at profils is empty-->
    OR !{$xf.visitor.Profile.custom_fields.rufname} <!-- checks if a custom userfield with filed ID rufname is empty-->
    OR !{$xf.visitor.Profile.custom_fields.meinezetor} <!-- checks if a custom userfield with filed ID meinezetor is empty-->
    OR !{$xf.visitor.Profile.location} <!-- checks if the location filed is empty-->
    OR {$xf.visitor.getAvatarType()} == 'default' <!-- checks if member hase set a own avatar or use the default one-->
    OR {$xf.visitor.message_count} == '0'"> <!-- checks if the member has wrote a post or thread. All the first lines checks all if one the points of the progress list is empty or unset. If so the Widget is viewed, if not the widget is not viewed. -->
    <div class="block block--progress">
        <div class="block-container">
            <h3 class="block-minorHeader">
                Meine ToDo Liste  <!-- Title of the Widget-->
            </h3>
            <div class="block-body block-row block-row--minor">
                <!-- If one of the point at the progress list above is not empty or set like you want, there will be set a variable with a percent value. This percent values in sum have to be 100 (100%) You can just divide 100 by the count of points in your progress list and fill in the value="xx".-->
                <xf:if is="{$xf.visitor.Profile.signature}"><xf:set var="$progressSignature" value="14"/></xf:if>
                <xf:if is="{$xf.visitor.Profile.about}"><xf:set var="$progressAbout" value="14"/></xf:if>
                <xf:if is="{$xf.visitor.Profile.custom_fields.rufname}"><xf:set var="$progressRufname" value="15"/></xf:if>
                <xf:if is="{$xf.visitor.Profile.custom_fields.meinezetor}"><xf:set var="$progressMeinezetor" value="15"/></xf:if>
                <xf:if is="{$xf.visitor.Profile.location}"><xf:set var="$progressLocation" value="14"/></xf:if>
                <xf:if is="{$xf.visitor.getAvatarType()} != 'default'"><xf:set var="$progressAvatar" value="14"/></xf:if>
                <xf:if is="{$xf.visitor.message_count} > '0'"><xf:set var="$progressMessage" value="14"/></xf:if>

                <!-- next line must contain ALL your progress list items, so the progressbar calculation will propper work -->
                <xf:set var="$progressFinal">{{ $progressSignature + $progressAbout + $progressRufname + $progressMeinezetor + $progressLocation + $progressAvatar + $progressMessage }}</xf:set>
                <div class="progress-bar">
                    <div class="progress-width" style="width: {$progressFinal|raw}%;">
                        <p class="progress-percent">{$progressFinal|raw}%</p>
                    </div>
                </div>
                <ul class="progress-rows listPlain">
                    <!-- here you generate the vissilbe part of your progress list, check that all items from are also here, I think that part is self explaining -->
                    <li class="{{ $xf.visitor.Profile.signature ? 'progress-complete' : 'progress-notComplete' }}"><xf:fa icon="fa-check fa-fw" /> <a href="{{ link('account/signature') }}">Signatur erstellen</a></li>
                    <li class="{{ $xf.visitor.Profile.about ? 'progress-complete' : 'progress-notComplete' }}"><xf:fa icon="fa-check fa-fw" /> <a href="{{ link('account/account-details') }}">Etwas über mich schreiben</a></li>
                    <li class="{{ $xf.visitor.Profile.custom_fields.rufname ? 'progress-complete' : 'progress-notComplete' }}"><xf:fa icon="fa-check fa-fw" /> <a href="{{ link('account') }}">Rufnamen eintragen</a></li>
                    <li class="{{ $xf.visitor.Profile.custom_fields.meinezetor ? 'progress-complete' : 'progress-notComplete' }}"><xf:fa icon="fa-check fa-fw" /> <a href="{{ link('account') }}">Meine Traktoren eintragen</a></li>
                    <li class="{{ $xf.visitor.Profile.location ? 'progress-complete' : 'progress-notComplete' }}"><xf:fa icon="fa-check fa-fw" /> <a href="{{ link('account') }}">In Karte eintragen</a></li>
                    <li class="{{ $xf.visitor.getAvatarType() != 'default' ? 'progress-complete' : 'progress-notComplete' }}"><xf:fa icon="fa-check fa-fw" /> <a href="{{ link('account/avatar') }}" data-xf-click="overlay">Avatar hochladen</a></li>
                    <li class="{{ $xf.visitor.message_count > '0' ? 'progress-complete' : 'progress-notComplete' }}"><xf:fa icon="fa-check fa-fw" /> <a href="{{ link('forums/create-thread') }}" data-xf-click="overlay">Thema erstellen</a> oder <a href="{{ link('whats-new') }}">antworten</a></li>
                </ul>

                <div class="progress-footer">Probleme beim benutzen des Forums? <a href="{$xf.contactUrl}" data-xf-click="{{ ($xf.options.contactUrl.overlay OR $xf.options.contactUrl.type == 'default') ? 'overlay' : '' }}">Kontaktiere uns</a></div>
            </div>
        </div>
    </div>
</xf:if>
You can simply delete all comments from me for cleaner code.
Code:
<!-- ... -->

And the Extra.less only have some litle style changes from Russ code version from above. Thats not a must have if you like Russ version.

So thanks! Russ version is cost free and easy to use. :)
 
Last edited:
Thats at the widget html code, look:

HTML:
<xf:if is="!{$xf.visitor.Profile.signature} <!-- checks if signatur is empty -->
    OR !{$xf.visitor.Profile.about}  <!-- checks if about text field at profils is empty-->
    OR !{$xf.visitor.Profile.custom_fields.rufname} <!-- checks if a custom userfield with filed ID rufname is empty-->
    OR !{$xf.visitor.Profile.custom_fields.meinezetor} <!-- checks if a custom userfield with filed ID meinezetor is empty-->
    OR !{$xf.visitor.Profile.location} <!-- checks if the location filed is empty-->
    OR {$xf.visitor.getAvatarType()} == 'default' <!-- checks if member hase set a own avatar or use the default one-->
    OR {$xf.visitor.message_count} == '0'"> <!-- checks if the member has wrote a post or thread. All the first lines checks all if one the points of the progress list is empty or unset. If so the Widget is viewed, if not the widget is not viewed. -->
  
...
  
</xf:if>
This does what you want. :)


Everything within this condition (the complete widget) will only be shown if at least one condition in your progress list does NOT fail. If all fail = 100% on the progress bar (widget is OFF) and if one fails or more, the progress bar changes = 1% - 99% (widget ON) and if nothing fails = 0% on the progress bar (widget ON).

The "!" in a condition means "is empty" or "ist not set".
 
Last edited:
Damn ...

and I have now coded it my self in over a hour work. Its not my day today. ;) Thanks for the hint and link!



Thats now my version with the code from @Russ
View attachment 259556

I have a litle bit played around with his code and extended a litle bit for my use case.

My Feature List:
  • User has set a signature
  • User has entered some about at profile
  • User has entered a value for 2 custom fields
  • User has entered a location (and so is insert at membermap)
  • User has set an avatar
  • User has created a thread
  • User has replied to a thread
Its easy extendable with more points for the progress list widget.

Widget HTML code with some comments from me for beginners to know what is to do to expand or change the code:
HTML:
<xf:if is="!{$xf.visitor.Profile.signature} <!-- checks if signatur is empty -->
    OR !{$xf.visitor.Profile.about}  <!-- checks if about text field at profils is empty-->
    OR !{$xf.visitor.Profile.custom_fields.rufname} <!-- checks if a custom userfield with filed ID rufname is empty-->
    OR !{$xf.visitor.Profile.custom_fields.meinezetor} <!-- checks if a custom userfield with filed ID meinezetor is empty-->
    OR !{$xf.visitor.Profile.location} <!-- checks if the location filed is empty-->
    OR {$xf.visitor.getAvatarType()} == 'default' <!-- checks if member hase set a own avatar or use the default one-->
    OR {$xf.visitor.message_count} == '0'"> <!-- checks if the member has wrote a post or thread. All the first lines checks all if one the points of the progress list is empty or unset. If so the Widget is viewed, if not the widget is not viewed. -->
    <div class="block block--progress">
        <div class="block-container">
            <h3 class="block-minorHeader">
                Meine ToDo Liste  <!-- Title of the Widget-->
            </h3>
            <div class="block-body block-row block-row--minor">
                <!-- If one of the point at the progress list above is not empty or set like you want, there will be set a variable with a percent value. This percent values in sum have to be 100 (100%) You can just divide 100 by the count of points in your progress list and fill in the value="xx".-->
                <xf:if is="{$xf.visitor.Profile.signature}"><xf:set var="$progressSignature" value="14"/></xf:if>
                <xf:if is="{$xf.visitor.Profile.about}"><xf:set var="$progressAbout" value="14"/></xf:if>
                <xf:if is="{$xf.visitor.Profile.custom_fields.rufname}"><xf:set var="$progressRufname" value="15"/></xf:if>
                <xf:if is="{$xf.visitor.Profile.custom_fields.meinezetor}"><xf:set var="$progressMeinezetor" value="15"/></xf:if>
                <xf:if is="{$xf.visitor.Profile.location}"><xf:set var="$progressLocation" value="14"/></xf:if>
                <xf:if is="{$xf.visitor.getAvatarType()} != 'default'"><xf:set var="$progressAvatar" value="14"/></xf:if>
                <xf:if is="{$xf.visitor.message_count} > '0'"><xf:set var="$progressMessage" value="14"/></xf:if>

                <!-- next line must contain ALL your progress list items, so the progressbar calculation will propper work -->
                <xf:set var="$progressFinal">{{ $progressSignature + $progressAbout + $progressRufname + $progressMeinezetor + $progressLocation + $progressAvatar + $progressMessage }}</xf:set>
                <div class="progress-bar">
                    <div class="progress-width" style="width: {$progressFinal|raw}%;">
                        <p class="progress-percent">{$progressFinal|raw}%</p>
                    </div>
                </div>
                <ul class="progress-rows listPlain">
                    <!-- here you generate the vissilbe part of your progress list, check that all items from are also here, I think that part is self explaining -->
                    <li class="{{ $xf.visitor.Profile.signature ? 'progress-complete' : 'progress-notComplete' }}"><xf:fa icon="fa-check fa-fw" /> <a href="{{ link('account/signature') }}">Signatur erstellen</a></li>
                    <li class="{{ $xf.visitor.Profile.about ? 'progress-complete' : 'progress-notComplete' }}"><xf:fa icon="fa-check fa-fw" /> <a href="{{ link('account/account-details') }}">Etwas über mich schreiben</a></li>
                    <li class="{{ $xf.visitor.Profile.custom_fields.rufname ? 'progress-complete' : 'progress-notComplete' }}"><xf:fa icon="fa-check fa-fw" /> <a href="{{ link('account') }}">Rufnamen eintragen</a></li>
                    <li class="{{ $xf.visitor.Profile.custom_fields.meinezetor ? 'progress-complete' : 'progress-notComplete' }}"><xf:fa icon="fa-check fa-fw" /> <a href="{{ link('account') }}">Meine Traktoren eintragen</a></li>
                    <li class="{{ $xf.visitor.Profile.location ? 'progress-complete' : 'progress-notComplete' }}"><xf:fa icon="fa-check fa-fw" /> <a href="{{ link('account') }}">In Karte eintragen</a></li>
                    <li class="{{ $xf.visitor.getAvatarType() != 'default' ? 'progress-complete' : 'progress-notComplete' }}"><xf:fa icon="fa-check fa-fw" /> <a href="{{ link('account/avatar') }}" data-xf-click="overlay">Avatar hochladen</a></li>
                    <li class="{{ $xf.visitor.message_count > '0' ? 'progress-complete' : 'progress-notComplete' }}"><xf:fa icon="fa-check fa-fw" /> <a href="{{ link('forums/create-thread') }}" data-xf-click="overlay">Thema erstellen</a> oder <a href="{{ link('whats-new') }}">antworten</a></li>
                </ul>

                <div class="progress-footer">Probleme beim benutzen des Forums? <a href="{$xf.contactUrl}" data-xf-click="{{ ($xf.options.contactUrl.overlay OR $xf.options.contactUrl.type == 'default') ? 'overlay' : '' }}">Kontaktiere uns</a></div>
            </div>
        </div>
    </div>
</xf:if>
You can simply delete all comments from me for cleaner code.
Code:
<!-- ... -->

And the Extra.less only have some litle style changes from Russ code version from above. Thats not a must have if you like Russ version.

So thanks! Russ version is cost free and easy to use. :)
Hi,

How to add trophie and reaction score too?

regards.
 
Top Bottom