Eric’s adventures in Sharepoint, technology, and life.
Email icon Home icon
  • Employee Training template, official release!

    Posted on July 2nd, 2009 Eric 50 comments

    After developing this custom template for an internal project, I knew I would have to do some work to be able to recreate and reuse this internally. After a couple weeks of tinkering, deploying and troubleshooting, I have what I believe to be an easily deployable template to manage internal registrations for employee training. After about 10 to 15 minutes of simple configurations, you can have this up and running in your environment.

    All that is needed is Sharepoint Designer access and server access if you wish to deploy the STP file as a top level site in a collection. If not, the file can be uploaded to the Site Template Gallery on an existing collection and deployed as a new site.

    This should be fully WSS compliant, if you have MOSS you can take advantage of the audience features and security trim things a little cleaner. Link to the original template, link to Dessie’s updates and bug fixes.

    I have packaged this into 2 different STP files. Both contain configuration instructions and deployment batch files. One contains HTML emails the other contains more “stock” Sharepoint Designer work flow emails. Choose which ever you’d like.

    P.S. – This looks great with the new Event Planning theme that was released by Microsoft. If you go that route, you’ll want to add some style tags to change the page titles to black so they are readable (and the reason why I included Heather Solomon’s clean calendar CSS file, that theme calendar isn’t styled).

    Edit:7/15/09
    I believe I have tracked down and resolved the problem people were having deploying the template and creating sites and site collections off of it. I have updated the zip file above. For support reasons, I am eliminating the HTML email version of the download. Please refer to this post on how to configure HTML emails. Sorry, it is too difficult to try and maintain 2 different installations and ensure they are all in sync with the bug fixes.

    Post to Twitter Post to Plurk Plurk This Post Post to Yahoo Buzz Buzz This Post Post to Delicious Delicious Post to Digg Digg This Post Stumble This Post

  • Employee Training Comments

    Posted on June 25th, 2009 Eric No comments

    Michael Gannotti posted the video that we shot at Sharepoint Saturday Charlotte. If you have any specific questions or comments on how I did something, leave a comment and I’ll get back with you.

    I am hoping to release an updated STP of the template soon.

    Post to Twitter Post to Plurk Plurk This Post Post to Yahoo Buzz Buzz This Post Post to Delicious Delicious Post to Digg Digg This Post Stumble This Post

  • Admin page in the Employee Training template

    Posted on May 8th, 2009 Eric 1 comment

    This week my focus was to start testing a software upgrade but that got hijacked due to database issues. So I took the opportunity to finish the final features of a customized Employee Training template that we deployed to handle workshop registrations. The last few hurdles I was working on were usability issues to take it from ok with some workarounds to functional as is.

    I created a Administration page for the admins to manage some functions that they’d need to do. Mainly see a list of upcoming workshops, who is attending, being able to email 1 or all users and being able to export the roster to make sign in sheets. We also have a broken iCal function right now but that will be covered when that gets fixed.

    The data view web part on the page gets information for the courses being offered and when the filled seats is clicked, it passes the courseid variable into the registration list to get the users. Nothing too magical here. But wait, we’ve got a phone number field that is displaying all sorts of jibberish like ,#Domain\user,department,etc. Will looking at this user profile, they don’t have a phone number listed in their Sharepoint profile. Easy fix with some XSLT. I found the td that outputs the phone number and changed it to the following.

    
    
      Not Listed
      
      
      
    
    

    Nothing too hard there.

    CSV export. I thought this was going to be impossible or at least very difficult. A little Googling and I found a great, easy to use jQuery solution called table2CSV. Shout out to Kunal Babre, this script rocks! Used option 1 for this scenario. I created a sample page in SPD and added 2 buttons to the page, copied the HTLM and slapped it into a Content Editor Web part. I added an onclick reference to the jQuery function and presto, a popup window with comma delimited data for the list! Wow, great 2 problems solved with little coding, great for us code stupid people.

    Now comes the email requirements. I needed help from Tony Miller, colleague here and our go to guy for jQuery, to help with this. Again we went back to SPD and added an email id on the td that generates the email address for the registrant list. Now we have our selector to grab this information. One major problem though, all the fields are being displayed as rich text, if we stet them to plain text in the SPD data view options, it returns nobr span mumbo jumbo. So we did some more jQuery embedded in a content editor web part.

    $('td.RegList nobr span a').each(function (i) {
    		$(this).parent().html($(this).text())
    	});
    

    What this does is strip all the HTML in the Registrant table, defined by another id we tacked onto the tds, and returns it’s text value. Good, now we can use the information better.

    I added an additional column to the registration list that will hold the hyperlink so that the admins in 1 click can email an individual registrant. Now with some more jQuery, we can fill in that value. We assigned that td an id of MailtoLink so the function would know where to output the information.

    $('td.MailtoLink').each(function (i) { 
            $(this).html('<a href="mailto:' + 
                   $(this).parent().children('td.email').text() + 
    '?subject=Upcoming Workshop' + '">E-Mail Registrant</a>')
            });

    Boom, hyperlink fills the table cell and we are almost done.

    The last bit was to create a mail all users option. I had to turn to Paul Grenier, a moderator over at Stump the Panel on EndUserSharepoint.com. Great information in STP and on the site. Bookmark and RSS it, the content is amazing. Paul came back with some psuedo code and some jQuery to get it working. It can be found here.

    Tony and I had to make some tweaks to get it working. We removed the validation step from it since the information wasn’t manually input, it came from Sharepoint and Sharepoint provided it as an email address. Our final code loos like this, and is attached to the other button, named EmailButton, I created.

    $('#EmailButton').click(function() {
       var validEmails = [];
       var emailstr;
         $(".email").each(function(i) {
         validEmails.push($(this).text());
        });
       var url = 'mailto:' + validEmails.join(';') + '?subject=My%20Subject';
       var emailwin = window.open(url, "EmailWindow");
       emailwin.close();
      });
    }); 

    This process has been a lot of work but has been extremely rewarding. The feedback I’m receiving from the group this is designed for has been so positive and they are very excited. What more can you ask for than for people who are excited to use Sharepoint? Many thanks to Tony, Paul, Laura, and the Twitterverse that has helped with some of these issues.

    Post to Twitter Post to Plurk Plurk This Post Post to Yahoo Buzz Buzz This Post Post to Delicious Delicious Post to Digg Digg This Post Stumble This Post

  • Modifying Employee Training template

    Posted on April 8th, 2009 Eric 2 comments

    In my last blog post, I mentioned I was starting to dislike the fab 40 templates. This post describes how we (myself and my colleague Tony Miller) fixed an inherent issue with one of these templates. This post goes into steps done after following these three blog posts:

    Here is some background on the template if you aren’t familiar. The site is designed so that an instructor can add courses they wish to teach to a list. Users come into the site and see the courses available and click a link to go to the Dispform to register. However there is a glaring security issue here. The navigational bar is present for users to delete a course! If a permission level is created to stop them from deleting items, then they can’t unregister for a course. This bar also contains a function to export the item to Outlook.

    ms-toolbar

    ms-toolbar

    So what do we do to fix it? I hope that’s why you’re reading.

    The first thing I did was to create a calculated column in the course list that creates an iCal hyperlink. I created the function as =CONCATENATE(”https://MyDomain/sites/cferegistration/_vti_bin/owssvr.dll?CS=109&Cmd=Display&List=%7B242652E5%2D0492%2D4C2F%2D8B37%2D06C9A59B0020%7D&CacheControl=1&ID=”,ID,”&Using=event.ics”). Easy enough. I then used a little of Paul Grenier’s jQuery magic to clean that up. Functionality restored for the users. Now to get it on the Dispform.

    Here I opened Sharepoint Designer and opened the Dispform associated with the Courses list. I added @iCal, iCal to the XSL data fields at the top of the transform. Then I added

    <tr style="display: none">
    	<td width="190px" valign="top" class="ms-formlabel">
    		<H3 class="ms-standardheader">
    			<nobr>Export to Outlook</nobr>
    		</H3>
    	</td>
    	<td width="400px" valign="top" class="ms-formbody">
    		<xsl:value-of select="@iCal/>
    	</td>
    </tr>

    an thought I’d be golden. well, I was wrong. It created a nightmare of a URL and needed a way to make a nice hyperlink so users could just click it and save the item. After about an hour of trying all sorts of things, Tony realized that Sharepoint was using XSL version 1.0. With this in hand we were able to utilize a replacement function to clean out the amp; values and create a nice hyperlink.

    We added

    <xsl:template name="replace-substring">
      <xsl:param name="original"/>
      <xsl:param name="substring"/>
      <xsl:param name="replacement" select="''"/>
      <xsl:variable name="first">
        <xsl:choose>
          <xsl:when test="contains($original, $substring)">
            <xsl:value-of select="substring-before($original, $substring)"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="$original"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:variable>
      <xsl:variable name="middle">
        <xsl:choose>
          <xsl:when test="contains($original, $substring)">
            <xsl:value-of select="$replacement"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:text></xsl:text>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:variable>
      <xsl:variable name="last">
        <xsl:choose>
          <xsl:when test="contains($original, $substring)">
            <xsl:choose>
              <xsl:when test="contains(substring-after($original, $substring), 
                                       $substring)">
                <xsl:call-template name="replace-substring">
                  <xsl:with-param name="original">
                    <xsl:value-of select="substring-after($original, $substring)"/>
                  </xsl:with-param>
                  <xsl:with-param name="substring">
                    <xsl:value-of select="$substring"/>
                  </xsl:with-param>
                  <xsl:with-param name="replacement">
                    <xsl:value-of select="$replacement"/>
                  </xsl:with-param>
                </xsl:call-template>
              </xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="substring-after($original, $substring)"/>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:when>
          <xsl:otherwise>
            <xsl:text></xsl:text>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:variable>
      <xsl:value-of select="concat($first, $middle, $last)"/>
    </xsl:template>

    to the top of the transform after the following code.

    <xsl:variable name="dvt_1_automode">0</xsl:variable>

    Then we changed the values being displayed by altering the output code to:

    <tr>
    	<td width="190px" valign="top" class="ms-formlabel">
    		<H3 class="ms-standardheader">
    			<nobr>Export to iCal</nobr>
    		</H3>
    	</td>
    	<td width="400px" valign="top" class="ms-formbody">
    		<xsl:variable name="iCalLink">
    		<xsl:call-template name="replace-substring">
    		<xsl:with-param name="original" select="@iCal"/>
    		<xsl:with-param name="substring" select="string('amp;')"/>
    		<xsl:with-param name="replacement" select="string('')"/>
    		</xsl:call-template>
    		</xsl:variable>
    		<a href="{$iCalLink}">Export to iCal</a>
    	</td>
    </tr>

    Now we had a working hyperlink in our item details.

    Whew, almost done! Last cleanup item is to remove the toolbar so users cannot delete items. We cranked up Firefox and Firebug and found the toolbar easily enough. A few console trial and errors and we had removed it. Instead of putting it into a CEWP like I normally would, I just added it to the page head on the dispform. That code is:

    <script type="text/javascript">
     
    $(function() {
    	$('table[@id$=toolBarTbl].ms-toolbar').remove();
    });
    </script>

    Save, refresh and viola! the dispform now looks like the below image. This might not have been the easiest method to do this, and I’d be happy to hear other ways of doing it.

    dispform.aspx

    dispform.aspx

    Post to Twitter Post to Plurk Plurk This Post Post to Yahoo Buzz Buzz This Post Post to Delicious Delicious Post to Digg Digg This Post Stumble This Post