Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding /browse view. #295

Open
wants to merge 84 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
e7a2c7d
Adding /browse view
dmichaels-harvard Nov 20, 2024
b7b6de6
Adding /browse view
dmichaels-harvard Nov 20, 2024
d39c93c
comments in CHANGELOG.rst
dmichaels-harvard Nov 20, 2024
a39073b
udpate version
dmichaels-harvard Nov 20, 2024
3c7a0cf
merge from main
dmichaels-harvard Nov 21, 2024
2abecfa
merge from main
dmichaels-harvard Nov 22, 2024
566ff2a
changes for new /recent_files_summary endpoint for C4-1192
dmichaels-harvard Dec 6, 2024
3ef3916
merge from main
dmichaels-harvard Dec 6, 2024
6148956
debugging
dmichaels-harvard Dec 7, 2024
fdcca3d
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 7, 2024
300ae14
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 7, 2024
0650d8d
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 7, 2024
f598c3f
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 7, 2024
b30dd87
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 8, 2024
6da8961
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 8, 2024
c507835
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 8, 2024
b36eb83
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 8, 2024
911808b
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 8, 2024
7bde707
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 8, 2024
e59840a
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 8, 2024
d772ec1
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 9, 2024
8ddcd24
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 9, 2024
81ae204
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 9, 2024
021f0b0
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 9, 2024
099b525
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 10, 2024
eac4384
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 10, 2024
6f24487
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 10, 2024
1a36263
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 10, 2024
828ae52
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 11, 2024
df7c33c
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 11, 2024
fdbe871
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 11, 2024
e21a5c7
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 11, 2024
4ed1041
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 11, 2024
b5c99ce
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 11, 2024
e7420cc
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 11, 2024
da2a211
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 11, 2024
8be133e
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 12, 2024
713f50f
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 12, 2024
cc4f8f1
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 12, 2024
c8f3ba9
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 12, 2024
a854653
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 12, 2024
9860674
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 12, 2024
56a72f4
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 12, 2024
60b541d
merge from main
dmichaels-harvard Dec 12, 2024
1fe7fbf
minor /recent_files_summary refactor mostly for troubleshooting
dmichaels-harvard Dec 12, 2024
f84340a
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 12, 2024
45917f5
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 12, 2024
fed57eb
merge from main
dmichaels-harvard Dec 12, 2024
975f297
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 12, 2024
6eba0a8
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 12, 2024
77a0171
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 13, 2024
2b0ad4b
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 13, 2024
66cec6e
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 13, 2024
0c1195f
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 13, 2024
c546ca2
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 13, 2024
77f0537
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 14, 2024
3448c9a
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 14, 2024
414dfde
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 14, 2024
c6e595d
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 14, 2024
b87d83a
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 14, 2024
c4f97f9
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 15, 2024
18ceaa0
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 15, 2024
567f685
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 15, 2024
2f45e8c
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 15, 2024
203228c
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 15, 2024
82daa17
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 15, 2024
db2cc99
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 15, 2024
e8280d6
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 15, 2024
3a1f19f
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 15, 2024
a383ceb
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 16, 2024
847aaa5
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 16, 2024
a092124
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 16, 2024
8e534f4
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 16, 2024
fb7ba9b
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 16, 2024
57af5b1
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 16, 2024
4a212d1
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 16, 2024
bbddc5c
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 16, 2024
142626b
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 16, 2024
dde4db5
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 16, 2024
397aeb1
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 16, 2024
c27f1a5
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 16, 2024
c5e275a
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 16, 2024
56ec435
refactoring /recent_files_summary endpoint
dmichaels-harvard Dec 17, 2024
05bff6a
merge from maingd
dmichaels-harvard Dec 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ smaht-portal
Change Log
----------

0.113.0
=======
* 2024-11-20/dmichaels
* Added module browse.py for /browse; adapted from fourfront/.../search.py/browse.
This is for ticket: https://hms-dbmi.atlassian.net/browse/C4-1184


0.112.3
=======
* 2024-11-08/dmichaels
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "encoded"
version = "0.112.3"
version = "0.113.0"
description = "SMaHT Data Analysis Portal"
authors = ["4DN-DCIC Team <[email protected]>"]
license = "MIT"
Expand Down
1 change: 1 addition & 0 deletions src/encoded/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ def main(global_config, **local_config):
if 'elasticsearch.server' in config.registry.settings:
config.include('snovault.elasticsearch')
config.include('snovault.search.search')
config.include('encoded.browse')
config.include('snovault.search.compound_search')

# this contains fall back url, so make sure it comes just before static_resoruces
Expand Down
57 changes: 57 additions & 0 deletions src/encoded/browse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import structlog
from pyramid.view import view_config
from webob.multidict import MultiDict
from pyramid.httpexceptions import HTTPFound
from urllib.parse import urlencode
from snovault.search.search import search
from snovault.util import debug_log

log = structlog.getLogger(__name__)

# 2024-11-19/dmichaels: Adapted from fourfront for C4-1184.

def includeme(config):
config.add_route('browse', '/browse{slash:/?}')
config.scan(__name__)


# DEFAULT_BROWSE_TYPE = "FileSet"
# DEFAULT_BROWSE_TYPE = "UnalignedReads"
# DEFAULT_BROWSE_TYPE = "OutputFile"

DEFAULT_BROWSE_TYPE = "File"
DEFAULT_BROWSE_FACETS = ["file_size"]

DEFAULT_BROWSE_PARAM_LISTS = {
"type": [DEFAULT_BROWSE_TYPE],
"additional_facet": DEFAULT_BROWSE_FACETS
}

@view_config(route_name='browse', request_method='GET', permission='search')
@debug_log
def browse(context, request, search_type=DEFAULT_BROWSE_TYPE, return_generator=False):
"""
Simply use search results for browse view
Redirect to proper URL w. params if needed
"""
orig_params = request.params
for k,vals in DEFAULT_BROWSE_PARAM_LISTS.items():
if k not in orig_params or orig_params[k] not in vals:
# Redirect to DEFAULT_BROWSE_PARAM_LISTS URL
next_qs = MultiDict()
for k2, v2list in DEFAULT_BROWSE_PARAM_LISTS.items():
for v2 in v2list:
next_qs.add(k2, v2)
# Preserve other keys that arent in DEFAULT_BROWSE_PARAM_LISTS
for k2, v2 in orig_params.items():
if k2 not in DEFAULT_BROWSE_PARAM_LISTS:
next_qs.add(k2, v2)
# next_qs.add("redirected_from", str(request.path_qs))
return HTTPFound(
location=str(request.path) + '?' + urlencode(next_qs),
detail="Redirected from " + str(request.path_info)
)

# TODO
# No real /browse specific UI yet; initially just basically copied static/components/SearchView.js to BrowseView.js.
return search(context, request, search_type, return_generator, forced_type="Browse")
242 changes: 242 additions & 0 deletions src/encoded/static/components/browse/BrowseView.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
'use strict';

import React from 'react';
import memoize from 'memoize-one';
import _ from 'underscore';
import url from 'url';

import {
memoizedUrlParse,
schemaTransforms,
analytics,
} from '@hms-dbmi-bgm/shared-portal-components/es/components/util';
import { SearchView as CommonSearchView } from '@hms-dbmi-bgm/shared-portal-components/es/components/browse/SearchView';
import { DetailPaneStateCache } from '@hms-dbmi-bgm/shared-portal-components/es/components/browse/components/DetailPaneStateCache';
import { columnExtensionMap } from './columnExtensionMap';
import { Schemas } from './../util';
import {
TitleAndSubtitleBeside,
PageTitleContainer,
TitleAndSubtitleUnder,
pageTitleViews,
EditingItemPageTitle,
} from './../PageTitleSection';

export default function BrowseView(props) {
const {
context: { '@type': searchPageType = ['ItemSearchResults'] },
} = props;
const isCaseSearch = searchPageType[0] === 'CaseSearchResults';

if (isCaseSearch) {
return (
<DetailPaneStateCache>
<BrowseViewBody {...props} {...{ isCaseSearch }} />
</DetailPaneStateCache>
);
}

return <BrowseViewBody {...props} />;
}

export class BrowseViewBody extends React.PureComponent {
/**
* Function which is passed into a `.filter()` call to
* filter context.facets down, usually in response to frontend-state.
*
* Currently is meant to filter out type facet if we're in selection mode,
* as well as some fields from embedded 'experiment_set' which might
* give unexpected results.
*
* @todo Potentially get rid of this and do on backend.
*
* @param {{ field: string }} facet - Object representing a facet.
* @returns {boolean} Whether to keep or discard facet.
*/
static filterFacet(facet, currentAction) {
// Set in backend or schema for facets which are under development or similar.
if (facet.hide_from_view) return false;

// Remove the @type facet while in selection mode.
if (facet.field === 'type' && currentAction === 'selection')
return false;

return true;
}

/** Filter the `@type` facet options down to abstract types only (if none selected) for Search. */
static transformedFacets(context, currentAction, schemas) {
// Clone/filter list of facets.
// We may filter out type facet completely at this step,
// in which case we can return out of func early.
const facets = context.facets.filter(function (facet) {
return BrowseViewBody.filterFacet(facet, currentAction);
});

// Find facet for '@type'
const searchItemTypes =
schemaTransforms.getAllSchemaTypesFromSearchContext(context); // "Item" is excluded

if (searchItemTypes.length > 0) {
console.info(
"A (non-'Item') type filter is present. Will skip filtering Item types in Facet."
);
// Keep all terms/leaf-types - backend should already filter down to only valid sub-types through
// nature of search itself.

if (searchItemTypes.length > 1) {
const errMsg =
'More than one "type" filter is selected. This is intended to not occur, at least as a consequence of interacting with the UI. Perhaps have entered multiple types into URL.';
analytics.exception('CGAP SearchView - ' + errMsg);
console.warn(errMsg);
}

return facets;
}

const typeFacetIndex = _.findIndex(facets, { field: 'type' });
if (typeFacetIndex === -1) {
console.error(
'Could not get type facet, though some filter for it is present.'
);
return facets; // Facet not present, return.
}

// Avoid modifying in place.
facets[typeFacetIndex] = _.clone(facets[typeFacetIndex]);

// Show only base types for when itemTypesInSearch.length === 0 (aka 'type=Item').
facets[typeFacetIndex].terms = _.filter(
facets[typeFacetIndex].terms,
function (itemType) {
const parentType = schemaTransforms.getAbstractTypeForType(
itemType.key,
schemas
);
return !parentType || parentType === itemType.key;
}
);

return facets;
}

/** Not currently used. */
static filteredFilters(filters) {
const typeFilterCount = filters.reduce(function (m, { field }) {
if (field === 'type') return m + 1;
return m;
}, 0);
return filters.filter(function ({ field, term }) {
if (field === 'type') {
if (term === 'Item') {
return false;
}
if (typeFilterCount === 1) {
return false;
}
}
return true;
});
}

constructor(props) {
super(props);
this.memoized = {
transformedFacets: memoize(BrowseViewBody.transformedFacets),
filteredFilters: memoize(BrowseViewBody.filteredFilters),
};
}

render() {
const {
isCaseSearch = false,
context,
currentAction,
schemas,
} = this.props;

// We don't need full screen btn on CGAP as already full width.
const passProps = _.omit(
this.props,
'isFullscreen',
'toggleFullScreen',
'isCaseSearch'
);

//const filters = BrowseView.filteredFilters(context.filters || []);
const facets = this.memoized.transformedFacets(
context,
currentAction,
schemas
);
const tableColumnClassName = 'results-column col';
const facetColumnClassName = 'facets-column col-auto';

return (
<div
className="container-wide search-page-outer-container"
id="content">
<CommonSearchView
{...passProps}
{...{
columnExtensionMap,
tableColumnClassName,
facetColumnClassName,
facets,
}}
renderDetailPane={null}
termTransformFxn={Schemas.Term.toName}
separateSingleTermFacets={false}
rowHeight={31}
openRowHeight={40}
/>
HELLO: THIS IS BROWSE-VIEW!
</div>
);
}
}

const BrowseViewPageTitle = React.memo(function BrowseViewPageTitle(props) {
const { context, schemas, currentAction, alerts } = props;

if (currentAction === 'add') {
// Fallback unless any custom PageTitles registered for @type=<ItemType>SearchResults & currentAction=add
return (
<EditingItemPageTitle
{...{ context, schemas, currentAction, alerts }}
/>
);
}

if (currentAction === 'selection' || currentAction === 'multiselect') {
return (
<PageTitleContainer alerts={alerts} className="container-wide">
<TitleAndSubtitleUnder subtitle="Drag and drop Items from this view into other window(s).">
Selecting
</TitleAndSubtitleUnder>
</PageTitleContainer>
);
}

const thisTypeTitle = schemaTransforms.getSchemaTypeFromSearchContext(
context,
schemas
);
const subtitle = thisTypeTitle ? (
<span>
<small className="text-300">for</small> {thisTypeTitle}
</span>
) : null;

return (
<PageTitleContainer alerts={alerts} className="container-wide">
<TitleAndSubtitleBeside subtitle={subtitle}>
Search
</TitleAndSubtitleBeside>
</PageTitleContainer>
);
});

pageTitleViews.register(BrowseViewPageTitle, 'Browse');
pageTitleViews.register(BrowseViewPageTitle, 'Browse', 'selection');
pageTitleViews.register(BrowseViewPageTitle, 'Browse', 'add');
5 changes: 5 additions & 0 deletions src/encoded/static/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import DocumentView from './item-pages/DocumentView';
import StaticSectionView from './item-pages/StaticSectionView';
import SMaHTSubmissionView from './forms/SMaHTSubmissionView';
import SearchView from './browse/SearchView';
import BrowseView from './browse/BrowseView';
import FileView from './item-pages/FileView';

/**
Expand Down Expand Up @@ -59,6 +60,10 @@ content_views.register(SearchView, 'Search');
content_views.register(SearchView, 'Search', 'selection');
content_views.register(SearchView, 'Search', 'multiselect');

content_views.register(BrowseView, 'Browse');
content_views.register(BrowseView, 'Browse', 'selection');
content_views.register(BrowseView, 'Browse', 'multiselect');

// Fallback for anything we haven't registered
content_views.fallback = function () {
return FallbackView;
Expand Down
Loading