Changeset ddbc82 in indico


Ignore:
Timestamp:
02/22/11 11:05:06 (2 years ago)
Author:
Jose Benito <jose.benito.gonzalez@…>
Branches:
master, burotel, hello-world-walkthrough, ipv6, v0.98-series, v0.98.2, v0.98.3, v0.98b1, v0.98b2, v0.99, 051b2622c51afb171a1dedb46a0df4fbb0cbd02e, 0da0c1403bae8e51d8229f460181c71b9e6dda72
Children:
0e7b55
Parents:
c099cd
git-author:
Adrian Moennich <jerome.ernst.monnich@…> (01/10/11 18:26:20)
git-committer:
Jose Benito <jose.benito.gonzalez@…> (02/22/11 11:05:06)
Message:

[IMP] Allow multiple materials to be added at once

  • add "more" link to add material dialog
  • hide "advanced" tab when adding multiple materials
  • make dialog growable to avoid scrolling issues
  • fix dialog positioning with small resolutions (force top position >=0)
  • fixes #598
Location:
indico
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • indico/MaKaC/webinterface/rh/conferenceBase.py

    ra370da rddbc82  
    210210        self._target=target 
    211211        self._callerRH = rh 
    212         self._repositoryId = None 
     212        #self._repositoryId = None 
    213213 
    214214    def _getNewTempFile( self ): 
     
    233233        #if request has already been handled (DB conflict), then we keep the existing files list 
    234234 
    235         self._file = {} 
    236         self._link = {} 
     235        self._files = [] 
     236        self._links = [] 
    237237        self._topdf=params.has_key("topdf") 
    238238 
     
    249249 
    250250        if self._uploadType == "file": 
    251             if type(params["file"]) != str and params["file"].filename.strip() != "": 
    252                 fDict = {} 
    253                 fDict["filePath"]=self._saveFileToTemp(params["file"].file) 
    254  
    255                 if self._callerRH != None: 
    256                     self._callerRH._tempFilesToDelete.append(fDict["filePath"]) 
    257  
    258                 fDict["fileName"]=params["file"].filename 
    259                 fDict["size"] = int(os.stat(fDict["filePath"])[stat.ST_SIZE]) 
    260                 self._file = fDict 
     251            if isinstance(params["file"], list): 
     252                files = params["file"] 
     253                self._displayName = "" 
     254                self._description = "" 
     255            else: 
     256                files = [params["file"]] 
     257 
     258            for fileUpload in files: 
     259                if type(fileUpload) != str and fileUpload.filename.strip() != "": 
     260                    fDict = {} 
     261                    fDict["filePath"] = self._saveFileToTemp(fileUpload.file) 
     262 
     263                    if self._callerRH != None: 
     264                        self._callerRH._tempFilesToDelete.append(fDict["filePath"]) 
     265 
     266                    fDict["fileName"] = fileUpload.filename 
     267                    fDict["size"] = int(os.stat(fDict["filePath"])[stat.ST_SIZE]) 
     268                    self._files.append(fDict) 
    261269 
    262270        elif self._uploadType == "link": 
    263             link={} 
    264             link["url"]=params.get("url","") 
    265             link["matType"]=params.get("materialType","") 
    266             self._link = link 
     271            if isinstance(params["url"], list): 
     272                urls = params["url"] 
     273                self._displayName = "" 
     274                self._description = "" 
     275            else: 
     276                urls =  [params["url"]] 
     277 
     278            matType = params.get("materialType", "") 
     279            for url in urls: 
     280                link = {} 
     281                link["url"] = url 
     282                link["matType"] = matType 
     283                self._links.append(link) 
     284 
    267285 
    268286    def _getErrorList(self): 
     
    270288 
    271289        if self._uploadType == "file": 
    272             if self._file == {}: 
     290            if not self._files: 
    273291                res.append("""A file must be submitted.""") 
    274             if hasattr(self._file, "filePath") and self._file["filePath"].strip()=="": 
    275                 res.append("""A valid file to be submitted must be specified.""") 
    276             if hasattr(self._file, "size") and self._file["size"] < 10: 
    277                 res.append("""The file %s seems to be empty""" % self._file["fileName"]) 
     292            for fileEntry in self._files: 
     293                if hasattr(fileEntry, "filePath") and not fileEntry["filePath"].strip(): 
     294                    res.append("""A valid file to be submitted must be specified.""") 
     295                if hasattr(fileEntry, "size") and fileEntry["size"] < 10: 
     296                    res.append("""The file %s seems to be empty""" % fileEntry["fileName"]) 
    278297        elif self._uploadType == "link": 
    279             if self._link["url"].strip()=="": 
     298            if not self._links[0]["url"].strip(): 
    280299                res.append("""A valid URL must be specified.""") 
    281300 
     
    329348            protectedAtResourceLevel = True 
    330349 
     350        resources = [] 
    331351        if self._uploadType in ['file','link']: 
    332352            if self._uploadType == "file": 
    333353 
    334                 resource = LocalFile() 
    335                 resource.setFileName(self._file["fileName"]) 
    336                 resource.setFilePath(self._file["filePath"]) 
    337                 resource.setDescription(self._description) 
    338                 if self._displayName == "": 
    339                     resource.setName(resource.getFileName()) 
    340                 else: 
    341                     resource.setName(self._displayName) 
    342  
    343                 if not type(self._target) is Category: 
    344                     self._target.getConference().getLogHandler().logAction({"subject":"Added file %s%s" % (self._file["fileName"],text)},"Files",user) 
    345                 # in case of db conflict we do not want to send the file to conversion again, nor re-store the file 
     354                for fileEntry in self._files: 
     355                    resource = LocalFile() 
     356                    resource.setFileName(fileEntry["fileName"]) 
     357                    resource.setFilePath(fileEntry["filePath"]) 
     358                    resource.setDescription(self._description) 
     359                    if self._displayName == "": 
     360                        resource.setName(resource.getFileName()) 
     361                    else: 
     362                        resource.setName(self._displayName) 
     363 
     364                    if not type(self._target) is Category: 
     365                        self._target.getConference().getLogHandler().logAction({"subject":"Added file %s%s" % (fileEntry["fileName"], text)}, "Files", user) 
     366                    resources.append(resource) 
     367                    # in case of db conflict we do not want to send the file to conversion again, nor re-store the file 
    346368 
    347369            elif self._uploadType == "link": 
    348370 
    349                 resource = Link() 
    350                 resource.setURL(self._link["url"]) 
    351                 resource.setDescription(self._description) 
    352                 if self._displayName == "": 
    353                     resource.setName(resource.getURL()) 
    354                 else: 
    355                     resource.setName(self._displayName) 
    356  
    357                 if not type(self._target) is Category: 
    358                     self._target.getConference().getLogHandler().logAction({"subject":"Added link %s%s" % (resource.getURL(),text)},"Files",user) 
     371                for link in self._links: 
     372                    resource = Link() 
     373                    resource.setURL(link["url"]) 
     374                    resource.setDescription(self._description) 
     375                    if self._displayName == "": 
     376                        resource.setName(resource.getURL()) 
     377                    else: 
     378                        resource.setName(self._displayName) 
     379 
     380                    if not type(self._target) is Category: 
     381                        self._target.getConference().getLogHandler().logAction({"subject":"Added link %s%s" % (resource.getURL(), text)}, "Files", user) 
     382                    resources.append(resource) 
    359383 
    360384            status = "OK" 
    361             info = resource 
     385            info = resources 
    362386        else: 
    363387            status = "ERROR" 
     
    365389            return mat, status, info 
    366390 
     391        from MaKaC.user import AvatarHolder, GroupHolder 
     392 
     393        toPdf = self._topdf 
     394        self._topdf = False 
     395 
    367396        # forcedFileId - in case there is a conflict, use the file that is 
    368397        # already stored 
    369         mat.addResource(resource, forcedFileId=self._repositoryId) 
    370  
    371         #apply conversion 
    372         if self._topdf and fileConverter.CDSConvFileConverter.hasAvailableConversionsFor(os.path.splitext(resource.getFileName())[1].strip().lower()): 
    373             Logger.get('conv').debug('Queueing %s for conversion' % resource.getFilePath()) 
    374  
    375             fileConverter.CDSConvFileConverter.convert(resource.getFilePath(), "pdf", mat) 
    376  
    377         self._topdf = False 
    378  
    379         # store the repo id, for files 
    380         if isinstance(resource, LocalFile): 
    381             self._repositoryId = resource.getRepositoryId() 
    382  
    383         if protectedAtResourceLevel: 
    384             protectedObject = resource 
    385         else: 
    386             protectedObject = mat 
    387             mat.setHidden(self._visibility) 
    388             mat.setAccessKey(self._password) 
    389  
    390         protectedObject.setProtection(self._statusSelection) 
    391  
    392         from MaKaC.user import AvatarHolder, GroupHolder 
    393  
    394         for userElement in self._userList: 
    395             if 'isGroup' in userElement and userElement['isGroup']: 
    396                 avatar = GroupHolder().getById(userElement['id']) 
    397             else: 
    398                 avatar = AvatarHolder().getById(userElement['id']) 
    399             protectedObject.grantAccess(avatar) 
     398        for resource in resources: 
     399            #mat.addResource(resource, forcedFileId=self._repositoryId) 
     400            mat.addResource(resource, forcedFileId=None) 
     401 
     402            #apply conversion 
     403            if toPdf and fileConverter.CDSConvFileConverter.hasAvailableConversionsFor(os.path.splitext(resource.getFileName())[1].strip().lower()): 
     404                Logger.get('conv').debug('Queueing %s for conversion' % resource.getFilePath()) 
     405 
     406                fileConverter.CDSConvFileConverter.convert(resource.getFilePath(), "pdf", mat) 
     407 
     408            # store the repo id, for files 
     409            #if isinstance(resource, LocalFile): 
     410            #    self._repositoryId = resource.getRepositoryId() 
     411 
     412            if protectedAtResourceLevel: 
     413                protectedObject = resource 
     414            else: 
     415                protectedObject = mat 
     416                mat.setHidden(self._visibility) 
     417                mat.setAccessKey(self._password) 
     418 
     419                protectedObject.setProtection(self._statusSelection) 
     420 
     421            for userElement in self._userList: 
     422                if 'isGroup' in userElement and userElement['isGroup']: 
     423                    avatar = GroupHolder().getById(userElement['id']) 
     424                else: 
     425                    avatar = AvatarHolder().getById(userElement['id']) 
     426                protectedObject.grantAccess(avatar) 
    400427 
    401428        return mat, status, fossilize(info, {"MaKaC.conference.Link": ILinkFossil, 
     
    436463 
    437464                if status == "OK": 
    438                     info['material'] = mat.getId(); 
     465                    for entry in info: 
     466                        entry['material'] = mat.getId(); 
    439467        except Exception, e: 
    440468            status = "ERROR" 
  • indico/htdocs/js/indico/Core/Dialogs/Popup.js

    r45698e rddbc82  
    174174 
    175175        this.canvas.dom.style.left = pixels(left); 
    176         this.canvas.dom.style.top = pixels(top); 
     176        this.canvas.dom.style.top = top >= 0 ? pixels(top) : 0; 
    177177    }, 
    178178 
     
    283283    } 
    284284); 
     285 
     286/** 
     287 * Builds an exclusive popup with a button bar which can grow vertically 
     288 * Constructor arguments: the same ones as ExclusivePopup 
     289 */ 
     290type("ExclusivePopupWithButtonsGrowing", ["ExclusivePopupWithButtons"], { 
     291    /** 
     292     * Overloads ExclusivePopupWithButtons._adjustContentWrapper 
     293     */ 
     294    _adjustContentWrapper: function() { 
     295        this.contentWrapper.setStyle('padding', pixels(0)); 
     296        this.contentWrapper.setStyle('overflowY', 'auto'); 
     297        this.contentWrapper.setStyle('overflowX', 'hidden'); 
     298        this.contentWrapper.setStyle('position', 'relative'); 
     299        if (this.title && this.title !== '') { 
     300            this.contentWrapper.setStyle('top', pixels(-10)); 
     301        } else { 
     302            this.contentWrapper.setStyle('top', pixels(10)); 
     303        } 
     304    }, 
     305 
     306    lockHeight: function() { 
     307        var contentHeight = this._calculateContentHeight(); 
     308        this.contentWrapper.setStyle('height', pixels(contentHeight)); 
     309        // always show scroll bar as overflow:auto likes to hide content behind the scrollbar 
     310        this.contentWrapper.setStyle('overflowY', 'scroll'); 
     311        //this.contentWrapper.setStyle('paddingRight', pixels(8)); 
     312    } 
     313}, 
     314    function(title, closeButtonHandler, printable, showPrintButton){ 
     315        this.ExclusivePopup(title, closeButtonHandler, printable, showPrintButton); 
     316    } 
     317); 
     318 
    285319 
    286320type("BalloonPopup", ["PopupDialog"], { 
  • indico/htdocs/js/indico/MaterialEditor/Editor.js

    ra25433 rddbc82  
    88 
    99 
    10 type("AddMaterialDialog", ["ExclusivePopupWithButtons"], { 
     10type("AddMaterialDialog", ["ExclusivePopupWithButtonsGrowing"], { 
    1111 
    1212    _drawButtons: function() { 
     
    6868     */ 
    6969    _drawResourcePathPane: function(locationSelector) { 
    70  
    71         var file = Html.input('file', {name: 'file'}); 
    72         var urlBox = Html.edit({name: 'url'}); 
     70        var MAX_MATERIAL_FIELDS = 5; 
     71        var MAX_GROW_MATERIAL_FIELDS = 3; 
     72        var files = [Html.input('file', {name: 'file'})]; 
     73        var urlBoxes = [Html.edit({name: 'url'})]; 
    7374        var toPDFCheckbox = Html.checkbox({style: {verticalAlign: 'middle'}}, true); 
     75        var currentResourceLocation; 
    7476        toPDFCheckbox.dom.name = 'topdf'; 
    7577 
    7678        var self = this; 
     79 
     80        var addInputLink = Widget.link(command(function() { 
     81            if(files.length == MAX_GROW_MATERIAL_FIELDS || urlBoxes.length == MAX_GROW_MATERIAL_FIELDS) { 
     82                self.lockHeight(); 
     83            } 
     84 
     85            self.tabWidget.disableTab(2); 
     86            if(currentResourceLocation == 'local') { 
     87                files.push(Html.input('file', {name: 'file', style: {display: 'block'}})); 
     88            } 
     89            else { 
     90                urlBoxes.push(Html.edit({name: 'url'})); 
     91            } 
     92 
     93            // redraw resourcePathPane. is there an easier way?! 
     94            resourcePathPane.set(currentResourceLocation); 
     95        }, Html.span({}, ' ', $T("more")))); 
    7796 
    7897        var resourcePathPane = new Chooser( 
    7998            new Lookup({ 
    8099                'local':  function() { 
    81                     self.pm.remove(urlBox); 
    82                     return Html.div({}, 
    83                                     self.pm.add(file, 'text'), 
    84                                     Html.div({style:{marginTop: '5px'}}, 
    85                                              toPDFCheckbox, 
    86                                              Html.label({style: {verticalAlign: 'middle'}, className: 'emphasis'} 
    87                                                         , $T("Convert to PDF (when applicable)"))) 
    88                                    ); 
     100                    currentResourceLocation = 'local'; 
     101                    // remove url boxes 
     102                    for(var i = 0; i < urlBoxes.length; i++) { 
     103                        self.pm.remove(urlBoxes[i]); 
     104                    } 
     105                    // setup Html.div() args with all file upload fields etc. 
     106                    var args = [{}]; 
     107                    for(var i = 0; i < files.length; i++) { 
     108                        args.push(self.pm.add(files[i], 'text')); 
     109                        if(i == 0 && files.length < MAX_MATERIAL_FIELDS) { 
     110                            args.push(addInputLink); 
     111                        } 
     112                    } 
     113                    args.push(Html.div({style:{marginTop: '5px'}}, 
     114                            toPDFCheckbox, 
     115                            Html.label({style: {verticalAlign: 'middle'}, className: 'emphasis'}, 
     116                                    $T("Convert to PDF (when applicable)")))); 
     117 
     118                    return Html.div.apply(null, args); 
    89119                }, 
    90120                'remote': function() { 
    91                     self.pm.remove(file); 
    92                     setTimeout(function() { urlBox.dom.focus(); }, 200); 
    93                     return Html.div({}, 
    94                                     Html.label('popUpLabel', $T("URL")), 
    95                                     self.pm.add(urlBox, 'url'), 
    96                                     Html.div("smallGrey", $T("Example: http://www.example.com/YourPDFFile.pdf"))); 
     121                    currentResourceLocation = 'remote'; 
     122                    // remove file upload fields 
     123                    for(var i = 0; i < files.length; i++) { 
     124                        self.pm.remove(files[i]); 
     125                    } 
     126                    // setup Html.div() args with all url boxes etc. 
     127                    var args = [{}]; 
     128                    for(var i = 0; i < urlBoxes.length; i++) { 
     129                        var divArgs = [ 
     130                            {}, 
     131                            Html.label('popUpLabel', $T("URL")), 
     132                            self.pm.add(urlBoxes[i], 'url') 
     133                        ]; 
     134                        if(i == 0 && urlBoxes.length < MAX_MATERIAL_FIELDS) { 
     135                            divArgs.push(addInputLink); 
     136                        } 
     137                        args.push(Html.div.apply(null, divArgs)); 
     138                    } 
     139                    args.push(Html.div("smallGrey", $T("Example: http://www.example.com/YourPDFFile.pdf"))); 
     140                    setTimeout(function() { urlBoxes[0].dom.focus(); }, 200); 
     141                    return Html.div.apply(null, args); 
    97142                } 
    98143            })); 
     
    111156            // set the focus 
    112157            if (value == 'local') { 
    113                 file.dom.focus(); 
     158                files[0].dom.focus(); 
     159                if(self.tabWidget) { 
     160                    if(files.length == 1) { 
     161                        self.tabWidget.enableTab(2); 
     162                    } 
     163                    else { 
     164                        self.tabWidget.disableTab(2); 
     165                    } 
     166                } 
    114167            } else { 
    115                 urlBox.dom.focus(); 
     168                urlBoxes[0].dom.focus(); 
     169                if(self.tabWidget) { 
     170                    if(urlBoxes.length == 1) { 
     171                        self.tabWidget.enableTab(2); 
     172                    } 
     173                    else { 
     174                        self.tabWidget.disableTab(2); 
     175                    } 
     176                } 
    116177            } 
    117178        }); 
     
    14201481        }); 
    14211482 
    1422         var materialLoadFunction = function(info) { 
    1423             if (self.get(info.material)) { 
    1424                 self.get(info.material).get('resources').append(watchize(info)); 
    1425             } else { 
    1426                 self._loadMaterial(info.material); 
     1483        var materialLoadFunction = function(infoList) { 
     1484            for(var i = 0; i < infoList.length; i++) { 
     1485                var info = infoList[i]; 
     1486                if (self.get(info.material)) { 
     1487                    self.get(info.material).get('resources').append(watchize(info)); 
     1488                } else { 
     1489                    self._loadMaterial(info.material); 
     1490                } 
    14271491            } 
    14281492        }; 
Note: See TracChangeset for help on using the changeset viewer.