Changeset 1159

Show
Ignore:
Timestamp:
17-11-10 16:20:33 (3 years ago)
Author:
robert@…
Message:

Improved the template editor so that template fields can be removed from templates, even if the templates are in use, but only if the template fields are never filled. (see ticket #74)

Also changed the user registration so that the administrator confirmation mails will be sent to the administrators in production environment, but still to gscfproject@… in other environments.

Location:
trunk/grails-app
Files:
13 modified

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/controllers/dbnp/authentication/UserRegistrationController.groovy

    r1147 r1159  
    1515package dbnp.authentication 
    1616import grails.plugins.springsecurity.Secured 
     17import org.codehaus.groovy.grails.commons.GrailsApplication 
     18import grails.util.GrailsUtil 
    1719 
    1820class UserRegistrationController { 
     
    125127        def adminLink = createLink( controller: 'userRegistration', action: 'confirmAdmin', params: [code: adminCode.token], absolute: true ) 
    126128 
     129                // If we are in production, send the mails to all administrators 
     130                // Otherwise, send it to a default (spam) mail address 
     131                def adminMail = "gscfproject@gmail.com"; 
     132                if ( GrailsUtil.getEnvironment().equals(GrailsApplication.ENV_PRODUCTION) ) { 
     133                        def administrators = SecRole.findUsers( 'ROLE_ADMIN' ); 
     134                        if( administrators.size() > 0 ) { 
     135                                adminMail = administrators.email.toArray(); 
     136                        } 
     137                } 
     138 
    127139        // Send an email to the administrators 
    128140        try { 
    129141                        // Determine administrator email addresses 
    130142            sendMail { 
    131                 to      "gscfproject@gmail.com" 
     143                to      adminMail 
    132144                subject "New user (" + user.username + ") at GSCF" 
    133145                html    g.render(template:"/email/registrationConfirmationAdmin", model:[username: user.username, email: user.email, link: adminLink]) 
  • trunk/grails-app/controllers/dbnp/studycapturing/TemplateEditorController.groovy

    r1077 r1159  
    494494                templateField.properties = params 
    495495        if (!templateField.hasErrors() && templateField.save(flush: true)) { 
    496                         def html = g.render( template: 'elements/available', model: [templateField: templateField, ontologies: Ontology.list(), fieldTypes: TemplateFieldType.list()] ); 
     496 
     497                        // Select the template to use for the HTML output 
     498                        def renderTemplate = 'elements/available'; 
     499                        if( params.renderTemplate == 'selected' ) { 
     500                                renderTemplate = 'elements/selected'; 
     501                        } 
     502 
     503                        // Selected fields should have a template given 
     504                        def template = null; 
     505                        if( params.templateId ) 
     506                                template = Template.findById( params.templateId ); 
     507                         
     508                        def html = g.render( template: renderTemplate, model: [template: template, templateField: templateField, ontologies: Ontology.list(), fieldTypes: TemplateFieldType.list()] ); 
    497509                        def output = [ id: templateField.id, html: html ]; 
    498510                        render output as JSON; 
     
    635647 
    636648                // If the template is in use, field can not be removed 
    637                 if( template.inUse() ) { 
    638                         response.status = 500; 
    639                         render 'No fields can be removed from templates that are in use.' 
     649                if( templateField.isFilledInTemplate(template) ) { 
     650                        response.status = 500; 
     651                        render 'Fields can not be removed from a template if it has been filled somewhere.' 
    640652                        return; 
    641653                } 
  • trunk/grails-app/domain/dbnp/authentication/SecRole.groovy

    r976 r1159  
    1212                authority blank: false, unique: true 
    1313        } 
     14 
     15        static List<SecUser> findUsers(String authority) { 
     16                def userRoles = SecUserSecRole.findAllBySecRole( SecRole.findByAuthority( authority ) ); 
     17                 
     18                def users = []; 
     19                userRoles.each { users.add( it.secUser ) } 
     20                 
     21                return users 
     22        } 
    1423} 
  • trunk/grails-app/domain/dbnp/studycapturing/TemplateField.groovy

    r959 r1159  
    118118 
    119119        /** 
    120          * The number of templates that use this template 
    121          * 
    122          * @returns             the number of templates that use this template. 
     120         * The number of templates that use this template field 
     121         * 
     122         * @returns             the number of templates that use this template field. 
    123123         */ 
    124124        def numUses() { 
     125                return getUses().size(); 
     126        } 
     127 
     128        /** 
     129         * Retrieves the templates that use this template field 
     130         * 
     131         * @returns             a list of templates that use this template field. 
     132         */ 
     133        def getUses() { 
    125134                def templates = Template.findAll(); 
    126135                def elements; 
     136 
    127137                if( templates && templates.size() > 0 ) { 
    128138                        elements = templates.findAll { template -> template.fields.contains( this ) }; 
    129139                } else { 
    130                         return 0; 
     140                        return []; 
    131141                } 
    132142 
    133                 return elements.size(); 
    134         } 
     143                return elements; 
     144        } 
     145 
     146        /** 
     147         * Checks whether this template field is used in a template and also filled in any instance of that template 
     148         * 
     149         * @returns             true iff this template field is used in a template, the template is instantiated 
     150         *                              and an instance has a value for this field. false otherwise 
     151         */ 
     152        def isFilled() { 
     153                // Find all entities that use this template 
     154                def templates = getUses(); 
     155 
     156                if( templates.size() == 0 ) 
     157                        return false; 
     158 
     159                def c = this.entity.createCriteria() 
     160                def entities = c { 
     161                        'in'("template",templates) 
     162                } 
     163 
     164                def filledEntities = entities.findAll { entity -> entity.getFieldValue( this.name ) } 
     165 
     166                return filledEntities.size() > 0; 
     167        } 
     168 
     169        /** 
     170         * Checks whether this template field is used in the given template and also filled in an instance of that template 
     171         * 
     172         * @returns             true iff this template field is used in the given template, the template is instantiated 
     173         *                              and an instance has a value for this field. false otherwise 
     174         */ 
     175        def isFilledInTemplate(Template t) { 
     176                println( "Checking field " + this.name ) 
     177                println( "Filled in template: " + t) 
     178                if( t == null )  
     179                        return false; 
     180                         
     181                // If the template is not used, if can never be filled 
     182                if( !t.fields.contains( this ) ) 
     183                        return false; 
     184 
     185                // Find all entities that use this template 
     186                def entities = entity.findAllByTemplate( t ); 
     187 
     188                println( "Num entities: " + entities.size() ) 
     189 
     190                def filledEntities = entities.findAll { entity -> entity.getFieldValue( this.name ) } 
     191 
     192                println( "Num filled entities: " + filledEntities.size() ) 
     193                println( "Values: " + filledEntities*.getFieldValue( this.name ).join( ', ' ) ) 
     194                return filledEntities.size() > 0; 
     195        } 
     196 
     197        /** 
     198         * Check whether a templatefield that is used in a template may still be edited or deleted. 
     199         * That is possible if the templatefield is never filled and the template is only used in one template 
     200         * 
     201         * This method should only be used for templatefields used in a template that is currently shown. Otherwise 
     202         * the user may edit this template field, while it is also in use in another template than is currently shown. 
     203         * That lead to confusion. 
     204         * 
     205         * @returns true iff this template may still be edited or deleted. 
     206         */ 
     207        def isEditable() { 
     208                return !isFilled() && numUses() == 1; 
     209        } 
     210 
     211        /** 
     212         * Checks whether the given list item is selected in an entity where this template field is used 
     213         * 
     214         * @param       item    ListItem to check. 
     215         * @returns                     true iff the list item is part of this template field and the given list 
     216         *                                      item is selected in an entity where this template field is used. false otherwise 
     217         *                                      Returns false if the type of this template field is other than STRINGLIST 
     218         */ 
     219        def entryUsed(TemplateFieldListItem item) { 
     220                //return numUses() > 0; 
     221        } 
     222 
     223        /** 
     224         * Checks whether a term from the given ontology is selected in an entity where this template field is used 
     225         * 
     226         * @param       item    ListItem to check. 
     227         * @returns                     true iff the ontology is part of this template field and a term from the given 
     228         *                                      ontology is selected in an entity where this template field is used. false otherwise 
     229         *                                      Returns false if the type of this template field is other than ONTOLOGY 
     230         */ 
     231        def entryUsed(Ontology item) { 
     232                //return numUses() > 0; 
     233        } 
     234 
    135235} 
  • trunk/grails-app/views/templateEditor/elements/_liFieldInUse.gsp

    r980 r1159  
    11<g:set var="numUses" value="${templateField.numUses()}" /> 
    22<span class="listButtons"> 
    3   <img onClick="showTemplateFieldForm( 'templateField_' + ${templateField.id}); this.blur(); return false;" src="${createLinkTo( dir: 'images/icons', file: 'application_edit.png', plugin: 'famfamfam' )}" alt="Edit template field properties" title="Edit template field properties"> 
    4   <img class="disabled" src="${createLinkTo( dir: 'images/icons', file: 'delete.png', plugin: 'famfamfam' )}" alt="Deleting this field is not possible. Field is used in ${numUses} templates." title="Deleting this field is not possible. Field is used in ${numUses} templates."> 
    5   <img onClick="addTemplateField( ${templateField.id}, null, true );" src="${createLinkTo( dir: 'images/icons', file: 'add.png', plugin: 'famfamfam' )}" alt="Add field to template" title="Add field to template"> 
     3  <img onClick="showTemplateFieldForm( 'templateField_' + ${templateField.id}); this.blur(); return false;" src="${resource( dir: 'images/icons', file: 'application_edit.png', plugin: 'famfamfam' )}" alt="Edit template field properties" title="Edit template field properties"> 
     4  <img class="disabled" src="${resource( dir: 'images/icons', file: 'delete.png', plugin: 'famfamfam' )}" alt="Deleting this field is not possible. Field is used in ${numUses} templates." title="Deleting this field is not possible. Field is used in ${numUses} templates."> 
     5  <img onClick="addTemplateField( ${templateField.id}, null, true );" src="${resource( dir: 'images/icons', file: 'add.png', plugin: 'famfamfam' )}" alt="Add field to template" title="Add field to template"> 
    66</span> 
    77 
  • trunk/grails-app/views/templateEditor/elements/_liFieldNotInUse.gsp

    r980 r1159  
    11<span class="listButtons"> 
    2   <img onClick="showTemplateFieldForm( 'templateField_' + ${templateField.id}); this.blur(); return false;" src="${createLinkTo( dir: 'images/icons', file: 'application_edit.png', plugin: 'famfamfam' )}" alt="Edit template field properties" title="Edit template field properties"> 
    3   <img onClick="if( confirm( 'Are you sure?' ) ) { deleteTemplateField( ${templateField.id} ); }" src="${createLinkTo( dir: 'images/icons', file: 'delete.png', plugin: 'famfamfam' )}" alt="Delete this template field" title="Delete this template field"> 
    4   <img onClick="addTemplateField( ${templateField.id}, null, true );" src="${createLinkTo( dir: 'images/icons', file: 'add.png', plugin: 'famfamfam' )}" alt="Add field to template" title="Add field to template"> 
     2  <img onClick="showTemplateFieldForm( 'templateField_' + ${templateField.id}); this.blur(); return false;" src="${resource( dir: 'images/icons', file: 'application_edit.png', plugin: 'famfamfam' )}" alt="Edit template field properties" title="Edit template field properties"> 
     3  <img onClick="if( confirm( 'Are you sure?' ) ) { deleteTemplateField( ${templateField.id} ); }" src="${resource( dir: 'images/icons', file: 'delete.png', plugin: 'famfamfam' )}" alt="Delete this template field" title="Delete this template field"> 
     4  <img onClick="addTemplateField( ${templateField.id}, null, true );" src="${resource( dir: 'images/icons', file: 'add.png', plugin: 'famfamfam' )}" alt="Add field to template" title="Add field to template"> 
    55</span> 
    66 
  • trunk/grails-app/views/templateEditor/elements/_liFieldSelected.gsp

    r1136 r1159  
    11<span class="listButtons"> 
    2   <img onClick="showTemplateFieldForm( 'templateField_' + ${templateField.id}); this.blur(); return false;" src="${createLinkTo( dir: 'images/icons', file: 'application_edit.png', plugin: 'famfamfam' )}" alt="Show template field properties" title="Show template field properties"> 
    3  
    4   <g:if test="${template.inUse()}"> 
    5         <img class="disabled" src="${createLinkTo( dir: 'images/icons', file: 'delete.png', plugin: 'famfamfam' )}" alt="This field can not be removed from the template, as the template is still in use." title="This field can not be removed from the template, as the template is still in use."> 
     2  <img onClick="showTemplateFieldForm( 'templateField_' + ${templateField.id}); this.blur(); return false;" src="${resource( dir: 'images/icons', file: 'application_edit.png', plugin: 'famfamfam' )}" alt="Show template field properties" title="Show template field properties"> 
     3  <g:if test="${templateField.isFilledInTemplate(template)}"> 
     4        <img class="disabled" src="${resource( dir: 'images/icons', file: 'delete.png', plugin: 'famfamfam' )}" alt="This field can not be removed from the template, as this field is already in use." title="This field can not be removed from the template, as this field is already in use."> 
    65  </g:if> 
    76  <g:else> 
    8         <img onClick="removeTemplateField( ${templateField.id} ); moveFieldListItem( ${templateField.id}, '#availableTemplateFields' );" src="${createLinkTo( dir: 'images/icons', file: 'delete.png', plugin: 'famfamfam' )}" alt="Remove this template field from the template" title="Remove this template field from the template"> 
     7        <img onClick="removeTemplateField( ${templateField.id} ); moveFieldListItem( ${templateField.id}, '#availableTemplateFields' );" src="${resource( dir: 'images/icons', file: 'delete.png', plugin: 'famfamfam' )}" alt="Remove this template field from the template" title="Remove this template field from the template"> 
    98  </g:else> 
    109</span> 
     
    1413  (<g:if test="${templateField.unit}">${templateField.unit}, </g:if><g:render template="elements/${templateField.type.toString().toLowerCase().replaceAll(/ /,'_')}" model="[templateField: templateField]"/>) 
    1514 
    16   <form class="templateField_form" id="templateField_${templateField.id}_form"> 
    17           <g:render template="elements/disabledFieldForm" model="['templateField': templateField, 'ontologies': ontologies, 'fieldTypes': fieldTypes]"/> 
    18           <div class="templateFieldButtons"> 
    19                   <input type="button" value="Close" onClick="hideTemplateFieldForm( ${templateField.id} );"> 
    20           </div> 
     15  <form class="templateField_form" id="templateField_${templateField.id}_form" action="updateField"> 
     16          <g:if test="${templateField.isEditable()}"> 
     17                <g:hiddenField name="id" value="${templateField.id}" /> 
     18                <g:hiddenField name="version" value="${templateField.version}" /> 
     19                <g:hiddenField name="renderTemplate" value="selected" /> 
     20                <g:hiddenField name="templateId" value="${template.id}" /> 
     21                <g:render template="elements/fieldForm" model="['templateField': templateField, 'ontologies': ontologies, 'fieldTypes': fieldTypes]"/> 
     22                <div class="templateFieldButtons"> 
     23                        <input type="button" value="Save" onClick="updateTemplateField( ${templateField.id} );"> 
     24                        <input type="button" value="Close" onClick="hideTemplateFieldForm( ${templateField.id} );"> 
     25                </div> 
     26          </g:if> 
     27        <g:else> 
     28                <g:render template="elements/disabledFieldForm" model="['templateField': templateField, 'ontologies': ontologies, 'fieldTypes': fieldTypes]"/> 
     29                <div class="templateFieldButtons"> 
     30                        <input type="button" value="Close" onClick="hideTemplateFieldForm( ${templateField.id} );"> 
     31                </div> 
     32        </g:else> 
    2133  </form> 
  • trunk/grails-app/views/templateEditor/elements/_liTemplateEditable.gsp

    r1027 r1159  
    11<span class="listButtons"> 
    2   <img onClick="editTemplate( ${template.id} );" src="${createLinkTo( dir: 'images/icons', file: 'application_edit.png', plugin: 'famfamfam' )}" alt="Edit template properties" title="Edit template properties"> 
    3   <img onClick="editFields( ${template.id} );"src="${createLinkTo( dir: 'images/icons', file: 'application_form.png', plugin: 'famfamfam' )}" alt="Add/remove template fields" title="Add/remove template fields"> 
    4   <img onClick="cloneTemplate( ${template.id} );"src="${createLinkTo( dir: 'images/icons', file: 'page_copy.png', plugin: 'famfamfam' )}" alt="Clone this template" title="Clone this template"> 
    5   <img onClick="if( confirm( 'Are you sure?' ) ) { deleteTemplate( ${template.id} ); }" src="${createLinkTo( dir: 'images/icons', file: 'delete.png', plugin: 'famfamfam' )}" alt="Delete this template" title="Delete this template"> 
     2  <img onClick="editTemplate( ${template.id} );" src="${resource( dir: 'images/icons', file: 'application_edit.png', plugin: 'famfamfam' )}" alt="Edit template properties" title="Edit template properties"> 
     3  <img onClick="editFields( ${template.id} );"src="${resource( dir: 'images/icons', file: 'application_form.png', plugin: 'famfamfam' )}" alt="Add/remove template fields" title="Add/remove template fields"> 
     4  <img onClick="cloneTemplate( ${template.id} );"src="${resource( dir: 'images/icons', file: 'page_copy.png', plugin: 'famfamfam' )}" alt="Clone this template" title="Clone this template"> 
     5  <img onClick="if( confirm( 'Are you sure?' ) ) { deleteTemplate( ${template.id} ); }" src="${resource( dir: 'images/icons', file: 'delete.png', plugin: 'famfamfam' )}" alt="Delete this template" title="Delete this template"> 
    66</span> 
    77${template.name} 
  • trunk/grails-app/views/templateEditor/elements/_liTemplateNonEditable.gsp

    r1027 r1159  
    11<g:set var="numUses" value="${template.numUses()}" /> 
    22<span class="listButtons"> 
    3   <img onClick="editTemplate( ${template.id} );" src="${createLinkTo( dir: 'images/icons', file: 'application_edit.png', plugin: 'famfamfam' )}" alt="Edit template properties" title="Edit template properties"> 
    4   <img onClick="editFields( ${template.id} );"src="${createLinkTo( dir: 'images/icons', file: 'application_form.png', plugin: 'famfamfam' )}" alt="Add/remove template fields" title="Add/remove template fields"> 
    5   <img onClick="cloneTemplate( ${template.id} );"src="${createLinkTo( dir: 'images/icons', file: 'page_copy.png', plugin: 'famfamfam' )}" alt="Clone this template" title="Clone this template"> 
    6   <img class="disabled" src="${createLinkTo( dir: 'images/icons', file: 'delete.png', plugin: 'famfamfam' )}" alt="Deleting this template is not possible. Template is used in ${numUses} objects." title="Deleting this template is not possible. Template is used in ${numUses} objects."> 
     3  <img onClick="editTemplate( ${template.id} );" src="${resource( dir: 'images/icons', file: 'application_edit.png', plugin: 'famfamfam' )}" alt="Edit template properties" title="Edit template properties"> 
     4  <img onClick="editFields( ${template.id} );"src="${resource( dir: 'images/icons', file: 'application_form.png', plugin: 'famfamfam' )}" alt="Add/remove template fields" title="Add/remove template fields"> 
     5  <img onClick="cloneTemplate( ${template.id} );"src="${resource( dir: 'images/icons', file: 'page_copy.png', plugin: 'famfamfam' )}" alt="Clone this template" title="Clone this template"> 
     6  <img class="disabled" src="${resource( dir: 'images/icons', file: 'delete.png', plugin: 'famfamfam' )}" alt="Deleting this template is not possible. Template is used in ${numUses} objects." title="Deleting this template is not possible. Template is used in ${numUses} objects."> 
    77</span> 
    88${template.name} 
  • trunk/grails-app/views/templateEditor/elements/_selected.gsp

    r959 r1159  
    11<li class="ui-state-default  <g:if test="${templateField.required}">required</g:if>" id="templateField_${templateField.id}"> 
    2     <g:render template="elements/liFieldSelected" model="['templateField': templateField, 'template': template, 'fieldTypes': fieldTypes]"/> 
     2  <g:render template="elements/liFieldSelected" model="['templateField': templateField, 'template': template, 'ontologies': ontologies, 'fieldTypes': fieldTypes]"/> 
    33</li> 
  • trunk/grails-app/views/templateEditor/index.gsp

    r1125 r1159  
    1919                <meta name="layout" content="${layout}"/> 
    2020                <title>template editor</title> 
    21                 <script src="${createLinkTo(dir: 'js', file: 'templateEditor.js')}" type="text/javascript"></script> 
    22                 <link rel="stylesheet" href="${createLinkTo(dir: 'css', file: 'templateEditor.css')}" /> 
     21                <script src="${resource(dir: 'js', file: 'templateEditor.js')}" type="text/javascript"></script> 
     22                <link rel="stylesheet" href="${resource(dir: 'css', file: 'templateEditor.css')}" /> 
    2323                <style type="text/css"> 
    2424                  #content .templateEditorStep { font-size: 0.8em; } 
  • trunk/grails-app/views/templateEditor/_ontologyDialog.gsp

    r959 r1159  
    44        Search by ncboID. Fill in the ncboID of the ontology you want to add.<br /> 
    55        <input class="text" type="text" name="ncboID" id="ncboIDText" onClick="$('#searchType_ncbo').attr( 'checked', true ); $( '#termID' ).val( '' );"> 
    6         <img id="ncbo_spinner" src="${createLinkTo( dir: 'images', file: 'spinner.gif' )}" style="margin-left: 5px; display: none;"> 
     6        <img id="ncbo_spinner" src="${resource( dir: 'images', file: 'spinner.gif' )}" style="margin-left: 5px; display: none;"> 
    77  </li> 
    88  <li onClick="$('#searchType_term').attr( 'checked', true ); $( '#ncboIDText' ).val( '' );"> 
     
    1111        be added to the system.<br /> 
    1212        <g:textField class="text" name="termID" rel="ontology-all" onClick="\$('#searchType_term').attr( 'checked', true ); \$( '#ncboIDText' ).val( '' );"/> 
    13         <img id="term_spinner" src="${createLinkTo( dir: 'images', file: 'spinner.gif' )}" style="margin-left: 5px; display: none;"> 
     13        <img id="term_spinner" src="${resource( dir: 'images', file: 'spinner.gif' )}" style="margin-left: 5px; display: none;"> 
    1414  </li> 
    1515</ul> 
  • trunk/grails-app/views/user/edit.gsp

    r1152 r1159  
    2424                        </p> 
    2525          </div> 
     26        </g:if> 
    2627        <h3><g:message code="default.edit.label" args="[entityName]"/></h3> 
    2728 
     
    5657                <div> 
    5758                        <g:checkBox name="${entry.key.authority}" value="${entry.value}"/> 
    58                         <g:link controller='role' action='edit' id='${entry.key.id}'>${entry.key.authority.encodeAsHTML()}</g:link> 
     59                        ${entry.key.authority.encodeAsHTML()} 
    5960                </div> 
    6061                </g:each>