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

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

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

The GUI can now be used to add multiple files of types that has enabled this.

  • 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    Forms.createHidden(toForm, 'datafiles.validate', frm['datafiles.validate'].checked ? 1 : 0);
294    for (var i = 0; i < fileActions.length; i++)
295    {
296      var action = fileActions[i];
297      Forms.createHidden(toForm, action.action + '.' + action.fileTypeId, action.fileId);
298    }
299  }
300 
301  var visibleRecentFilesDiv = null;
302  function recentFilesOnClick(event, fileTypeId)
303  {
304    var recentDiv = document.getElementById('recentfiles.'+fileTypeId);
305    var currentDiv = visibleRecentFilesDiv;
306    hideVisibleRecentFilesDiv();
307    if (currentDiv == recentDiv) return;
308   
309    var fileCell = document.getElementById('filelist.'+fileTypeId+'.file');
310    var pos = Main.getElementPosition(fileCell, true);
311    Main.show('recentfiles.'+fileTypeId);
312   
313    recentDiv.style.top = (pos.bottom-2) + 'px';
314    recentDiv.style.left = (pos.left) + 'px';
315    recentDiv.style.width = (pos.width+18) + 'px';
316
317    visibleRecentFilesDiv = recentDiv;
318    if (event.stopPropagation)
319    {
320      event.stopPropagation();
321    }
322    else
323    {
324      event.cancelBubble = true;
325    }
326  }
327
328  function selectRecentFile(fileTypeId, fileId, allowMultiple, hasValidator)
329  {
330    var path = document.getElementById('recentfile.'+fileTypeId+'.'+fileId).innerHTML;
331    if (allowMultiple)
332    {
333      addFile(fileTypeId, fileId, path, hasValidator);
334    }
335    else
336    {
337      setFile(fileTypeId, fileId, path, hasValidator);
338    }
339  }
340 
341  function hideVisibleRecentFilesDiv()
342  {
343    if (visibleRecentFilesDiv)
344    {
345      visibleRecentFilesDiv.style.display = 'none';
346      visibleRecentFilesDiv = null;
347    }
348  }
349  </script>
350  <style>
351  .filelist {
352    overflow: auto;
353    padding: 0px;
354    border: 1px solid #cccccc;
355    background: #FFFFFF;
356  }
357  .filelist td {
358    border-bottom: 1px dotted #cccccc;
359    padding: 1px 2px 1px 2px;
360  }
361  .filelist .filetype {
362    width: 150px;
363    font-weight: bold;
364    background-color: #f0f0f0;
365    border-right: 1px solid #cccccc;
366    white-space: nowrap;
367  }
368  .filelist .file {
369    cursor: pointer;
370  }
371  .filelist .required {
372    background: #D0F0FF !important;
373  }
374  .filelist .fileaction {
375    max-width: 18px;
376    width: 18px;
377    text-align: center;
378  }
379  .recentfiles {
380    position: absolute;
381    top: 0px;
382    left: 0px;
383    border: 1px solid #999999;
384    background: #ffffff;
385    text-align: left;
386  }
387  .recentfiles .recentfile {
388    padding: 2px;
389    background: #f0f0f0;
390    border-bottom: 1px dotted #d0d0d0;
391  }
392  .recentfiles .recentfile:hover {
393    cursor: pointer;
394    background: #d0d0d0;
395    padding: 2px;
396  }
397  .filelist .member {
398    xbackground: #ff0000;
399  }
400  </style>
401  </base:head>
402 
403  <base:body onload="init()" style="background: #E0E0E0;">
404
405    <div id="filelist" class="filelist" style="height: <%=(int)(scale*320)%>px; width:100%">
406    <%
407    boolean hasNonPlatformFiles = false;     
408    boolean activateCheckBoxes = false;
409    boolean validationSupport = false;
410    if (fileTypes.size() == 0)
411    {
412      String what = "";
413      if (platform != null)
414      {
415        what = "'" + HTML.encodeTags(platform.getName()) + "' platform";
416      }
417      else if (itemSubtype != null)
418      {
419        what = "'" + HTML.encodeTags(itemSubtype.getName()) + "' subtype";
420      }
421      %>
422      <div class="error">
423        The <%=what%> doesn't define any file types for
424        <%=itemType.toString() %> items.
425      </div>
426      <%
427    }
428    else if (deniedPlatform)
429    {
430      %>
431      <div class="error">Denied</div>
432      <%
433    }
434    else
435    {
436      %>
437      <table border="0" cellspacing="0" cellpadding="0" width="100%">
438      <%
439      for (DataFileType dft : fileTypes)
440      {
441        String dftId = Integer.toString(dft.getId());
442        String fullLabel = dft.getName();
443        String label = Values.trimString(fullLabel, 25);
444       
445        UsableDataFileType usable = null;
446        if (platform != null) 
447        {
448          usable = platform.getFileType(dft, variant, false);
449          if (usable == null && variant != null)
450          {
451            // If file type is not registered with a variant, also check if it is inherited from platform
452            usable = platform.getFileType(dft, null, false);
453          }
454        }
455        else if (itemSubtype != null)
456        {
457          usable = itemSubtype.getAssociatedDataFileType(dft, false);
458        }
459       
460        boolean isPartOfPlatform = usable != null;
461        boolean isRequired = usable == null ? false : usable.isRequired();
462        boolean allowMultiple = usable == null ? false : usable.getAllowMultiple();
463        String extension = dft.getExtension();
464        boolean hasValidator = dft.hasActiveValidator(dc);
465        validationSupport |= hasValidator;
466        List<FileSetMember> files = members.get(dft);
467        List<File> recentFiles = (List<File>)cc.getRecent(dc, Item.FILE, dft.getExternalId());
468        %>
469        <tr class="item <%=isRequired ? "required" : "" %>" 
470          id="filelist.<%=dftId%>">
471          <td class="filetype" valign="top"
472            id="filelist.<%=dftId%>.label"
473            title="<%=fullLabel == label ? "" : HTML.encodeTags(fullLabel)%>"
474            ><%=HTML.encodeTags(label)%>
475            <%
476            if (!isPartOfPlatform && !deniedPlatform)
477            {
478              hasNonPlatformFiles = true;
479              %>
480              <base:icon image="warning.gif" 
481                tooltip="This file is not part of the platform/subtype" />
482              <%
483            }
484            %>
485          </td>
486          <td class="file" id="filelist.<%=dftId%>.file" 
487            onclick="<%="recentFilesOnClick(event, " + dftId + ")"%>">
488            <%
489            if (files != null && files.size() > 0)
490            {
491              for (FileSetMember fm : files)
492              {
493                File file = fm.getFile();
494                %>
495                <div id="filelist.<%=dftId%>.<%=file.getId()%>" class="member">
496                <%=file.getPath() %>
497                <base:icon image="remove.png" visible="<%=allowMultiple %>"
498                  tooltip="Remove this file"
499                  onclick="<%="removeFileOnClick(event, " + dftId + "," + file.getId() + "," + hasValidator + ")" %>"
500                />
501                </div>
502                <%
503              }
504              %>
505              <%
506            }
507            %>
508          </td>
509          <td class="fileaction">
510            <base:icon image="mini_scroll_down.png" 
511              visible="<%=recentFiles.size() >= 0 %>"
512              tooltip="Select a recently used file"
513              onclick="<%="recentFilesOnClick(event, " + dftId + ")"%>"
514            />
515            <div id="recentfiles.<%=dftId%>" style="display: none;" class="recentfiles">
516              <div class="recentfile"
517                onclick="selectRecentFile(<%=dftId%>, 0, false, <%=hasValidator%>)"
518                id="recentfile.<%=dftId%>.0"
519                ><i>- clear -</i></div>
520              <%
521              for (File recent : recentFiles)
522              {
523                %>
524                <div class="recentfile"
525                  onclick="selectRecentFile(<%=dftId%>, <%=recent.getId()%>, <%=allowMultiple ? 1 : 0 %>, <%=hasValidator%>)"
526                  id="recentfile.<%=dftId%>.<%=recent.getId()%>"
527                  ><%=HTML.encodeTags(recent.getPath().toString())%></div>
528                <%
529              }
530              %>
531            </div>
532          </td>
533          <td class="fileaction">
534            <base:icon image="add.png" 
535              onclick="<%="addFilesOnClick("+dftId+", '" + HTML.javaScriptEncode(extension) + "', "+ hasValidator + ")"%>"
536              visible="<%=allowMultiple %>"
537            />
538            <base:icon image="browse.png" 
539              onclick="<%="browseOnClick("+dftId+", '" + HTML.javaScriptEncode(extension) + "', "+ hasValidator + ")"%>"
540              visible="<%=!allowMultiple%>"
541            />
542          </td>
543        </tr>
544        <%
545      }
546      %>
547      </table>
548      <%
549    }
550    %>
551    </div>
552
553      <form name="datafiles">
554      <table width="100%">
555      <tr>
556        <td>
557          <%
558          if (validationSupport)
559          {
560            %>
561            <span title="Enabled this check box to validate and extract metadata from selected files">
562            <b>Validate files</b>
563            <input type="checkbox" value="1" name="datafiles.validate">
564            </span>
565            <%
566          }
567          %>
568        </td>
569        <td>
570          <%
571          if (hasNonPlatformFiles)
572          {
573            if (platform != null)
574            {
575              %>
576              <div align="right">
577              <base:icon image="warning.gif" /> 
578              = The file type is not part of the <i><%=HTML.encodeTags(platform.getName())%></i> platform
579              </div>
580              <%
581            }
582            else if (itemSubtype != null)
583            {
584              %>
585              <div align="right">
586              <base:icon image="warning.gif" /> 
587              = The file type is not part of the <i><%=HTML.encodeTags(itemSubtype.getName())%></i> subtype
588              </div>
589              <%
590            }
591          }
592          %>
593        </td>
594      </table>
595    </form>
596  </base:body>
597  </base:page>
598  <%
599}
600finally
601{
602  if (dc != null) dc.close();
603}
604%>
Note: See TracBrowser for help on using the repository browser.