Changeset 1257

Show
Ignore:
Timestamp:
09-12-10 21:12:10 (3 years ago)
Author:
robert@…
Message:

Added an export and import functionality for templates, as described in ticket #76

Location:
trunk
Files:
9 added
10 modified

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/controllers/dbnp/studycapturing/TemplateController.groovy

    r959 r1257  
    1515package dbnp.studycapturing 
    1616 
     17// Automatic marshalling of XML and JSON 
     18import grails.converters.* 
     19import grails.plugins.springsecurity.Secured 
     20import dbnp.authentication.AuthenticationService 
     21 
     22@Secured(['IS_AUTHENTICATED_REMEMBERED']) 
    1723class TemplateController { 
    18         def scaffold = Template 
     24        def authenticationService 
     25 
     26        /** 
     27         * Shows a form to pick a file to import templates 
     28         */ 
     29        def importTemplate = { 
     30        } 
     31 
     32        /** 
     33         * Handles file import 
     34         */ 
     35        def handleImportedFile = { 
     36                if( !request.getFile("file") ) { 
     37                        flash.message = "No file given."; 
     38                        redirect( action: 'importTemplate' ); 
     39                        return; 
     40                } 
     41 
     42                // Parse XML 
     43                def xml 
     44                 
     45                try { 
     46                        xml = XML.parse( request.getFile("file").inputStream.text ) 
     47                } catch( Exception e ) { 
     48                        // Error in parsing. Probably the file is not a XML file 
     49                        flash.message = "Imported file could not be read. Please specify an XML template file."; 
     50                        redirect( action: 'importTemplate' ); 
     51                } 
     52                 
     53                def numTemplates = xml.@count; 
     54 
     55                if( !xml.template ) { 
     56                        flash.message = "No templates could be found in the imported file. Please specify an XML template file."; 
     57                        redirect( action: 'importTemplate' ); 
     58                } 
     59 
     60                // Check whether the templates already exist 
     61                def templates = [] 
     62                def id = 0; 
     63                xml.template.each { template -> 
     64                        try { 
     65                                def t = Template.parse( template, authenticationService.getLoggedInUser() ); 
     66 
     67                                def templateData = [:] 
     68                                templateData.key = id++; 
     69                                templateData.template = t 
     70                                templateData.alternatives = [] 
     71 
     72                                // If a template exists that equals this xml template , return it. 
     73                                for( def otherTemplate in Template.findAllByEntity( t.entity ) ) { 
     74                                        if( t.contentEquals( otherTemplate ) ) { 
     75                                                templateData.alternatives << otherTemplate; 
     76                                        } 
     77                                } 
     78 
     79                                templates << templateData 
     80                        } catch (Exception e) { 
     81                                templates << [ template: null, error: "Template " + ( template.name ?: " without name" ) + " could not be parsed"]; 
     82                        } 
     83                } 
     84 
     85                // Save templates in session in order to have data available in the next (import) step 
     86                session.templates = templates 
     87                 
     88                [templates: templates] 
     89        } 
     90 
     91        /** 
     92         * Saves the imported templates that the user has chosen 
     93         */ 
     94        def saveImportedTemplates = { 
     95                def ids = params.selectedTemplate 
     96                def templates = session.templates 
     97                def messages = [] 
     98                 
     99                // Save all selected templates 
     100                ids.each { id -> 
     101                        def templateData = templates.find { template -> template.key == id.toLong() } 
     102                        def importTemplate = templateData?.template 
     103                        println id + ": " + templateData 
     104 
     105                        if( !importTemplate ) { 
     106                                messages << "Template with id " + id + " could not be found." 
     107                        } else { 
     108                                def originalName = importTemplate.name 
     109                                def newName = null 
     110 
     111                                // Check whether a new name has been given 
     112                                if( params[ 'templateNames_' + id ] && params[ 'templateNames_' + id ] != importTemplate.name ) { 
     113                                        importTemplate.name = params[ 'templateNames_' + id ] 
     114                                        newName = params[ 'templateNames_' + id ] 
     115                                } 
     116 
     117                                if( importTemplate.save() ) { 
     118                                        messages << "Template " + originalName + " saved" + ( newName ? " as " + newName : "" ) 
     119                                } else { 
     120                                        messages << "Template " + originalName + " could not be saved" 
     121                                } 
     122                        } 
     123                } 
     124 
     125                // Remove templates from the session 
     126                session.templates = null 
     127 
     128                [messages: messages] 
     129        } 
     130 
     131        /** 
     132         * Shows a form to select templates for export 
     133         */ 
     134        def export = { 
     135                // If the templates are already selected, export them 
     136                if( params.templates ) { 
     137                        if( !( params.templates instanceof String ) ) { 
     138                                params.templates = params.templates.join(",") 
     139                        } 
     140 
     141                        switch( params.type ) { 
     142                                case "xml": 
     143                                default: 
     144                                        xml(); 
     145                                        return 
     146                        } 
     147                        return; 
     148                } else { 
     149                        [templates: Template.findAll()] 
     150                } 
     151        } 
     152 
     153        /** 
     154         * XML Export of given templates, or all templates if no templates are given 
     155         */ 
     156        def xml = { 
     157                def templates 
     158                if( params.templates ) { 
     159                        def ids = []; 
     160                        params.templates.split(",").each { ids << it.toLong() } 
     161 
     162                        def c = Template.createCriteria() 
     163                        templates = c { 
     164                                'in'("id", ids) 
     165                        } 
     166                } else { 
     167                        templates = Template.findAll() 
     168                } 
     169                 
     170                response.setHeader "Content-disposition", "attachment; filename=templates.xml" 
     171 
     172                render(view: 'xml', contentType:"text/xml", model: [templates: templates]) 
     173        } 
     174 
    19175} 
  • trunk/grails-app/controllers/dbnp/studycapturing/TemplateEditorController.groovy

    r1175 r1257  
    2828    def entityName; 
    2929    def entity; 
    30         def AuthenticationService 
     30        def authenticationService 
    3131 
    3232        /** 
  • trunk/grails-app/domain/dbnp/studycapturing/TemplateEntity.groovy

    r1245 r1257  
    781781                } 
    782782        } 
     783 
     784    /** 
     785     * Returns a Class object given by the entityname, but only if it is a subclass of TemplateEntity 
     786         * 
     787         * @return A class object of the given entity, null if the entity is not a subclass of TemplateEntity 
     788         * @throws ClassNotFoundException 
     789     */ 
     790    static Class parseEntity( String entityName ) { 
     791                if( entityName == null ) 
     792                        return null 
     793 
     794        // Find the templates 
     795        def entity = Class.forName(entityName, true, Thread.currentThread().getContextClassLoader()) 
     796 
     797        // succes, is entity an instance of TemplateEntity? 
     798        if (entity?.superclass =~ /TemplateEntity$/ || entity?.superclass?.superclass =~ /TemplateEntity$/) { 
     799            return entity; 
     800        } else { 
     801            return null; 
     802        } 
     803 
     804    } 
    783805} 
  • trunk/grails-app/domain/dbnp/studycapturing/TemplateField.groovy

    r1213 r1257  
    366366        } 
    367367 
     368 
     369        /** 
     370         * Check whether the contents of the other templatefield and the current templatefield are equal. 
     371         * For this check the comments field doesn't matter.  
     372         * 
     373         * @return      true iff this template field equals the other template field 
     374         *                      (the comments field may be different) 
     375         */ 
     376        public boolean contentEquals( Object otherObject ) { 
     377                if( !( otherObject instanceof TemplateField ) ) 
     378                        return false 
     379 
     380                TemplateField otherField = (TemplateField) otherObject; 
     381 
     382                if( otherField == this ) 
     383                        return true 
     384 
     385                if( otherField == null ) 
     386                        return false 
     387 
     388                if( otherField.entity != this.entity ) { 
     389                        return false 
     390                } 
     391                if( otherField.name != this.name ) { 
     392                        return false 
     393                } 
     394                if( otherField.type != this.type ) { 
     395                        return false 
     396                } 
     397                if( otherField.unit != this.unit ) { 
     398                        return false 
     399                } 
     400                if( otherField.required != this.required ) { 
     401                        return false 
     402                } 
     403 
     404                if( otherField.preferredIdentifier != this.preferredIdentifier ) { 
     405                        return false 
     406                } 
     407 
     408                // Check whether the list entries are equal (except for the order) 
     409                def size1 = otherField.listEntries?.size() ?: 0 
     410                def size2 = this.listEntries?.size() ?: 0 
     411                if( size1 != size2 ) { 
     412                        return false 
     413                } 
     414                 
     415                if( otherField.listEntries != null && this.listEntries != null ) { 
     416                        for( def entry in this.listEntries ) { 
     417                                def entryFound = false; 
     418                                for( def otherEntry in otherField.listEntries ) { 
     419                                        if( otherEntry.name == entry.name ) { 
     420                                                entryFound = true; 
     421                                                break 
     422                                        } 
     423                                } 
     424 
     425                                if( !entryFound ) { 
     426                                        return false 
     427                                } 
     428                        } 
     429                } 
     430                 
     431                // Check whether the ontologies are equal (except for the order) 
     432                size1 = otherField.ontologies?.size() ?: 0 
     433                size2 = this.ontologies?.size() ?: 0 
     434                if( size1 != size2 ) { 
     435                        return false 
     436                } 
     437                if( this.ontologies != null && otherField.ontologies != null ) { 
     438                        for( def ontology in this.ontologies ) { 
     439                                if( !otherField.ontologies.contains( ontology ) ) { 
     440                                        return false 
     441                                } 
     442                        } 
     443                } 
     444                 
     445                // If all tests pass, the objects are content-equal 
     446                return true 
     447        } 
     448 
     449        /** 
     450         * Create a new template field based on the parsed XML object.  
     451         * 
     452         * @see grails.converters.XML#parse(java.lang.String) 
     453         * @throws IllegalArgumentException  
     454         */ 
     455        public static parse(Object xmlObject, Class entity) { 
     456                def t = new TemplateField(); 
     457 
     458                t.name = xmlObject?.name?.text() 
     459                t.unit = xmlObject?.unit?.text() == "" ? null : xmlObject?.unit?.text() 
     460                t.comment = xmlObject?.comment?.text() 
     461                t.required = xmlObject?.required?.text() == 'true' ? true : false 
     462                t.preferredIdentifier = xmlObject?.preferredIdentifier?.text() == 'true' ? true : false 
     463 
     464                t.entity = entity 
     465 
     466                t.type = TemplateFieldType.valueOf( xmlObject?.type?.text() ) 
     467 
     468                // Search for ontologies 
     469                xmlObject.ontologies?.ontology.each { 
     470                        def ncboId = it.ncboId?.text(); 
     471                        t.addToOntologies( Ontology.getOrCreateOntologyByNcboId( ncboId ) ); 
     472                } 
     473 
     474                // Search for list entries 
     475                xmlObject.listItems?.listItem.each { 
     476                        t.addToListEntries( new TemplateFieldListItem( name: it.name?.text() ) ); 
     477                } 
     478                return t; 
     479        } 
     480 
     481 
    368482} 
  • trunk/grails-app/domain/dbnp/studycapturing/Template.groovy

    r1027 r1257  
    123123 
    124124        /** 
     125         * Check whether the contents of the other template and the current template are equal. 
     126         * For this check the name, description and owner don't matter. Also, the order of 
     127         * template fields doesn't matter 
     128         * 
     129         * @return      true iff this template and the other template are used for the same entity and 
     130         *                      the template contain the same template fields 
     131         */ 
     132        public boolean contentEquals( Template otherTemplate ) { 
     133                if( otherTemplate == this ) 
     134                        return true 
     135 
     136                if( otherTemplate == null ) 
     137                        return false 
     138 
     139                if( otherTemplate.entity != this.entity ) 
     140                        return false 
     141 
     142                // Check all template fields 
     143                if( otherTemplate.fields?.size() != this.fields?.size() ) 
     144                        return false 
     145 
     146                if( otherTemplate.fields != null && this.fields != null ) { 
     147                        for( def field in this.fields ) { 
     148                                def fieldFound = false; 
     149                                for( def otherField in otherTemplate.fields ) { 
     150                                        if( otherField.contentEquals( field ) ) { 
     151                                                fieldFound = true; 
     152                                                break 
     153                                        } 
     154                                } 
     155 
     156                                if( !fieldFound ) { 
     157                                        return false 
     158                                } 
     159                        } 
     160                } 
     161 
     162                // If all tests pass, the objects are content-equal 
     163                return true 
     164        } 
     165 
     166        /** 
    125167         * Look up the type of a certain template subject field 
    126168         * @param String fieldName The name of the template field 
     
    210252                return results 
    211253        } 
     254 
     255        /** 
     256         * Create a new template based on the parsed XML object.  
     257         * 
     258         * @see grails.converters.XML#parse(java.lang.String) 
     259         * @throws IllegalArgumentException 
     260         * @throws ClassNotFoundException 
     261         * 
     262         */ 
     263        public static parse(Object xmlObject, SecUser loggedInUser) { 
     264                def t = new Template(); 
     265                t.name = xmlObject?.name?.text() 
     266                t.description = xmlObject?.description?.text() 
     267 
     268                // Check whether a correct entity is given. The parseEntity method might 
     269                // throw a ClassNotFoundException, but that is OK, it should be thrown if the class 
     270                // doesn't exist. 
     271                def entity = TemplateEntity.parseEntity( xmlObject.entity?.text() ); 
     272                if( !entity ) { 
     273                        throw new Exception( "Incorrect entity given" ); 
     274                } 
     275 
     276                t.entity = entity 
     277 
     278                // Set the owner to the currently logged in user 
     279                t.owner = loggedInUser 
     280 
     281                // Set all template fields 
     282                xmlObject.templateFields.templateField.each { 
     283                        def field = TemplateField.parse( it, entity ); 
     284 
     285                        // Check whether a similar field already exists. For that, we search in all 
     286                        // template fields with the same name, in order to have as little comparisons 
     287                        // as possible 
     288                        for( def otherField in TemplateField.findAllByName( field.name ) ) { 
     289                                if( field.contentEquals( otherField ) ) { 
     290                                        field = otherField; 
     291                                        break; 
     292                                } 
     293                        } 
     294                         
     295                        t.addToFields( field ); 
     296                } 
     297 
     298                return t 
     299        } 
    212300} 
  • trunk/grails-app/views/common/_topnav.gsp

    r1150 r1257  
    2828                        <li><g:link controller="templateEditor" action="sample" params="${[standalone: true]}">Sample templates</g:link></li> 
    2929                        <li><g:link controller="templateEditor" action="assay" params="${[standalone: true]}">Assay templates</g:link></li> 
     30                        <li><g:link controller="template" action="export">Export</g:link></li> 
     31                        <li><g:link controller="template" action="importTemplate">Import</g:link></li> 
    3032                </ul> 
    3133        </li> 
  • trunk/grails-app/views/templateEditor/elements/_disabledFieldForm.gsp

    r1175 r1257  
    1818 
    1919          <label for="type">Extra ontologies:<br /><br /><a href="#" style="text-decoration: underline;" onClick="openOntologyDialog();">Add new</a></label> 
    20                 <g:select multiple="yes" size="5" from="${ontologies - templateField?.getUsedOntologies()}" class="ontologySelect" optionValue="name" optionKey="id" name="ontologies" id="ontologies_${templateField?.id}" value="${templateField?.getNonUsedOntologies()}" /><br /> 
     20                <g:select multiple="yes" size="5" from="${ (ontologies ?: [])- templateField?.getUsedOntologies()}" class="ontologySelect" optionValue="name" optionKey="id" name="ontologies" id="ontologies_${templateField?.id}" value="${templateField?.getNonUsedOntologies()}" /><br /> 
    2121 
    2222        </div> 
  • trunk/test/unit/dbnp/studycapturing/TemplateFieldTests.groovy

    r959 r1257  
    22 
    33import grails.test.* 
     4import dbnp.data.Ontology 
    45 
    56class TemplateFieldTests extends GrailsUnitTestCase { 
     
    185186            fail(); 
    186187        } 
     188    } 
     189 
     190    void testContentEquals() { 
     191                // Check whether the fields matter 
     192                TemplateField tf1 = new TemplateField( entity: dbnp.studycapturing.Subject, name: 'Weight', type: TemplateFieldType.LONG, unit: 'kg', comments: 'Weight field' ) 
     193                TemplateField tf2 = new TemplateField( entity: dbnp.studycapturing.Subject, name: 'Weight', type: TemplateFieldType.LONG,  unit: 'kg', comments: 'Weight field 2' ) 
     194                TemplateField tf3 = new TemplateField( entity: dbnp.studycapturing.Subject, name: 'Length', type: TemplateFieldType.LONG,  unit: 'm', comments: 'Length field' ) 
     195                TemplateField tf4 = new TemplateField( entity: dbnp.studycapturing.Subject, name: 'Length', type: TemplateFieldType.LONG,  unit: 'm', comments: 'Length field', required: true ) 
     196                TemplateField tf5 = new TemplateField( entity: dbnp.studycapturing.Study, name: 'Length', type: TemplateFieldType.LONG,  unit: 'm', comments: 'Length field', required: true ) 
     197 
     198                TemplateField tf6 = new TemplateField( entity: dbnp.studycapturing.Subject, name: 'Species', type: TemplateFieldType.ONTOLOGYTERM ) 
     199                TemplateField tf7 = new TemplateField( entity: dbnp.studycapturing.Subject, name: 'Species', type: TemplateFieldType.ONTOLOGYTERM ) 
     200 
     201                TemplateField tf8 = new TemplateField( entity: dbnp.studycapturing.Subject, name: 'Species', type: TemplateFieldType.STRINGLIST ) 
     202                TemplateField tf9 = new TemplateField( entity: dbnp.studycapturing.Subject, name: 'Species', type: TemplateFieldType.STRINGLIST ) 
     203 
     204                mockDomain( TemplateField, [tf1, tf2, tf3, tf4, tf5, tf6, tf7, tf8, tf9] ); 
     205 
     206                assert( tf1.contentEquals( tf1 ) ); 
     207                assert( tf1.contentEquals( tf2 ) ); 
     208                assert( tf2.contentEquals( tf1 ) ); 
     209                assert( !tf1.contentEquals( tf3 ) ); 
     210                assert( !tf3.contentEquals( tf4 ) ); 
     211                assert( !tf5.contentEquals( tf4 ) ); 
     212 
     213                // Test ontology fields 
     214                Ontology o1 = new Ontology( ncboId: 1000, ncboVersionedId: 14192, name: "Ontology 1" ) 
     215                Ontology o2 = new Ontology( ncboId: 1000, ncboVersionedId: 14192, name: "Ontology 2" ) 
     216                Ontology o3 = new Ontology( ncboId: 1000, ncboVersionedId: 5123, name: "Ontology 3" ) 
     217                Ontology o4 = new Ontology( ncboId: 4123, ncboVersionedId: 14192, name: "Ontology 4" ) 
     218 
     219                tf6.addToOntologies( o1 ) 
     220 
     221                // Different number of ontologies 
     222                assert( !tf6.contentEquals( tf7 ) ); 
     223 
     224                tf7.addToOntologies( o1 ); 
     225 
     226                // Same ontologies 
     227                assert( tf6.contentEquals( tf7 ) ); 
     228 
     229                tf7.ontologies.clear() 
     230                tf7.addToOntologies( o2 ); 
     231 
     232                // Ontologies with the same ncboId 
     233                assert( !tf6.contentEquals( tf7 ) ); 
     234 
     235                tf6.ontologies.clear(); tf7.ontologies.clear() 
     236                tf6.addToOntologies( o1 ) 
     237                tf6.addToOntologies( o4 ) 
     238                tf7.addToOntologies( o4 ); 
     239                tf7.addToOntologies( o1 ); 
     240 
     241                // Different order but same ontologies 
     242                assert( tf6.contentEquals( tf7 ) ); 
     243 
     244                // Test listentries 
     245 
     246                assert( tf8.contentEquals( tf9 ) ); 
     247 
     248                TemplateFieldListItem l1 = new TemplateFieldListItem( name: 'string1' ); 
     249                TemplateFieldListItem l2 = new TemplateFieldListItem( name: 'string1' ); 
     250                TemplateFieldListItem l3 = new TemplateFieldListItem( name: 'string2' ); 
     251                TemplateFieldListItem l4 = new TemplateFieldListItem( name: 'string3' ); 
     252 
     253                tf8.addToListEntries( l1 ); 
     254 
     255                // Different number of list entries 
     256                assert( !tf8.contentEquals( tf9 ) ); 
     257 
     258                tf9.addToListEntries( l1 ); 
     259 
     260                // Same list entries 
     261                assert( tf8.contentEquals( tf9 ) ); 
     262 
     263                tf9.listEntries.clear(); 
     264                tf9.addToListEntries( l2 ); 
     265 
     266                // Different list entries with the same name 
     267                assert( tf8.contentEquals( tf9 ) ); 
     268 
     269                tf9.listEntries.clear(); 
     270                tf9.addToListEntries( l3 ); 
     271 
     272                // Different list entries 
     273                assert( !tf8.contentEquals( tf9 ) ); 
     274 
     275                // Same entries but different order 
     276                tf8.listEntries.clear(); 
     277                tf9.listEntries.clear(); 
     278                tf8.addToListEntries( l2 ); 
     279                tf8.addToListEntries( l3 ); 
     280                tf9.addToListEntries( l3 ); 
     281                tf9.addToListEntries( l2 ); 
     282 
     283                // Different order but same list entries 
     284                assert( tf8.contentEquals( tf9 ) ); 
    187285 
    188286    } 
  • trunk/test/unit/dbnp/studycapturing/TemplateTests.groovy

    r959 r1257  
    22 
    33import grails.test.* 
     4import dbnp.authentication.* 
    45 
    56class TemplateTests extends GrailsUnitTestCase { 
     
    2728                assert t2.inUse(); 
    2829                assert !t3.inUse(); 
     30    } 
     31 
     32    void testContentEquals() { 
     33                // Basic checks 
     34                Template t1 = new Template( entity: dbnp.studycapturing.Subject ); 
     35                Template t2 = new Template( entity: dbnp.studycapturing.Subject ); 
     36                Template t3 = new Template( entity: dbnp.studycapturing.Study ); 
     37 
     38                mockDomain( Template, [t1, t2, t3] ); 
     39 
     40                assert t1.contentEquals( t1 ); 
     41                assert t1.contentEquals( t2 ); 
     42                assert t2.contentEquals( t1 ); 
     43                assert !t3.contentEquals( t1 ); 
     44                assert !t2.contentEquals( t3 ); 
     45 
     46                // Check whether other fields matter 
     47                t1.name = "Test 1"; 
     48                t1.description = "Long description" 
     49                t1.owner = new SecUser( username: "TestUser" ) 
     50                t2.name = "Test 2"; 
     51                t2.description = "Short description" 
     52 
     53                assert( t1.contentEquals( t2 ) ); 
     54 
     55                // Check whether the fields matter 
     56                TemplateField tf1 = new TemplateField( entity: dbnp.studycapturing.Subject, name: 'Weight', type: TemplateFieldType.LONG,  unit: 'kg', comment: 'Weight field' ) 
     57                TemplateField tf2 = new TemplateField( entity: dbnp.studycapturing.Subject, name: 'Weight', type: TemplateFieldType.LONG,  unit: 'kg', comment: 'Weight field 2' ) 
     58                TemplateField tf3 = new TemplateField( entity: dbnp.studycapturing.Subject, name: 'Length', type: TemplateFieldType.LONG,  unit: 'm', comment: 'Length field' ) 
     59                TemplateField tf4 = new TemplateField( entity: dbnp.studycapturing.Subject, name: 'BMI', type: TemplateFieldType.LONG,  unit: 'kg/m2', comment: 'BMI field', required: true ) 
     60 
     61                mockDomain( TemplateField, [tf1, tf2, tf3, tf4] ); 
     62 
     63                t1.addToFields( tf1 ); 
     64                t2.addToFields( tf1 ); 
     65 
     66                // Same fields 
     67                assert( t1.contentEquals( t2 ) ); 
     68 
     69                t1.fields.clear(); 
     70                t1.addToFields( tf2 ); 
     71 
     72                // Fields with equal properties 
     73                assert( t1.contentEquals( t2 ) ); 
     74 
     75                t1.fields.clear(); 
     76                t1.addToFields( tf3 ); 
     77 
     78                // Fields with inequal properties 
     79                assert( !t1.contentEquals( t2 ) ); 
     80 
     81                t1.addToFields( tf1 ); 
     82                t2.addToFields( tf3 ); 
     83 
     84                // Same fields in different order 
     85                assert( t1.contentEquals( t2 ) ); 
     86 
     87                t1.addToFields( tf4 ) 
     88 
     89                // Different number of fields 
     90                assert( !t1.contentEquals( t2 ) ); 
    2991 
    3092    } 
     93 
    3194} 
  • trunk/web-app/css/templateEditor.css

    r1136 r1257  
    129129.longTitle { display: none; } 
    130130 
    131  
    132  
    133131/* Add Ontology dialog */ 
    134132#addOntology { list-style-type: none; padding-left: 0; } 
     
    137135#addOntology li .check { float: left; margin-left: -15px; margin-top: 2px; } 
    138136 
     137/* Importer */ 
     138#importTemplates h3 { margin-top: 0; } 
     139#importTemplates ol.fields { margin-top: 0; } 
     140#importTemplates .otherTemplateName { display: none; } 
     141#importTemplates .error { color: #AA0000; }