Merge pull request #8294 from bwlang/library_date_propagate

Library date propagate
This commit is contained in:
Martin Cech
2019-07-11 13:55:31 -04:00
committed by GitHub
8 changed files with 104 additions and 35 deletions
@@ -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
+2
View File
@@ -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)
+28
View File
@@ -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):
+1
View File
@@ -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,
+27
View File
@@ -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)