source: trunk/www/common/datafiles/select_files.jsp @ 5716

Last change on this file since 5716 was 5716, checked in by Nicklas Nordborg, 12 years ago

References #1604: Support for multiple files of the same type in a FileSet?

There is no "Validate" checkbox if none of the file types has a validator.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Id
File size: 17.2 KB
Line 
1<%-- $Id:select_files.jsp 3820 2007-10-12 10:03:18Z nicklas $
2  ------------------------------------------------------------------
3  Copyright (C) 2005 Nicklas Nordborg
4  Copyright (C) 2006 Jari Häkkinen, Nicklas Nordborg
5  Copyright (C) 2007 Nicklas Nordborg
6
7  This file is part of BASE - BioArray Software Environment.
8  Available at http://base.thep.lu.se/
9
10  BASE is free software; you can redistribute it and/or
11  modify it under the terms of the GNU General Public License
12  as published by the Free Software Foundation; either version 3
13  of the License, or (at your option) any later version.
14
15  BASE is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU General Public License for more details.
19
20  You should have received a copy of the GNU General Public License
21  along with BASE. If not, see <http://www.gnu.org/licenses/>.
22  ------------------------------------------------------------------
23 
24--%>
25<%@ page pageEncoding="UTF-8" session="false"
26  import="net.sf.basedb.core.SessionControl"
27  import="net.sf.basedb.core.DbControl"
28  import="net.sf.basedb.core.Item"
29  import="net.sf.basedb.core.ItemContext"
30  import="net.sf.basedb.core.Type"
31  import="net.sf.basedb.core.BasicItem"
32  import="net.sf.basedb.core.Permission"
33  import="net.sf.basedb.core.Nameable"
34  import="net.sf.basedb.core.FileStoreEnabled"
35  import="net.sf.basedb.core.FileSet"
36  import="net.sf.basedb.core.FileSetMember"
37  import="net.sf.basedb.core.File"
38  import="net.sf.basedb.core.Platform"
39  import="net.sf.basedb.core.PlatformVariant"
40  import="net.sf.basedb.core.PlatformFileType"
41  import="net.sf.basedb.core.UsableDataFileType"
42  import="net.sf.basedb.core.DataFileType"
43  import="net.sf.basedb.core.Subtypable"
44  import="net.sf.basedb.core.ItemSubtype"
45  import="net.sf.basedb.core.ItemQuery"
46  import="net.sf.basedb.core.Include"
47  import="net.sf.basedb.core.ItemResultList"
48  import="net.sf.basedb.core.PermissionDeniedException"
49  import="net.sf.basedb.core.query.Expressions"
50  import="net.sf.basedb.core.query.Restrictions"
51  import="net.sf.basedb.core.query.Hql"
52  import="net.sf.basedb.core.query.Orders"
53  import="net.sf.basedb.clients.web.Base"
54  import="net.sf.basedb.clients.web.util.HTML"
55  import="net.sf.basedb.util.formatter.Formatter"
56  import="net.sf.basedb.clients.web.formatter.FormatterFactory"
57  import="net.sf.basedb.clients.web.formatter.FormatterSettings"
58  import="net.sf.basedb.util.Values"
59  import="java.util.ArrayList"
60  import="java.util.List"
61  import="java.util.Date"
62  import="java.util.Map"
63  import="java.util.HashMap"
64%>
65<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
66<%
67final SessionControl sc = Base.getExistingSessionControl(pageContext, true);
68final String ID = sc.getId();
69final float scale = Base.getScale(sc);
70final Item itemType = Item.valueOf(request.getParameter("item_type"));
71final int itemId = Values.getInt(request.getParameter("item_id"));
72final int platformId = Values.getInt(request.getParameter("platform_id"), -1);
73final int variantId = Values.getInt(request.getParameter("variant_id"), -1);
74final int itemSubtypeId = Values.getInt(request.getParameter("itemsubtype_id"), -1);
75final ItemContext cc = sc.getCurrentContext(itemType);
76
77final DbControl dc = sc.newDbControl();
78try
79{
80
81  // Get the current item; null if we are editing a new item
82  final FileStoreEnabled item = itemId == 0 ? null : (FileStoreEnabled)itemType.getById(dc, itemId);
83  FileSet fileSet = null;
84  // Get the current files organized per data file type
85  Map<DataFileType, List<FileSetMember>> members = new HashMap<DataFileType, List<FileSetMember>>();
86  if (item != null && item.hasFileSet())
87  {
88    fileSet = item.getFileSet();
89    ItemQuery<FileSetMember> query = fileSet.getMembers();
90    query.order(Orders.asc(Hql.property("dataFileType.name")));
91    query.order(Orders.asc(Hql.property("file.name")));
92    List<FileSetMember> all = query.list(dc);
93    for (FileSetMember m : all)
94    {
95      DataFileType dft = m.getDataFileType();
96      List<FileSetMember> tmp = members.get(dft);
97      if (tmp == null)
98      {
99        tmp = new ArrayList<FileSetMember>();
100        members.put(dft, tmp);
101      }
102      tmp.add(m);
103    }
104  }
105
106  // Get the current platform/variant/itemsubtype
107  // -- if not submitted in URL use values from current item
108  PlatformVariant variant = null;
109  Platform platform = null;
110  ItemSubtype itemSubtype = null;
111  boolean deniedPlatform = false;
112  try
113  {
114    if (itemSubtypeId > 0)
115    {
116      itemSubtype = ItemSubtype.getById(dc, itemSubtypeId);
117    }
118    else if (item instanceof Subtypable)
119    {
120      itemSubtype = ((Subtypable)item).getItemSubtype();
121    }
122    if (variantId > 0)
123    {
124      variant = PlatformVariant.getById(dc, variantId);
125      platform = variant.getPlatform();
126    }
127    else if (platformId > 0)
128    {
129      platform = Platform.getById(dc, platformId);
130    }
131    else if (item != null)
132    {
133      variant = item.getVariant();
134      platform = item.getPlatform();
135    }
136  }
137  catch (PermissionDeniedException ex)
138  {
139    deniedPlatform = true; 
140  }
141 
142  // Query to load data file types for specific itemType/platform/variant
143  final ItemQuery<DataFileType> fileTypeQuery = 
144    Base.getDataFileTypes(itemType, item, platform, variant, itemSubtype);
145  List<DataFileType> fileTypes = fileTypeQuery.list(dc);
146  String title = "Select data files for " + 
147    HTML.encodeTags((item instanceof Nameable ? ((Nameable)item).getName() : 
148      (item == null ? " new item" : item.toString())));
149
150  final String clazz = "class=\"text\"";
151  final String requiredClazz = "class=\"text required\"";
152  %>
153  <base:page type="popup" title="<%=title%>">
154  <base:head >
155 
156  <script language="JavaScript">
157  function init()
158  {
159    if (document.body.addEventListener)
160    {
161      // Mozilla
162      document.body.addEventListener('click', hideVisibleRecentFilesDiv, false);
163    }
164    else
165    {
166      // IE.
167      document.body.onclick = hideVisibleRecentFilesDiv;
168    }
169  }
170 
171  var lastFileTypeId;
172  var lastHasValidator = false;
173  function addFilesOnClick(fileTypeId, extension, hasValidator)
174  {
175    var frm = document.forms['datafiles'];
176    var url = '../../filemanager/index.jsp?ID=<%=ID%>&cmd=SelectMultiple&callback=addFileCallback';
177    if (extension)
178    {
179      url += '&resetTemporary=1&tmpfilter:STRING:name='+escape('%.' + extension);
180    }
181    else
182    {
183      url += '&resetTemporary=1&filter:STRING:name=';
184    }
185    lastFileTypeId = fileTypeId;
186    lastHasValidator = hasValidator;
187    Main.openPopup(url, 'SelectFile', 1000, 700);
188  }
189  function addFileCallback(fileId, path)
190  {
191    addFile(lastFileTypeId, fileId, path, lastHasValidator);
192  }
193 
194  function browseOnClick(fileTypeId, extension, hasValidator)
195  {
196    var frm = document.forms['datafiles'];
197    var url = '../../filemanager/index.jsp?ID=<%=ID%>&cmd=SelectOne&callback=setFileCallback';
198    if (extension)
199    {
200      url += '&resetTemporary=1&tmpfilter:STRING:name='+escape('%.' + extension);
201    }
202    else
203    {
204      url += '&resetTemporary=1&filter:STRING:name=';
205    }
206    lastFileTypeId = fileTypeId;
207    lastHasValidator = hasValidator;
208    Main.openPopup(url, 'SelectFile', 1000, 700);
209  }
210  function setFileCallback(fileId, path)
211  {
212    setFile(lastFileTypeId, fileId, path, lastHasValidator);
213  }
214  function setFile(fileTypeId, fileId, path, hasValidator)
215  {
216    var frm = document.forms['datafiles'];
217    var fileDiv = document.getElementById('filelist.'+fileTypeId+'.file');
218    if (fileId)
219    {
220      fileDiv.innerHTML = '<div id="filelist.'+fileTypeId+'.'+fileId+'">'+path+'</div>';
221    }
222    else
223    {
224      fileDiv.innerHTML = '';
225    }
226    if (hasValidator) frm['datafiles.validate'].checked = true;
227    new FileAction('setfile', fileTypeId, fileId);
228  }
229  function addFile(fileTypeId, fileId, path, hasValidator)
230  {
231    var frm = document.forms['datafiles'];
232    var fileDiv = document.getElementById('filelist.'+fileTypeId+'.'+fileId);
233    if (fileDiv) return;
234   
235    fileDiv = document.createElement('div');
236    fileDiv.id = 'filelist.'+fileTypeId+'.'+fileId;
237    var html = path + '&nbsp;<img border=0 class="icon" style="cursor: pointer;" title="Remove this file" ';
238    html += ' onclick="removeFileOnClick(event, '+fileTypeId+','+fileId+','+hasValidator+')" src="/trunk/images/remove.png">';
239    fileDiv.innerHTML = html;
240    document.getElementById('filelist.'+fileTypeId+'.file').appendChild(fileDiv);
241    if (hasValidator) frm['datafiles.validate'].checked = true;
242    new FileAction('addfile', fileTypeId, fileId);
243  }
244  function removeFileOnClick(event, fileTypeId, fileId, hasValidator)
245  {
246    var frm = document.forms['datafiles'];
247    var fileDiv = document.getElementById('filelist.'+fileTypeId+'.'+fileId);
248    document.getElementById('filelist.'+fileTypeId+'.file').removeChild(fileDiv);
249    if (hasValidator) frm['datafiles.validate'].checked = true;
250    new FileAction('removefile', fileTypeId, fileId);
251    if (event.stopPropagation)
252    {
253      event.stopPropagation();
254    }
255    else
256    {
257      event.cancelBubble = true;
258    }
259  }
260 
261  var fileActions = new Array();
262  function FileAction(action, fileTypeId, fileId)
263  {
264    this.action = action;
265    this.fileTypeId = fileTypeId;
266    this.fileId = fileId;
267   
268
269    for (var i = fileActions.length-1; i >= 0; i--)
270    {
271      var other = fileActions[i];
272     
273      var remove = false;
274      if (action == 'setfile')
275      {
276        // Remove all other actions for the given file type
277        remove = other.fileTypeId == this.fileTypeId;
278      }
279      else
280      {
281        // Remove all other actions for the given file type+file
282        remove = other.fileTypeId == this.fileTypeId && other.fileId == this.fileId;
283      }
284      if (remove) fileActions.splice(i, 1);
285    }
286
287    fileActions[fileActions.length] = this;
288  }
289 
290  function writeFileActionsToForm(toForm)
291  {
292    var frm = document.forms['datafiles'];
293    if (frm['datafiles.validate'])
294    {
295      Forms.createHidden(toForm, 'datafiles.validate', frm['datafiles.validate'].checked ? 1 : 0);
296    }
297    for (var i = 0; i < fileActions.length; i++)
298    {
299      var action = fileActions[i];
300      Forms.createHidden(toForm, action.action + '.' + action.fileTypeId, action.fileId);
301    }
302  }
303 
304  var visibleRecentFilesDiv = null;
305  function recentFilesOnClick(event, fileTypeId)
306  {
307    var recentDiv = document.getElementById('recentfiles.'+fileTypeId);
308    var currentDiv = visibleRecentFilesDiv;
309    hideVisibleRecentFilesDiv();
310    if (currentDiv == recentDiv) return;
311   
312    var fileCell = document.getElementById('filelist.'+fileTypeId+'.file');
313    var pos = Main.getElementPosition(fileCell, true);
314    Main.show('recentfiles.'+fileTypeId);
315   
316    recentDiv.style.top = (pos.bottom-2) + 'px';
317    recentDiv.style.left = (pos.left) + 'px';
318    recentDiv.style.width = (pos.width+18) + 'px';
319
320    visibleRecentFilesDiv = recentDiv;
321    if (event.stopPropagation)
322    {
323      event.stopPropagation();
324    }
325    else
326    {
327      event.cancelBubble = true;
328    }
329  }
330
331  function selectRecentFile(fileTypeId, fileId, allowMultiple, hasValidator)
332  {
333    var path = document.getElementById('recentfile.'+fileTypeId+'.'+fileId).innerHTML;
334    if (allowMultiple)
335    {
336      addFile(fileTypeId, fileId, path, hasValidator);
337    }
338    else
339    {
340      setFile(fileTypeId, fileId, path, hasValidator);
341    }
342  }
343 
344  function hideVisibleRecentFilesDiv()
345  {
346    if (visibleRecentFilesDiv)
347    {
348      visibleRecentFilesDiv.style.display = 'none';
349      visibleRecentFilesDiv = null;
350    }
351  }
352  </script>
353  <style>
354  .filelist {
355    overflow: auto;
356    padding: 0px;
357    border: 1px solid #cccccc;
358    background: #FFFFFF;
359  }
360  .filelist td {
361    border-bottom: 1px dotted #cccccc;
362    padding: 1px 2px 1px 2px;
363  }
364  .filelist .filetype {
365    width: 150px;
366    font-weight: bold;
367    background-color: #f0f0f0;
368    border-right: 1px solid #cccccc;
369    white-space: nowrap;
370  }
371  .filelist .file {
372    cursor: pointer;
373  }
374  .filelist .required {
375    background: #D0F0FF !important;
376  }
377  .filelist .fileaction {
378    max-width: 18px;
379    width: 18px;
380    text-align: center;
381  }
382  .recentfiles {
383    position: absolute;
384    top: 0px;
385    left: 0px;
386    border: 1px solid #999999;
387    background: #ffffff;
388    text-align: left;
389  }
390  .recentfiles .recentfile {
391    padding: 2px;
392    background: #f0f0f0;
393    border-bottom: 1px dotted #d0d0d0;
394  }
395  .recentfiles .recentfile:hover {
396    cursor: pointer;
397    background: #d0d0d0;
398    padding: 2px;
399  }
400  .filelist .member {
401    xbackground: #ff0000;
402  }
403  </style>
404  </base:head>
405 
406  <base:body onload="init()" style="background: #E0E0E0;">
407
408    <div id="filelist" class="filelist" style="height: <%=(int)(scale*320)%>px; width:100%">
409    <%
410    boolean hasNonPlatformFiles = false;     
411    boolean activateCheckBoxes = false;
412    boolean validationSupport = false;
413    if (fileTypes.size() == 0)
414    {
415      String what = "";
416      if (platform != null)
417      {
418        what = "'" + HTML.encodeTags(platform.getName()) + "' platform";
419      }
420      else if (itemSubtype != null)
421      {
422        what = "'" + HTML.encodeTags(itemSubtype.getName()) + "' subtype";
423      }
424      %>
425      <div class="error">
426        The <%=what%> doesn't define any file types for
427        <%=itemType.toString() %> items.
428      </div>
429      <%
430    }
431    else if (deniedPlatform)
432    {
433      %>
434      <div class="error">Denied</div>
435      <%
436    }
437    else
438    {
439      %>
440      <table border="0" cellspacing="0" cellpadding="0" width="100%">
441      <%
442      for (DataFileType dft : fileTypes)
443      {
444        String dftId = Integer.toString(dft.getId());
445        String fullLabel = dft.getName();
446        String label = Values.trimString(fullLabel, 25);
447       
448        UsableDataFileType usable = null;
449        if (platform != null) 
450        {
451          usable = platform.getFileType(dft, variant, false);
452          if (usable == null && variant != null)
453          {
454            // If file type is not registered with a variant, also check if it is inherited from platform
455            usable = platform.getFileType(dft, null, false);
456          }
457        }
458        else if (itemSubtype != null)
459        {
460          usable = itemSubtype.getAssociatedDataFileType(dft, false);
461        }
462       
463        boolean isPartOfPlatform = usable != null;
464        boolean isRequired = usable == null ? false : usable.isRequired();
465        boolean allowMultiple = usable == null ? false : usable.getAllowMultiple();
466        String extension = dft.getExtension();
467        boolean hasValidator = dft.hasActiveValidator(dc);
468        validationSupport |= hasValidator;
469        List<FileSetMember> files = members.get(dft);
470        List<File> recentFiles = (List<File>)cc.getRecent(dc, Item.FILE, dft.getExternalId());
471        %>
472        <tr class="item <%=isRequired ? "required" : "" %>" 
473          id="filelist.<%=dftId%>">
474          <td class="filetype" valign="top"
475            id="filelist.<%=dftId%>.label"
476            title="<%=fullLabel == label ? "" : HTML.encodeTags(fullLabel)%>"
477            ><%=HTML.encodeTags(label)%>
478            <%
479            if (!isPartOfPlatform && !deniedPlatform)
480            {
481              hasNonPlatformFiles = true;
482              %>
483              <base:icon image="warning.gif" 
484                tooltip="This file is not part of the platform/subtype" />
485              <%
486            }
487            %>
488          </td>
489          <td class="file" id="filelist.<%=dftId%>.file" 
490            onclick="<%="recentFilesOnClick(event, " + dftId + ")"%>">
491            <%
492            if (files != null && files.size() > 0)
493            {
494              for (FileSetMember fm : files)
495              {
496                File file = fm.getFile();
497                %>
498                <div id="filelist.<%=dftId%>.<%=file.getId()%>" class="member">
499                <%=file.getPath() %>
500                <base:icon image="remove.png" visible="<%=allowMultiple %>"
501                  tooltip="Remove this file"
502                  onclick="<%="removeFileOnClick(event, " + dftId + "," + file.getId() + "," + hasValidator + ")" %>"
503                />
504                </div>
505                <%
506              }
507              %>
508              <%
509            }
510            %>
511          </td>
512          <td class="fileaction">
513            <base:icon image="mini_scroll_down.png" 
514              visible="<%=recentFiles.size() >= 0 %>"
515              tooltip="Select a recently used file"
516              onclick="<%="recentFilesOnClick(event, " + dftId + ")"%>"
517            />
518            <div id="recentfiles.<%=dftId%>" style="display: none;" class="recentfiles">
519              <div class="recentfile"
520                onclick="selectRecentFile(<%=dftId%>, 0, false, <%=hasValidator%>)"
521                id="recentfile.<%=dftId%>.0"
522                ><i>- clear -</i></div>
523              <%
524              for (File recent : recentFiles)
525              {
526                %>
527                <div class="recentfile"
528                  onclick="selectRecentFile(<%=dftId%>, <%=recent.getId()%>, <%=allowMultiple ? 1 : 0 %>, <%=hasValidator%>)"
529                  id="recentfile.<%=dftId%>.<%=recent.getId()%>"
530                  ><%=HTML.encodeTags(recent.getPath().toString())%></div>
531                <%
532              }
533              %>
534            </div>
535          </td>
536          <td class="fileaction">
537            <base:icon image="add.png" 
538              onclick="<%="addFilesOnClick("+dftId+", '" + HTML.javaScriptEncode(extension) + "', "+ hasValidator + ")"%>"
539              visible="<%=allowMultiple %>"
540            />
541            <base:icon image="browse.png" 
542              onclick="<%="browseOnClick("+dftId+", '" + HTML.javaScriptEncode(extension) + "', "+ hasValidator + ")"%>"
543              visible="<%=!allowMultiple%>"
544            />
545          </td>
546        </tr>
547        <%
548      }
549      %>
550      </table>
551      <%
552    }
553    %>
554    </div>
555
556      <form name="datafiles">
557      <table width="100%">
558      <tr>
559        <td>
560          <%
561          if (validationSupport)
562          {
563            %>
564            <span title="Enabled this check box to validate and extract metadata from selected files">
565            <b>Validate files</b>
566            <input type="checkbox" value="1" name="datafiles.validate">
567            </span>
568            <%
569          }
570          %>
571        </td>
572        <td>
573          <%
574          if (hasNonPlatformFiles)
575          {
576            if (platform != null)
577            {
578              %>
579              <div align="right">
580              <base:icon image="warning.gif" /> 
581              = The file type is not part of the <i><%=HTML.encodeTags(platform.getName())%></i> platform
582              </div>
583              <%
584            }
585            else if (itemSubtype != null)
586            {
587              %>
588              <div align="right">
589              <base:icon image="warning.gif" /> 
590              = The file type is not part of the <i><%=HTML.encodeTags(itemSubtype.getName())%></i> subtype
591              </div>
592              <%
593            }
594          }
595          %>
596        </td>
597      </table>
598    </form>
599  </base:body>
600  </base:page>
601  <%
602}
603finally
604{
605  if (dc != null) dc.close();
606}
607%>
Note: See TracBrowser for help on using the repository browser.