// If the token is from a LoginCluster federation, get user & token data
// from the token issuing cluster.
+ if (!config) {
+ return;
+ }
const lc = (config as Config).loginCluster
const tokenCluster = tokenParts.length === 3
? tokenParts[1].substring(0, 5)
const client = await svc.apiClientAuthorizationService.get('current');
dispatch(authActions.SET_EXTRA_TOKEN({
extraApiToken: extraToken,
- extraApiTokenExpiration: client.expiresAt ? new Date(client.expiresAt): undefined,
+ extraApiTokenExpiration: client.expiresAt ? new Date(client.expiresAt) : undefined,
}));
return extraToken;
} catch (e) {
const newExtraToken = getTokenV2(client);
dispatch(authActions.SET_EXTRA_TOKEN({
extraApiToken: newExtraToken,
- extraApiTokenExpiration: client.expiresAt ? new Date(client.expiresAt): undefined,
+ extraApiTokenExpiration: client.expiresAt ? new Date(client.expiresAt) : undefined,
}));
return newExtraToken;
} catch {
includeCollections?: boolean;
includeFiles?: boolean;
includeFilterGroups?: boolean;
- loadShared?: boolean;
options?: { showOnlyOwned: boolean; showOnlyWritable: boolean; };
}
home: `${pickerId}_home`,
shared: `${pickerId}_shared`,
favorites: `${pickerId}_favorites`,
- publicFavorites: `${pickerId}_publicFavorites`
+ publicFavorites: `${pickerId}_publicFavorites`,
+ search: `${pickerId}_search`,
});
export const getAllNodes = <Value>(pickerId: string, filter = (node: TreeNode<Value>) => true) => (state: TreePicker) =>
export const initProjectsTreePicker = (pickerId: string) =>
async (dispatch: Dispatch, _: () => RootState, services: ServiceRepository) => {
- const { home, shared, favorites, publicFavorites } = getProjectsTreePickerIds(pickerId);
+ const { home, shared, favorites, publicFavorites, search } = getProjectsTreePickerIds(pickerId);
dispatch<any>(initUserProject(home));
dispatch<any>(initSharedProject(shared));
dispatch<any>(initFavoritesProject(favorites));
dispatch<any>(initPublicFavoritesProject(publicFavorites));
+ dispatch<any>(initSearchProject(search));
};
interface ReceiveTreePickerDataParams<T> {
interface LoadProjectParamsWithId extends LoadProjectParams {
id: string;
pickerId: string;
- includeCollections?: boolean;
- includeFiles?: boolean;
- includeFilterGroups?: boolean;
loadShared?: boolean;
- options?: { showOnlyOwned: boolean; showOnlyWritable: boolean; };
+ searchProjects?: boolean;
}
export const loadProject = (params: LoadProjectParamsWithId) =>
async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
- const { id, pickerId, includeCollections = false, includeFiles = false, includeFilterGroups = false, loadShared = false, options } = params;
+ const { id, pickerId, includeCollections = false, includeFiles = false, includeFilterGroups = false, loadShared = false, options, searchProjects = false } = params;
dispatch(treePickerActions.LOAD_TREE_PICKER_NODE({ id, pickerId }));
- let filterB = pipe(
- (fb: FilterBuilder) => includeCollections
- ? fb.addIsA('uuid', [ResourceKind.PROJECT, ResourceKind.COLLECTION])
- : fb.addIsA('uuid', [ResourceKind.PROJECT]),
- fb => fb.addNotIn("collections.properties.type", ["intermediate", "log"]),
- )(new FilterBuilder());
+ let filterB = new FilterBuilder();
+
+ filterB = (includeCollections && !searchProjects)
+ ? filterB.addIsA('uuid', [ResourceKind.PROJECT, ResourceKind.COLLECTION])
+ : filterB.addIsA('uuid', [ResourceKind.PROJECT]);
const state = getState();
if (state.treePickerSearch.collectionFilterValues[pickerId]) {
filterB = filterB.addILike('collections.name', state.treePickerSearch.collectionFilterValues[pickerId]);
+ } else {
+ filterB = filterB.addNotIn("collections.properties.type", ["intermediate", "log"]);
+ }
+
+ if (searchProjects && state.treePickerSearch.projectSearchValues[pickerId]) {
+ filterB = filterB.addILike('groups.name', state.treePickerSearch.projectSearchValues[pickerId]);
}
const filters = filterB.getFilters();
- const { items, itemsAvailable } = await services.groupsService.contents(loadShared ? '' : id, { filters, excludeHomeProject: loadShared || undefined, limit: 1000 });
+ const { items, itemsAvailable } = await services.groupsService.contents((loadShared || searchProjects) ? '' : id, { filters, excludeHomeProject: loadShared || undefined, limit: 1000 });
if (itemsAvailable > 1000) {
items.push({
}));
};
+export const SEARCH_PROJECT_ID = 'Search all Projects';
+export const initSearchProject = (pickerId: string) =>
+ async (dispatch: Dispatch<any>, getState: () => RootState, services: ServiceRepository) => {
+ dispatch(receiveTreePickerData({
+ id: '',
+ pickerId,
+ data: [{ uuid: SEARCH_PROJECT_ID, name: SEARCH_PROJECT_ID }],
+ extractNodeData: value => ({
+ id: value.uuid,
+ status: TreeNodeStatus.INITIAL,
+ value,
+ }),
+ }));
+ };
+
+
interface LoadFavoritesProjectParams {
pickerId: string;
includeCollections?: boolean;
import { ProjectsTreePicker, ProjectsTreePickerProps } from 'views-components/projects-tree-picker/generic-projects-tree-picker';
import { Dispatch } from 'redux';
import { loadUserProject } from 'store/tree-picker/tree-picker-actions';
-import { ProjectIcon } from 'components/icon/icon';
+import { ProjectsIcon } from 'components/icon/icon';
export const HomeTreePicker = connect(() => ({
- rootItemIcon: ProjectIcon,
+ rootItemIcon: ProjectsIcon,
}), (dispatch: Dispatch): Pick<ProjectsTreePickerProps, 'loadRootItem'> => ({
loadRootItem: (_, pickerId, includeCollections, includeFiles, options) => {
dispatch<any>(loadUserProject(pickerId, includeCollections, includeFiles, options));
},
-}))(ProjectsTreePicker);
\ No newline at end of file
+}))(ProjectsTreePicker);
import { HomeTreePicker } from 'views-components/projects-tree-picker/home-tree-picker';
import { SharedTreePicker } from 'views-components/projects-tree-picker/shared-tree-picker';
import { FavoritesTreePicker } from 'views-components/projects-tree-picker/favorites-tree-picker';
+import { SearchProjectsPicker } from 'views-components/projects-tree-picker/search-projects-picker';
import {
getProjectsTreePickerIds, treePickerActions, treePickerSearchActions, initProjectsTreePicker,
SHARED_PROJECT_ID, FAVORITES_PROJECT_ID
}
const mapStateToProps = (state: RootState, props: ToplevelPickerProps): ProjectsTreePickerSearchProps => ({
- projectSearch: "",
- collectionFilter: "",
+ projectSearch: state.treePickerSearch.projectSearchValues[props.pickerId],
+ collectionFilter: state.treePickerSearch.collectionFilterValues[props.pickerId],
...props
});
const mapDispatchToProps = (dispatch: Dispatch, props: ToplevelPickerProps): (ProjectsTreePickerActionProps & DispatchProp) => {
- const { home, shared, favorites, publicFavorites } = getProjectsTreePickerIds(props.pickerId);
+ const { home, shared, favorites, publicFavorites, search } = getProjectsTreePickerIds(props.pickerId);
const params = {
includeCollections: props.includeCollections,
includeFiles: props.includeFiles,
dispatch(treePickerSearchActions.SET_TREE_PICKER_LOAD_PARAMS({ pickerId: shared, params }));
dispatch(treePickerSearchActions.SET_TREE_PICKER_LOAD_PARAMS({ pickerId: favorites, params }));
dispatch(treePickerSearchActions.SET_TREE_PICKER_LOAD_PARAMS({ pickerId: publicFavorites, params }));
+ dispatch(treePickerSearchActions.SET_TREE_PICKER_LOAD_PARAMS({ pickerId: search, params }));
return {
- onProjectSearch: (projectSearchValue: string) => dispatch(treePickerSearchActions.SET_TREE_PICKER_PROJECT_SEARCH({ pickerId: props.pickerId, projectSearchValue })),
+ onProjectSearch: (projectSearchValue: string) => dispatch(treePickerSearchActions.SET_TREE_PICKER_PROJECT_SEARCH({ pickerId: search, projectSearchValue })),
onCollectionFilter: (collectionFilterValue: string) => {
dispatch(treePickerSearchActions.SET_TREE_PICKER_COLLECTION_FILTER({ pickerId: home, collectionFilterValue }));
dispatch(treePickerSearchActions.SET_TREE_PICKER_COLLECTION_FILTER({ pickerId: shared, collectionFilterValue }));
dispatch(treePickerSearchActions.SET_TREE_PICKER_COLLECTION_FILTER({ pickerId: favorites, collectionFilterValue }));
dispatch(treePickerSearchActions.SET_TREE_PICKER_COLLECTION_FILTER({ pickerId: publicFavorites, collectionFilterValue }));
+ dispatch(treePickerSearchActions.SET_TREE_PICKER_COLLECTION_FILTER({ pickerId: search, collectionFilterValue }));
},
dispatch
}
};
-type CssRules = 'pickerHeight' | 'searchFlex' | 'searchPadding';
+type CssRules = 'pickerHeight' | 'searchFlex';
const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
pickerHeight: {
class FileInputComponent extends React.Component<ProjectsTreePickerCombinedProps> {
componentDidMount() {
- const { home, shared, favorites, publicFavorites } = getProjectsTreePickerIds(this.props.pickerId);
+ const { home, shared, favorites, publicFavorites, search } = getProjectsTreePickerIds(this.props.pickerId);
this.props.dispatch<any>(initProjectsTreePicker(this.props.pickerId));
- this.props.dispatch(treePickerSearchActions.SET_TREE_PICKER_PROJECT_SEARCH({ pickerId: this.props.pickerId, projectSearchValue: "" }));
+ this.props.dispatch(treePickerSearchActions.SET_TREE_PICKER_PROJECT_SEARCH({ pickerId: search, projectSearchValue: "" }));
+ this.props.dispatch(treePickerSearchActions.SET_TREE_PICKER_COLLECTION_FILTER({ pickerId: search, collectionFilterValue: "" }));
this.props.dispatch(treePickerSearchActions.SET_TREE_PICKER_COLLECTION_FILTER({ pickerId: home, collectionFilterValue: "" }));
this.props.dispatch(treePickerSearchActions.SET_TREE_PICKER_COLLECTION_FILTER({ pickerId: shared, collectionFilterValue: "" }));
this.props.dispatch(treePickerSearchActions.SET_TREE_PICKER_COLLECTION_FILTER({ pickerId: favorites, collectionFilterValue: "" }));
}
componentWillUnmount() {
- const { home, shared, favorites, publicFavorites } = getProjectsTreePickerIds(this.props.pickerId);
+ const { home, shared, favorites, publicFavorites, search } = getProjectsTreePickerIds(this.props.pickerId);
// Release all the state, we don't need it to hang around forever.
- this.props.dispatch(treePickerActions.RESET_TREE_PICKER({ pickerId: this.props.pickerId }));
+ this.props.dispatch(treePickerActions.RESET_TREE_PICKER({ pickerId: search }));
this.props.dispatch(treePickerActions.RESET_TREE_PICKER({ pickerId: home }));
this.props.dispatch(treePickerActions.RESET_TREE_PICKER({ pickerId: shared }));
this.props.dispatch(treePickerActions.RESET_TREE_PICKER({ pickerId: favorites }));
const onProjectSearch = this.props.onProjectSearch;
const onCollectionFilter = this.props.onCollectionFilter;
- const { home, shared, favorites, publicFavorites } = getProjectsTreePickerIds(pickerId);
+ const { home, shared, favorites, publicFavorites, search } = getProjectsTreePickerIds(pickerId);
const relatedTreePickers = getRelatedTreePickers(pickerId);
const p = {
includeCollections: this.props.includeCollections,
<SearchInput value="" label="Search Projects" selfClearProp='' onSearch={onProjectSearch} debounce={200} />
<SearchInput value="" label="Filter Collections inside Projects" selfClearProp='' onSearch={onCollectionFilter} debounce={200} />
</span>
- <div data-cy="projects-tree-home-tree-picker">
- <HomeTreePicker {...p} pickerId={home} />
- </div>
- <div data-cy="projects-tree-shared-tree-picker">
- <SharedTreePicker {...p} pickerId={shared} />
- </div>
- <div data-cy="projects-tree-public-favourites-tree-picker">
- <PublicFavoritesTreePicker {...p} pickerId={publicFavorites} />
- </div>
- <div data-cy="projects-tree-favourites-tree-picker">
- <FavoritesTreePicker {...p} pickerId={favorites} />
- </div>
+
+ {this.props.projectSearch !== "" ?
+ <div data-cy="projects-tree-search-picker">
+ <SearchProjectsPicker {...p} pickerId={search} />
+ </div>
+ :
+ <>
+ <div data-cy="projects-tree-home-tree-picker">
+ <HomeTreePicker {...p} pickerId={home} />
+ </div>
+ <div data-cy="projects-tree-shared-tree-picker">
+ <SharedTreePicker {...p} pickerId={shared} />
+ </div>
+ <div data-cy="projects-tree-public-favourites-tree-picker">
+ <PublicFavoritesTreePicker {...p} pickerId={publicFavorites} />
+ </div>
+ <div data-cy="projects-tree-favourites-tree-picker">
+ <FavoritesTreePicker {...p} pickerId={favorites} />
+ </div>
+ </>}
</div >;
}
}));
import { Dispatch } from 'redux';
import { ShareMeIcon } from 'components/icon/icon';
import { loadProject } from 'store/tree-picker/tree-picker-actions';
+import { SHARED_PROJECT_ID } from 'store/tree-picker/tree-picker-actions';
export const SharedTreePicker = connect(() => ({
rootItemIcon: ShareMeIcon,
}), (dispatch: Dispatch): Pick<ProjectsTreePickerProps, 'loadRootItem'> => ({
loadRootItem: (_, pickerId, includeCollections, includeFiles, options) => {
- dispatch<any>(loadProject({ id: 'Shared with me', pickerId, includeCollections, includeFiles, loadShared: true, options }));
+ dispatch<any>(loadProject({ id: SHARED_PROJECT_ID, pickerId, includeCollections, includeFiles, loadShared: true, options }));
},
-}))(ProjectsTreePicker);
\ No newline at end of file
+}))(ProjectsTreePicker);