mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge pull request #8294 from bwlang/library_date_propagate
Library date propagate
This commit is contained in:
@@ -703,6 +703,12 @@ var LibraryDatasetView = Backbone.View.extend({
|
||||
<td><%= _.escape(item.get("file_size")) %></td>
|
||||
</tr>
|
||||
<% } %>
|
||||
<% if (item.get("update_time")) { %>
|
||||
<tr>
|
||||
<th scope="row">Date last updated (UTC)</th>
|
||||
<td><%= _.escape(item.get("update_time")) %></td>
|
||||
</tr>
|
||||
<% } %>
|
||||
<% if (item.get("date_uploaded")) { %>
|
||||
<tr>
|
||||
<th scope="row">Date uploaded (UTC)</th>
|
||||
@@ -880,6 +886,12 @@ var LibraryDatasetView = Backbone.View.extend({
|
||||
<td><%= _.escape(ldda.get("file_size")) %></td>
|
||||
</tr>
|
||||
<% } %>
|
||||
<% if (ldda.get("update_time")) { %>
|
||||
<tr>
|
||||
<th scope="row">Date last updated (UTC)</th>
|
||||
<td><%= _.escape(ldda.get("update_time")) %></td>
|
||||
</tr>
|
||||
<% } %>
|
||||
<% if (ldda.get("date_uploaded")) { %>
|
||||
<tr>
|
||||
<th scope="row">Date uploaded (UTC)</th>
|
||||
@@ -1006,6 +1018,10 @@ var LibraryDatasetView = Backbone.View.extend({
|
||||
<th scope="row">Size</th>
|
||||
<td><%= _.escape(item.get("file_size")) %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Date last updated (UTC)</th>
|
||||
<td><%= _.escape(item.get("update_time")) %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Date uploaded (UTC)</th>
|
||||
<td><%= _.escape(item.get("date_uploaded")) %></td>
|
||||
|
||||
@@ -517,7 +517,7 @@ var FolderListView = Backbone.View.extend({
|
||||
<span title="Sorted by Size" class="sort-icon-raw_size fa"></span>
|
||||
</th>
|
||||
<th style="width:160px;">
|
||||
<a class="sort-folder-update_time" title="Click to reverse order" href='#'>Time Updated (UTC)</a>
|
||||
<a class="sort-folder-update_time" title="Click to reverse order" href='#'>Date Updated (UTC)</a>
|
||||
<span title="Sorted by Date" class="sort-icon-update_time fa"></span>
|
||||
</th>
|
||||
<th style="width:5%;">
|
||||
|
||||
@@ -1,45 +1,38 @@
|
||||
/**
|
||||
* Create alphabetical based two-argument comparator
|
||||
* that takes into account that Folder comes before Dataset.
|
||||
* Create alphabetical based two-argument comparator to handle library items (including folders)
|
||||
* If sort_key is not present it is set to ''.
|
||||
* @param {str} sort_key key to sort by
|
||||
* @param {str} sort_order order to sort by (asc, desc)
|
||||
* @return {function} two-argument comparator function
|
||||
*/
|
||||
var generateComparator = (sort_key, sort_order) => (itemA, itemB) => {
|
||||
if (itemA.get("type") === itemB.get("type")) {
|
||||
if (!itemA.has(sort_key) && !itemB.has(sort_key)) {
|
||||
return 0;
|
||||
} else if (!itemA.has(sort_key)) {
|
||||
return 1;
|
||||
} else if (!itemB.has(sort_key)) {
|
||||
return -1;
|
||||
}
|
||||
var comparable_itemA_key;
|
||||
var comparable_itemB_key;
|
||||
if (typeof itemA.get(sort_key) === "number") {
|
||||
comparable_itemA_key = itemA.get(sort_key);
|
||||
comparable_itemB_key = itemB.get(sort_key);
|
||||
}
|
||||
else
|
||||
{
|
||||
comparable_itemA_key = itemA.get(sort_key).toLowerCase();
|
||||
comparable_itemB_key = itemB.get(sort_key).toLowerCase();
|
||||
}
|
||||
if ( comparable_itemA_key > comparable_itemB_key) {
|
||||
return sort_order === "asc" ? 1 : -1;
|
||||
}
|
||||
if (comparable_itemB_key > comparable_itemA_key) {
|
||||
return sort_order === "asc" ? -1 : 1;
|
||||
}
|
||||
|
||||
return 0; // equal
|
||||
} else {
|
||||
if (itemA.get("type") === "folder") {
|
||||
return -1; // folder is always before dataset
|
||||
}
|
||||
if (!itemA.has(sort_key) && !itemB.has(sort_key)) {
|
||||
return 0;
|
||||
} else if (!itemA.has(sort_key)) {
|
||||
return 1;
|
||||
} else if (!itemB.has(sort_key)) {
|
||||
return -1;
|
||||
}
|
||||
var comparable_itemA_key;
|
||||
var comparable_itemB_key;
|
||||
if (typeof itemA.get(sort_key) === "number") {
|
||||
comparable_itemA_key = itemA.get(sort_key);
|
||||
comparable_itemB_key = itemB.get(sort_key);
|
||||
}
|
||||
else
|
||||
{
|
||||
comparable_itemA_key = itemA.get(sort_key).toLowerCase();
|
||||
comparable_itemB_key = itemB.get(sort_key).toLowerCase();
|
||||
}
|
||||
|
||||
if ( comparable_itemA_key > comparable_itemB_key) {
|
||||
return sort_order === "asc" ? 1 : -1;
|
||||
}
|
||||
if (comparable_itemB_key > comparable_itemA_key) {
|
||||
return sort_order === "asc" ? -1 : 1;
|
||||
}
|
||||
|
||||
return 0; // equal
|
||||
};
|
||||
export default {
|
||||
generateComparator: generateComparator
|
||||
|
||||
@@ -101,6 +101,7 @@ class LibraryDatasetsManager(datasets.DatasetAssociationManager):
|
||||
ldda.dbkey = new_genome_build
|
||||
changed = True
|
||||
if changed:
|
||||
ldda.update_parent_folder_update_times()
|
||||
trans.sa_session.add(ldda)
|
||||
trans.sa_session.flush()
|
||||
return changed
|
||||
@@ -223,6 +224,7 @@ class LibraryDatasetsManager(datasets.DatasetAssociationManager):
|
||||
rval['full_path'] = full_path
|
||||
rval['file_size'] = util.nice_size(int(ldda.get_size()))
|
||||
rval['date_uploaded'] = ldda.create_time.strftime("%Y-%m-%d %I:%M %p")
|
||||
rval['update_time'] = ldda.update_time.strftime("%Y-%m-%d %I:%M %p")
|
||||
rval['can_user_modify'] = trans.user_is_admin or trans.app.security_agent.can_modify_library_item(current_user_roles, ld)
|
||||
rval['is_unrestricted'] = trans.app.security_agent.dataset_is_public(ldda.dataset)
|
||||
rval['tags'] = self.tag_handler.get_tags_str(ldda.tags)
|
||||
|
||||
@@ -31,6 +31,7 @@ from sqlalchemy import (
|
||||
not_,
|
||||
or_,
|
||||
select,
|
||||
text,
|
||||
true,
|
||||
type_coerce,
|
||||
types)
|
||||
@@ -3425,6 +3426,7 @@ class LibraryDataset(RepresentById):
|
||||
uploaded_by=ldda.user.email,
|
||||
message=ldda.message,
|
||||
date_uploaded=ldda.create_time.isoformat(),
|
||||
update_time=ldda.update_time.isoformat(),
|
||||
file_size=int(ldda.get_size()),
|
||||
file_ext=ldda.ext,
|
||||
data_type=ldda.datatype.__class__.__module__ + '.' + ldda.datatype.__class__.__name__,
|
||||
@@ -3593,6 +3595,32 @@ class LibraryDatasetDatasetAssociation(DatasetInstance, HasName, RepresentById):
|
||||
rval['metadata_' + name] = val
|
||||
return rval
|
||||
|
||||
def update_parent_folder_update_times(self):
|
||||
# sets the update_time for all continaing folders up the tree
|
||||
ldda = self
|
||||
|
||||
sql = text(
|
||||
'''
|
||||
WITH RECURSIVE parent_folders_of(folder_id) AS
|
||||
(SELECT folder_id
|
||||
FROM library_dataset
|
||||
WHERE id = :library_dataset_id
|
||||
UNION ALL
|
||||
SELECT library_folder.parent_id
|
||||
FROM library_folder, parent_folders_of
|
||||
WHERE library_folder.id = parent_folders_of.folder_id )
|
||||
UPDATE library_folder
|
||||
SET update_time =
|
||||
(SELECT update_time
|
||||
FROM library_dataset_dataset_association
|
||||
WHERE id = :ldda_id)
|
||||
WHERE exists (SELECT 1 FROM parent_folders_of
|
||||
WHERE library_folder.id = parent_folders_of.folder_id)
|
||||
''').execution_options(autocommit=True)
|
||||
ret = object_session(self).execute(sql, {'library_dataset_id': ldda.library_dataset_id, 'ldda_id': ldda.id})
|
||||
if ret.rowcount < 1:
|
||||
log.warn('Attempt to updated parent folder times failed: {0} records updated.'.format(ret.rowcount))
|
||||
|
||||
|
||||
class ExtendedMetadata(RepresentById):
|
||||
def __init__(self, data):
|
||||
|
||||
@@ -546,6 +546,7 @@ class UsesLibraryMixinItems(SharableItemSecurityMixin):
|
||||
# I don't see a reason why hdas copied into libraries should not be visible.
|
||||
# If there is, refactor `ldda.visible = True` to do this only when adding HDCAs.
|
||||
ldda.visible = True
|
||||
ldda.update_parent_folder_update_times()
|
||||
trans.sa_session.flush()
|
||||
ldda_dict = ldda.to_dict()
|
||||
rval = trans.security.encode_dict_ids(ldda_dict)
|
||||
|
||||
@@ -81,13 +81,13 @@ class FolderContentsController(BaseAPIController, UsesLibraryMixin, UsesLibraryM
|
||||
for content_item in self._load_folder_contents(trans, folder, deleted):
|
||||
return_item = {}
|
||||
encoded_id = trans.security.encode_id(content_item.id)
|
||||
update_time = content_item.update_time.strftime("%Y-%m-%d %I:%M %p")
|
||||
create_time = content_item.create_time.strftime("%Y-%m-%d %I:%M %p")
|
||||
|
||||
if content_item.api_type == 'folder':
|
||||
encoded_id = 'F' + encoded_id
|
||||
can_modify = is_admin or (trans.user and trans.app.security_agent.can_modify_library_item(current_user_roles, folder))
|
||||
can_manage = is_admin or (trans.user and trans.app.security_agent.can_manage_library_item(current_user_roles, folder))
|
||||
update_time = content_item.update_time.strftime("%Y-%m-%d %I:%M %p")
|
||||
return_item.update(dict(can_modify=can_modify, can_manage=can_manage))
|
||||
if content_item.description:
|
||||
return_item.update(dict(description=content_item.description))
|
||||
@@ -107,11 +107,13 @@ class FolderContentsController(BaseAPIController, UsesLibraryMixin, UsesLibraryM
|
||||
can_manage = is_admin or (trans.user and trans.app.security_agent.can_manage_dataset(current_user_roles, content_item.library_dataset_dataset_association.dataset))
|
||||
raw_size = int(content_item.library_dataset_dataset_association.get_size())
|
||||
nice_size = util.nice_size(raw_size)
|
||||
update_time = content_item.library_dataset_dataset_association.update_time.strftime("%Y-%m-%d %I:%M %p")
|
||||
|
||||
library_dataset_dict = content_item.to_dict()
|
||||
encoded_ldda_id = trans.security.encode_id(content_item.library_dataset_dataset_association.id)
|
||||
return_item.update(dict(file_ext=library_dataset_dict['file_ext'],
|
||||
date_uploaded=library_dataset_dict['date_uploaded'],
|
||||
update_time=update_time,
|
||||
is_unrestricted=is_unrestricted,
|
||||
is_private=is_private,
|
||||
can_manage=can_manage,
|
||||
|
||||
@@ -232,6 +232,26 @@ class LibrariesApiTestCase(api.ApiTestCase, TestsDatasets):
|
||||
self._assert_status_code_is(create_response, 200)
|
||||
self._assert_has_keys(create_response.json(), "name", "id")
|
||||
|
||||
def test_create_dataset_in_subfolder(self):
|
||||
library = self.library_populator.new_private_library("ForCreateDatasets")
|
||||
folder_response = self._create_folder(library)
|
||||
self._assert_status_code_is(folder_response, 200)
|
||||
folder_id = folder_response.json()[0]['id']
|
||||
subfolder_response = self._create_subfolder(folder_id)
|
||||
self._assert_status_code_is(folder_response, 200)
|
||||
print(subfolder_response.json())
|
||||
subfolder_id = subfolder_response.json()['id']
|
||||
history_id = self.dataset_populator.new_history()
|
||||
hda_id = self.dataset_populator.new_dataset(history_id, content="1 2 3 sub")['id']
|
||||
payload = {'from_hda_id': hda_id}
|
||||
create_response = self._post("folders/%s/contents" % subfolder_id, payload)
|
||||
self._assert_status_code_is(create_response, 200)
|
||||
self._assert_has_keys(create_response.json(), "name", "id")
|
||||
dataset_update_time = create_response.json()['update_time']
|
||||
container_fetch_response = self.galaxy_interactor.get("folders/%s/contents" % folder_id)
|
||||
container_update_time = container_fetch_response.json()['folder_contents'][0]['update_time']
|
||||
assert dataset_update_time == container_update_time, container_fetch_response
|
||||
|
||||
def test_update_dataset_in_folder(self):
|
||||
ld = self._create_dataset_in_folder_in_library("ForUpdateDataset")
|
||||
data = {'name': 'updated_name', 'file_ext': 'fastq', 'misc_info': 'updated_info', 'genome_build': 'updated_genome_build'}
|
||||
@@ -301,6 +321,13 @@ class LibrariesApiTestCase(api.ApiTestCase, TestsDatasets):
|
||||
)
|
||||
return self._post("libraries/%s/contents" % library["id"], data=create_data)
|
||||
|
||||
def _create_subfolder(self, containing_folder_id):
|
||||
create_data = dict(
|
||||
description="new subfolder desc",
|
||||
name="New Subfolder",
|
||||
)
|
||||
return self._post("folders/%s" % containing_folder_id, data=create_data)
|
||||
|
||||
def _create_dataset_in_folder_in_library(self, library_name):
|
||||
library = self.library_populator.new_private_library(library_name)
|
||||
folder_response = self._create_folder(library)
|
||||
|
||||
Reference in New Issue
Block a user