});
});
});
+
+ it('copies project URL to clipboard', () => {
+ const projectName = `Test project (${Math.floor(999999 * Math.random())})`;
+
+ cy.loginAs(activeUser);
+ cy.get('[data-cy=side-panel-button]').click();
+ cy.get('[data-cy=side-panel-new-project]').click();
+ cy.get('[data-cy=form-dialog]')
+ .should('contain', 'New Project')
+ .within(() => {
+ cy.get('[data-cy=name-field]').within(() => {
+ cy.get('input').type(projectName);
+ });
+ cy.get('[data-cy=form-submit-btn]').click();
+ });
+
+ cy.get('[data-cy=side-panel-tree]').contains('Projects').click();
+ cy.get('[data-cy=project-panel]').contains(projectName).rightclick();
+ cy.get('[data-cy=context-menu]').contains('Copy to clipboard').click();
+ cy.window().then((win) => (
+ win.navigator.clipboard.readText().then((text) => {
+ expect(text).to.match(/https\:\/\/localhost\:[0-9]+\/projects\/[a-z0-9]{5}-[a-z0-9]{5}-[a-z0-9]{15}/,);
+ })
+ ));
+
+ });
});
});
});
+ it('can search items using quotes', function() {
+ const random = Math.floor(Math.random() * Math.floor(999999));
+ const colName = `Collection ${random}`;
+ const colName2 = `Collection test ${random}`;
+
+ // Creates the collection using the admin token so we can set up
+ // a bogus manifest text without block signatures.
+ cy.createCollection(adminUser.token, {
+ name: colName,
+ owner_uuid: activeUser.user.uuid,
+ preserve_version: true,
+ manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:bar\n"
+ }).as('collection1');
+
+ cy.createCollection(adminUser.token, {
+ name: colName2,
+ owner_uuid: activeUser.user.uuid,
+ preserve_version: true,
+ manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:bar\n"
+ }).as('collection2');
+
+ cy.getAll('@collection1', '@collection2')
+ .then(function() {
+ cy.loginAs(activeUser);
+
+ cy.doSearch(colName);
+ cy.get('[data-cy=search-results] table tbody tr').should('have.length', 2);
+
+ cy.doSearch(`"${colName}"`);
+ cy.get('[data-cy=search-results] table tbody tr').should('have.length', 1);
+ });
+ });
+
it('can display owner of the item', function() {
const colName = `Collection ${Math.floor(Math.random() * Math.floor(999999))}`;
import Star from '@material-ui/icons/Star';
import StarBorder from '@material-ui/icons/StarBorder';
import Warning from '@material-ui/icons/Warning';
-import Visibility from '@material-ui/icons/Visibility';
-import VisibilityOff from '@material-ui/icons/VisibilityOff';
import VpnKey from '@material-ui/icons/VpnKey';
import LinkOutlined from '@material-ui/icons/LinkOutlined';
import RemoveRedEye from '@material-ui/icons/RemoveRedEye';
export const TrashIcon: IconType = (props) => <Delete {...props} />;
export const UserPanelIcon: IconType = (props) => <Person {...props} />;
export const UsedByIcon: IconType = (props) => <Folder {...props} />;
-export const VisibleIcon: IconType = (props) => <Visibility {...props} />;
-export const InvisibleIcon: IconType = (props) => <VisibilityOff {...props} />;
export const WorkflowIcon: IconType = (props) => <Code {...props} />;
export const WarningIcon: IconType = (props) => <Warning style={{ color: '#fbc02d', height: '30px', width: '30px' }} {...props} />;
export const Link: IconType = (props) => <LinkOutlined {...props} />;
import { GridProps } from '@material-ui/core/Grid';
import { isArray } from 'lodash';
import { DefaultView } from 'components/default-view/default-view';
-import { InfoIcon, InvisibleIcon, VisibleIcon } from 'components/icon/icon';
+import { InfoIcon } from 'components/icon/icon';
import { ReactNodeArray } from 'prop-types';
import classNames from 'classnames';
(panelStates[idx] &&
(panelStates[idx].visible || panelStates[idx].visible === undefined)));
const [panelVisibility, setPanelVisibility] = useState<boolean[]>(visibility);
- const [brightenedPanel, setBrightenedPanel] = useState<number>(-1);
+ const [highlightedPanel, setHighlightedPanel] = useState<number>(-1);
+ const [selectedPanel, setSelectedPanel] = useState<number>(-1);
const panelRef = useRef<any>(null);
let panels: JSX.Element[] = [];
- let toggles: JSX.Element[] = [];
+ let buttons: JSX.Element[] = [];
if (isArray(children)) {
for (let idx = 0; idx < children.length; idx++) {
true,
...panelVisibility.slice(idx+1)
]);
+ setSelectedPanel(idx);
};
const hideFn = (idx: number) => () => {
setPanelVisibility([
...panelVisibility.slice(idx+1).map(() => false),
])
};
- const toggleIcon = panelVisibility[idx]
- ? <VisibleIcon className={classNames(classes.buttonIcon)} />
- : <InvisibleIcon className={classNames(classes.buttonIcon)}/>
const panelName = panelStates === undefined
? `Panel ${idx+1}`
: (panelStates[idx] && panelStates[idx].name) || `Panel ${idx+1}`;
- const toggleVariant = "outlined";
- const toggleTooltip = panelVisibility[idx]
- ? ''
- :`Show ${panelName} panel`;
+ const btnVariant = panelVisibility[idx]
+ ? "contained"
+ : "outlined";
+ const btnTooltip = panelVisibility[idx]
+ ? ``
+ :`Open ${panelName} panel`;
const panelIsMaximized = panelVisibility[idx] &&
panelVisibility.filter(e => e).length === 1;
- let brightenerTimer: NodeJS.Timer;
- toggles = [
- ...toggles,
- <Tooltip title={toggleTooltip} disableFocusListener>
- <Button variant={toggleVariant} size="small" color="primary"
+ buttons = [
+ ...buttons,
+ <Tooltip title={btnTooltip} disableFocusListener>
+ <Button variant={btnVariant} size="small" color="primary"
className={classNames(classes.button)}
onMouseEnter={() => {
- brightenerTimer = setTimeout(
- () => setBrightenedPanel(idx), 100);
+ setHighlightedPanel(idx);
}}
onMouseLeave={() => {
- brightenerTimer && clearTimeout(brightenerTimer);
- setBrightenedPanel(-1);
+ setHighlightedPanel(-1);
}}
onClick={showFn(idx)}>
{panelName}
- {toggleIcon}
</Button>
</Tooltip>
];
const aPanel =
<MPVHideablePanel key={idx} visible={panelVisibility[idx]} name={panelName}
- panelRef={(idx === brightenedPanel) ? panelRef : undefined}
- maximized={panelIsMaximized} illuminated={idx === brightenedPanel}
+ panelRef={(idx === selectedPanel) ? panelRef : undefined}
+ maximized={panelIsMaximized} illuminated={idx === highlightedPanel}
doHidePanel={hideFn(idx)} doMaximizePanel={maximizeFn(idx)}>
{children[idx]}
</MPVHideablePanel>;
return <Grid container {...props}>
<Grid container item direction="row">
- { toggles.map((tgl, idx) => <Grid item key={idx}>{tgl}</Grid>) }
+ { buttons.map((tgl, idx) => <Grid item key={idx}>{tgl}</Grid>) }
</Grid>
- <Grid container item {...props} xs className={classes.content}>
+ <Grid container item {...props} xs className={classes.content}
+ onScroll={() => setSelectedPanel(-1)}>
{ panelVisibility.includes(true)
? panels
: <Grid container item alignItems='center' justify='center'>
}
public addFullTextSearch(value: string) {
- const terms = value.trim().split(/(\s+)/);
+ const regex = /"[^"]*"/;
+ const matches: any[] = [];
+
+ let match = value.match(regex);
+
+ while (match) {
+ value = value.replace(match[0], "");
+ matches.push(match[0].replace(/"/g, ''));
+ match = value.match(regex);
+ }
+
+ const terms = value.trim().split(/(\s+)/).concat(matches);
terms.forEach(term => {
if (term !== " ") {
this.addCondition("any", "ilike", term, "%", "%");
// Copy to clipboard omits token to avoid accidental sharing
const url = getNavUrl(resource.uuid, getState().auth, false);
- if (url) {
+ if (url[0] === '/') {
+ copy(`${window.location.origin}${url}`);
+ } else if (url.length) {
copy(url);
}
};
languageName: node
linkType: hard
-"caniuse-lite@npm:1.0.30001299, caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30000981, caniuse-lite@npm:^1.0.30001035, caniuse-lite@npm:^1.0.30001109, caniuse-lite@npm:^1.0.30001219":
+"caniuse-lite@npm:1.0.30001299":
version: 1.0.30001299
resolution: "caniuse-lite@npm:1.0.30001299"
checksum: c770f60ebf3e0cc8043ba4db0ebec12d7a595a6b50cb4437c3c5c55b04de9d2413f711f2828be761e8c37bb46b927a8abe6b199b8f0ffc1a34af0ebdee84be27
languageName: node
linkType: hard
+"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30000981, caniuse-lite@npm:^1.0.30001035, caniuse-lite@npm:^1.0.30001109, caniuse-lite@npm:^1.0.30001219":
+ version: 1.0.30001414
+ resolution: "caniuse-lite@npm:1.0.30001414"
+ checksum: 97210cfd15ded093b20c33d35bef9711a88402c3345411dad420c991a41a3e38ad17fd66721e8334c86e9b2e4aa2c1851d3631f1441afb73b92d93b2b8ca890d
+ languageName: node
+ linkType: hard
+
"capture-exit@npm:^2.0.0":
version: 2.0.0
resolution: "capture-exit@npm:2.0.0"