cancel
Showing results for 
Search instead for 
Did you mean: 

Custom Site Properties

punk
Champ in-the-making
Champ in-the-making
How can I add my own custom properties to a Share Site in order to

1) Show them into the site-profile dashlet.
2) Be able to search for these new properties.

Thanks in advance.
21 REPLIES 21

punk
Champ in-the-making
Champ in-the-making
It was not a criticism to the Alfresco staff.
Just an observation: is often frustrating  examine the problems of the community version. This is the official forum and given the high diffusion of Alfresco I would expect a greater contribution by all, not only by staff members.
I see many topic where users demand, but few answers.
The Italian community then  is completely absent.

I did not know it was good practice to avoid the old topics, I apologize.
Normally in the forums I used to avoid doing this to avoid the proliferation of the same topic. So I used the same approach.

I really appreciate your suggestions.
Thank you very much Alex.

David.

afaust
Legendary Innovator
Legendary Innovator
Regarding your points of "greater contribution by all" I have to agree - considering how many people actually use Alfresco (based on the numbers of installation / downloads given in official Alfresco reports), one would expect more activity and interaction of users. And indeed, some local communities appear to be stillborn despite having a lot of installations - I think the German community is not much better off than the Italian one on this one…

Regarding the topic proliferation - I usually try to avoid that too. As long as you feel a conversation is still relevant or without conclusion, I would do that in these forums as well. But monkeys follow-up post was two months after the last entry - chances are, the participants have since moved on. A new thread immediately pops up as "unanswered" in the global filter some community members like myself use to identify as "open questions".

mincd_evolpe
Champ in-the-making
Champ in-the-making
I trying to extend the site properties and so far I customised:

-siteModel.xml with additional properties aspect
-create-site.get.html.ftl and edit-site.get.html.ftl with new text fields
-create-site.js and edit-site.js

The problem is that I can't save my custom properties in sites.post.json.js and site.put.json.js - org.alfresco.repo.site.SiteService and other classes from org.alfresco.repo.site package don't support saving this custom properties.
I tried to extend the SiteServiceImpl class with my own createSite(…) method, but I'm getting an error when starting alfresco:

ERROR [web.context.ContextLoader] [Thread-1] Context initialization failed
org.springframework.beans.factory.CannotLoadBeanClassException: Error loading class [com.someco.site.SomecoSiteService] for bean with name 'webscript.com.someco.site.SomecoSiteService' defined in file [C:\Alfresco\tomcat\shared\classes\alfresco\web-extension\custom-site-context.xml]: problem with class file or dependent class; nested exception is java.lang.NoClassDefFoundError: org/alfresco/repo/site/SiteServiceImpl


the context file :

    <bean id="webscript.com.someco.site.SomecoSiteService" class="com.someco.site.SomecoSiteService"
      parent="webscript">
            <property name="siteService">
            <ref bean="SiteService" />
         </property>
   </bean>

What am I doing wrong?

afaust
Legendary Innovator
Legendary Innovator
Hello,

I guess you have put your custom class in a JAR in /shared/lib or something similar, right? This won't work due to classloading rules. Any custom code that has dependencies on Alfresco components needs to be put in /webapps/alfresco/WEB-INF/lib (or exploded in /webapps/alfresco/WEB-INF/classes).

But you should not need to extend the SiteServiceImpl (I would even say this is discouraged) - you can save your custom properties in sites.post.json.js and site.put.json.js. Just use the ScriptNode instance you get via "site.node" and simply modify its properties before calling "save()".

Example for sites.post.json.js:

var site = null;  
if (sitetype == null)
{
  site = siteService.createSite(sitePreset, shortName, title, description, visibility);
}
else
{
  site = siteService.createSite(sitePreset, shortName, title, description, visibility, sitetype);
}

site.node.properties["some:prop"] = "someValue";
site.node.save();

Since I have recently done this kind of customization on the newest Alfresco version, I'll try to find some time to blog about a possible generic approach (that maybe could be provided out-of-the-box).

Regards
Axel

mincd_evolpe
Champ in-the-making
Champ in-the-making
Thanks for help, It looks simpler, but it still doesn't work (Sorry if this is silly question but I'm new to Alfresco)
When my model look like this:

   <type name="st:site">
         <title>Site</title>
         <parent>cm:folder</parent>        
         <properties>
            <property name="st:sitePreset">
               <title>Site Preset</title>
               <type>d:text</type>       
            </property>
            <property name="st:siteVisibility">
               <title>Site Visibility</title>
               <type>d:text</type>       
            </property>
         </properties>
         <mandatory-aspects>
            <aspect>cm:titled</aspect>
            <!– Sites are by default undeletable. Only deletable through the SiteService. –>
            <aspect>sys:undeletable</aspect>
            <aspect>st:customSiteProperties</aspect>
         </mandatory-aspects>
      </type>

     <!– Site Root Folder:                                                               –>
     <!–    - all sites are stored beneath the site root folder                           –>
      <type name="st:sites">
         <title>Sites</title>
         <parent>cm:folder</parent>        
      </type>   
    
   </types>
  
   <aspects>
  
      <!– Site Container Aspect –>
      <aspect name="st:siteContainer">
        <title>Site Container</title>         
         <properties>
            <property name="st:componentId">
               <title>Component Id</title>
               <type>d:text</type>       
            </property>
         </properties>
        </aspect>
       
        <!– Example Custom Site Properties Aspect –>
      <aspect name="st:customSiteProperties">
        <title>Custom Site Properties</title>         
         <properties>
            <property name="stcp:siteComment">
               <title>Site Comment</title>
               <type>d:text</type>       
            </property>
            <property name="stcp:matureOnly">
               <title>For mature only</title>
               <type>d:text</type>       
            </property>
         </properties>
        </aspect>
  
   </aspects>

In sites.post.json.js I use this kind of reference to properties?:

 
site.node.properties["stcp:siteComment"] = json.get("siteComment");
  site.node.save();

afaust
Legendary Innovator
Legendary Innovator
Hello,

the usage is correct. Are any errors reported? What is the state of the node in the NodeBrowser?

By the way - what kind of site needs a "matureOnly" flag / text?   :wink:

Regards
Axel

mincd_evolpe
Champ in-the-making
Champ in-the-making
I've got problem with script/template:

2012-07-19 09:45:25,656  ERROR [freemarker.runtime] [http-8080-4] Template processing error: "on line 1, column 1 in org/alfresco/modules/edit-site.get.html.ftl script not found."

on line 1, column 1 in org/alfresco/modules/edit-site.get.html.ftl script not found.
The problematic instruction:
———-
==> user-directive script [on line 1, column 1 in org/alfresco/modules/edit-site.get.html.ftl]
———-

Java backtrace for programmers:
———-
freemarker.core.InvalidReferenceException: on line 1, column 1 in org/alfresco/modules/edit-site.get.html.ftl script not found.
   at freemarker.core.UnifiedCall.accept(UnifiedCall.java:134)
   at freemarker.core.Environment.visit(Environment.java:221)


edit-site.get.html.ftl:
<@script type="text/javascript" src="${page.url.context}/extension/modules/edit-site.js"></@script>

<script type="text/javascript">//<![CDATA[
   var profile = new SomeCo.UserSite("${args.htmlid}").setOptions(
   {
      userId: "${user.name}",
      profile: {
          shortName: "<#if profile.shortName??>${profile.shortName?js_string}</#if>",
          title: "<#if profile.title??>${profile.title?js_string}</#if>",
          description: "<#if profile.description??>${profile.description?js_string}</#if>",
         visibility: "<#if profile.visibility??>${profile.visibility?js_string}</#if>",
         siteComment: "<#if profile.properties.siteComment??>${profile.properties.siteComment?js_string}</#if>",
         matureOnly: "<#if profile.properties.matureOnly??>${profile.properties.matureOnly?js_string}</#if>"
      }
   }).setMessages(
      ${messages}
   );
//]]></script>

#assign el=args.htmlid?html>
The file is in C:\Alfresco\tomcat\webapps\share\extension\modules\edit-site.js
Is there a different method to get the value like this?:
<div class="yui-u">
         <input id="${el}-siteComment" type="text" name="siteComment" tabindex="0" maxlength="255" value="${(profile.siteComment)?html}" /><br>
</div>
Do I have to modify edit-site.js?
Btw. matureOnly is just temporary name, that was first thing that came to my mind ;]

afaust
Legendary Innovator
Legendary Innovator
Hello,

"@script" does not belong in the .html.ftl, but the .head.ftl. Only the most recent HEAD has the ability for script includes to reside in .html.ftl, but this is not yet Alfresco standard and not available in current releases.

Regards
Axel

mincd_evolpe
Champ in-the-making
Champ in-the-making
I've discovered that in share repository I can edit custom properties and they are saved, do you know which files are responsible for the repo "edit properties? Is it possible to add only the *.head.ftl and *.html.ftl code from original "edit properties" files to "edit-site" code?

mincd_evolpe
Champ in-the-making
Champ in-the-making
Hello,

the usage is correct. Are any errors reported? What is the state of the node in the NodeBrowser?

By the way - what kind of site needs a "matureOnly" flag / text?   :wink:

Regards
Axel
There is no error in logs. In NodeBrowser I see that there is st:customSiteProperties aspect in the site and I can edit and save my custom properties via Share->Repository, but it looks like sites.post.json.js and site.put.json.js doesn't work properly, there's the whole codes:
site.put.json.js:
function main()
{
   // Get the site
   var shortName = url.extension;
   var site = siteService.getSite(shortName);
   
   if (site != null)
   {   
      // Updafte the sites details
      if (json.has("title") == true)
      {
         site.title = json.get("title");
      }
      if (json.has("description") == true)
      {
         site.description = json.get("description");
      }
      if (json.has("siteComment"))
      {
        site.node.properties["stcp:siteComment"] = json.get("siteComment");
      }

      if (json.has("matureOnly"))
      {
        site.node.properties["stcp:matureOnly"] = json.get("matureOnly");
      }
      
      // Use the visibility flag before the isPublic flag
      if (json.has("visibility") == true)
      {
         site.visibility = json.get("visibility");
      }
      else if (json.has("isPublic") == true)
      {
         // Deal with deprecated isPublic flag accordingly
         var isPublic = json.getBoolean("isPublic");
         if (isPublic == true)
         {
            site.visibility = siteService.PUBLIC_SITE;
         }
         else
         {
            site.visibility = siteService.PRIVATE_SITE;
         }
       }
      
      site.node.save();
      
      // Save the site
      site.save();
      
      // Pass the model to the template
      model.site = site;
   }
   else
   {
      // Return 404
      status.setCode(status.STATUS_NOT_FOUND, "Site " + shortName + " does not exist");
      return;
   }
}

main();

sites.post.json.js:
function main()
{
   // The commented out code below checks if the current user has the necessary permissions to
   // create a site and retrns a 401 status if they do not.
   //
   // However, the presentation tier currently handles 500 errors, but not 400 errors.
   // Therefore the UNAUTHORIZED status is not currently returned.
   // If a user who does not have permission to create a site tries to do so, a dialog
   // appears in Share telling them AccessDenied. You do not have the appropriate permissions
   // to perform this operation.
   // TODO If we can fix up create-site.js in Slingshot to handle 401s, we can comment this back in.


   // Irrespective of the checks below, the currently authenticated user needs to have
   // permission to create a site.
//   if (siteService.hasCreateSitePermissions() == false)
//   {
//      status.setCode(status.STATUS_UNAUTHORIZED, "User does not have permission to create sites.");
//      return;
//   }
  
   // Get the details of the site
   if (json.has("shortName") == false || json.get("shortName").length == 0)
   {
      status.setCode(status.STATUS_BAD_REQUEST, "Short name missing when creating site");
      return;
   }
   var shortName = json.get("shortName");
  
   // See if the shortName is available
   var site = siteService.getSite(shortName);
   if (site != null)
   {
      status.setCode(status.STATUS_INTERNAL_SERVER_ERROR, "error.duplicateShortName");
      return;
   }
  
   if (json.has("sitePreset") == false || json.get("sitePreset").length == 0)
   {
      status.setCode(status.STATUS_BAD_REQUEST, "Site preset missing when creating site");
      return;
   }
   var sitePreset = json.get("sitePreset");
  
   var title = null;
   if (json.has("title"))
   {
      title = json.get("title");
   }
     
   var description = null;
   if (json.has("description"))
   {
      description = json.get("description");
   }

   var siteComment = null;
   if (json.has("siteComment"))
   {
      siteComment = json.get("siteComment");
   }
  
   var matureOnly = null;
   if (json.has("matureOnly"))
   {
      matureOnly = json.get("matureOnly");
   }
  
   var sitetype = null;
   if (json.has("type") == true)
   {
      sitetype = json.get("type");
   }
  
   // Use the visibility flag before the isPublic flag
   var visibility = siteService.PUBLIC_SITE;
   if (json.has("visibility"))
   {
      visibility = json.get("visibility");
   }
   else if (json.has("isPublic"))
   {
      var isPublic = json.getBoolean("isPublic");
      if (isPublic == true)
      {
         visibility = siteService.PUBLIC_SITE;
      }
      else
      {
         visibility = siteService.PRIVATE_SITE;
      }
   }
  
   // Create the site
   var site = null;  
   if (sitetype == null)
   {
      site = siteService.createSite(sitePreset, shortName, title, description, visibility);
   }
   else
   {
      site = siteService.createSite(sitePreset, shortName, title, description, visibility, sitetype);
   }
  
   site.node.properties["stcp:siteComment"] = siteComment;
   site.node.properties["stcp:matureOnly"] = matureOnly;
   site.node.save();
   // Put the created site into the model
   model.site = site;
}

main();

In the create-site.get.html.ftl I added:
<div class="yui-gd">
            <div class="yui-u first"><label for="${el}-siteComment">${msg("label.siteComment")}:</label></div>
            <div class="yui-u">
               <input id="${el}-siteComment" type="text" name="siteComment" tabindex="0" maxlength="255" /><br>
            </div>
         </div>
         <div class="yui-gd">
            <div class="yui-u first"><label for="${el}-matureOnly">${msg("label.matureOnly")}:</label></div>
            <div class="yui-u">
               <select id="${el}-matureOnly" name="matureOnly" tabindex="0">
                     <option value="no">no</option>
                     <option value="yes">yes</option>                 
               </select>
            </div>
         </div>
Please help