[ARVADOS-WORKBENCH2] updated: 1.4.1-110-g63ffac0b

Git user git at public.curoverse.com
Wed Nov 13 22:04:18 UTC 2019


Summary of changes:
 src/store/details-panel/details-panel-action.ts    | 10 ++++--
 .../details-panel/project-details.tsx              | 32 ++++++++++++++---
 .../project-properties-dialog.tsx                  | 36 +++++++++++++------
 .../property-key-field.tsx                         | 42 +++++++++++-----------
 .../property-value-field.tsx                       | 42 +++++++++++-----------
 src/views/collection-panel/collection-panel.tsx    | 19 +++++-----
 6 files changed, 110 insertions(+), 71 deletions(-)

       via  63ffac0b419097265599243dd645c0447d1c24d6 (commit)
       via  9caac45e4e1c1bfe42876eaeb74b4c32df6904e3 (commit)
       via  70e0ef7baeb7a27e2048b359b5b3ae204d3b4528 (commit)
       via  83df67242fa95dd321a19189e68e3ce82f1a0837 (commit)
       via  0369ee1292c296942219b9ed49654f7343680eca (commit)
      from  796a3ce005800d37ef5711b367c926ac720577d5 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit 63ffac0b419097265599243dd645c0447d1c24d6
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date:   Wed Nov 13 19:03:37 2019 -0300

    15067: Shows tags labels on project details. Adds copy-on-click feature.
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <ldipentima at veritasgenetics.com>

diff --git a/src/views-components/details-panel/project-details.tsx b/src/views-components/details-panel/project-details.tsx
index 8f03cc5d..7db4df7b 100644
--- a/src/views-components/details-panel/project-details.tsx
+++ b/src/views-components/details-panel/project-details.tsx
@@ -4,6 +4,7 @@
 
 import * as React from 'react';
 import { connect } from 'react-redux';
+import { RootState } from '~/store/store';
 import { openProjectPropertiesDialog } from '~/store/details-panel/details-panel-action';
 import { ProjectIcon, RenameIcon } from '~/components/icon/icon';
 import { ProjectResource } from '~/models/project';
@@ -15,6 +16,11 @@ import { DetailsAttribute } from "~/components/details-attribute/details-attribu
 import { RichTextEditorLink } from '~/components/rich-text-editor-link/rich-text-editor-link';
 import { withStyles, StyleRulesCallback, Chip, WithStyles } from '@material-ui/core';
 import { ArvadosTheme } from '~/common/custom-theme';
+import * as CopyToClipboard from 'react-copy-to-clipboard';
+import { snackbarActions, SnackbarKind } from '~/store/snackbar/snackbar-actions';
+import { getTagValueLabel, getTagKeyLabel, Vocabulary } from '~/models/vocabulary';
+import { getVocabulary } from "~/store/vocabulary/vocabulary-selectors";
+import { Dispatch } from 'redux';
 
 export class ProjectDetails extends DetailsData<ProjectResource> {
     getIcon(className?: string) {
@@ -42,19 +48,32 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
 
 interface ProjectDetailsComponentDataProps {
     project: ProjectResource;
+    vocabulary: Vocabulary;
 }
 
 interface ProjectDetailsComponentActionProps {
     onClick: () => void;
+    onCopy: (message: string) => void;
 }
 
-const mapDispatchToProps = ({ onClick: openProjectPropertiesDialog });
+const mapStateToProps = ({ properties }: RootState) => ({
+    vocabulary: getVocabulary(properties),
+});
+
+const mapDispatchToProps = (dispatch: Dispatch) => ({
+    onClick: () => dispatch<any>(openProjectPropertiesDialog()),
+    onCopy: (message: string) => dispatch(snackbarActions.OPEN_SNACKBAR({
+        message,
+        hideDuration: 2000,
+        kind: SnackbarKind.SUCCESS
+    }))
+});
 
 type ProjectDetailsComponentProps = ProjectDetailsComponentDataProps & ProjectDetailsComponentActionProps & WithStyles<CssRules>;
 
-const ProjectDetailsComponent = connect(null, mapDispatchToProps)(
+const ProjectDetailsComponent = connect(mapStateToProps, mapDispatchToProps)(
     withStyles(styles)(
-        ({ classes, project, onClick }: ProjectDetailsComponentProps) => <div>
+        ({ classes, project, onClick, vocabulary, onCopy }: ProjectDetailsComponentProps) => <div>
             <DetailsAttribute label='Type' value={resourceLabel(ResourceKind.PROJECT)} />
             {/* Missing attr */}
             <DetailsAttribute label='Size' value='---' />
@@ -80,7 +99,12 @@ const ProjectDetailsComponent = connect(null, mapDispatchToProps)(
             </DetailsAttribute>
             {
                 Object.keys(project.properties).map(k => {
-                    return <Chip key={k} className={classes.tag} label={`${k}: ${project.properties[k]}`} />;
+                    const label = `${getTagKeyLabel(k, vocabulary)}: ${getTagValueLabel(k, project.properties[k], vocabulary)}`;
+                    return (
+                        <CopyToClipboard key={k} text={label} onCopy={() => onCopy("Copied")}>
+                            <Chip key={k} className={classes.tag} label={label} />
+                        </CopyToClipboard>
+                    );
                 })
             }
         </div>
diff --git a/src/views-components/project-properties-dialog/project-properties-dialog.tsx b/src/views-components/project-properties-dialog/project-properties-dialog.tsx
index caedd4e6..a071a985 100644
--- a/src/views-components/project-properties-dialog/project-properties-dialog.tsx
+++ b/src/views-components/project-properties-dialog/project-properties-dialog.tsx
@@ -13,6 +13,10 @@ import { Dialog, DialogTitle, DialogContent, DialogActions, Button, Chip, withSt
 import { ArvadosTheme } from '~/common/custom-theme';
 import { ProjectPropertiesForm } from '~/views-components/project-properties-dialog/project-properties-form';
 import { getResource } from '~/store/resources/resources';
+import * as CopyToClipboard from 'react-copy-to-clipboard';
+import { snackbarActions, SnackbarKind } from '~/store/snackbar/snackbar-actions';
+import { getTagValueLabel, getTagKeyLabel, Vocabulary } from '~/models/vocabulary';
+import { getVocabulary } from "~/store/vocabulary/vocabulary-selectors";
 
 type CssRules = 'tag';
 
@@ -25,19 +29,26 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
 
 interface ProjectPropertiesDialogDataProps {
     project: ProjectResource;
+    vocabulary: Vocabulary;
 }
 
 interface ProjectPropertiesDialogActionProps {
     handleDelete: (key: string) => void;
+    onCopy: (message: string) => void;
 }
 
-const mapStateToProps = ({ detailsPanel, resources }: RootState): ProjectPropertiesDialogDataProps => {
-    const project = getResource(detailsPanel.resourceUuid)(resources) as ProjectResource;
-    return { project };
-};
+const mapStateToProps = ({ detailsPanel, resources, properties }: RootState): ProjectPropertiesDialogDataProps => ({
+    project: getResource(detailsPanel.resourceUuid)(resources) as ProjectResource,
+    vocabulary: getVocabulary(properties),
+});
 
 const mapDispatchToProps = (dispatch: Dispatch): ProjectPropertiesDialogActionProps => ({
-    handleDelete: (key: string) => dispatch<any>(deleteProjectProperty(key))
+    handleDelete: (key: string) => dispatch<any>(deleteProjectProperty(key)),
+    onCopy: (message: string) => dispatch(snackbarActions.OPEN_SNACKBAR({
+                message,
+                hideDuration: 2000,
+                kind: SnackbarKind.SUCCESS
+            }))
 });
 
 type ProjectPropertiesDialogProps =  ProjectPropertiesDialogDataProps & ProjectPropertiesDialogActionProps & WithDialogProps<{}> & WithStyles<CssRules>;
@@ -45,7 +56,7 @@ type ProjectPropertiesDialogProps =  ProjectPropertiesDialogDataProps & ProjectP
 export const ProjectPropertiesDialog = connect(mapStateToProps, mapDispatchToProps)(
     withStyles(styles)(
     withDialog(PROJECT_PROPERTIES_DIALOG_NAME)(
-        ({ classes, open, closeDialog, handleDelete, project }: ProjectPropertiesDialogProps) =>
+        ({ classes, open, closeDialog, handleDelete, onCopy, project, vocabulary }: ProjectPropertiesDialogProps) =>
             <Dialog open={open}
                 onClose={closeDialog}
                 fullWidth
@@ -53,11 +64,16 @@ export const ProjectPropertiesDialog = connect(mapStateToProps, mapDispatchToPro
                 <DialogTitle>Properties</DialogTitle>
                 <DialogContent>
                     <ProjectPropertiesForm />
-                    {project && project.properties && 
+                    {project && project.properties &&
                         Object.keys(project.properties).map(k => {
-                            return <Chip key={k} className={classes.tag}
-                                onDelete={() => handleDelete(k)}
-                                label={`${k}: ${project.properties[k]}`} />;
+                            const label = `${getTagKeyLabel(k, vocabulary)}: ${getTagValueLabel(k, project.properties[k], vocabulary)}`;
+                            return (
+                                <CopyToClipboard key={k} text={label} onCopy={() => onCopy("Copied")}>
+                                    <Chip key={k} className={classes.tag}
+                                        onDelete={() => handleDelete(k)}
+                                        label={label} />
+                                </CopyToClipboard>
+                            );
                         })
                     }
                 </DialogContent>

commit 9caac45e4e1c1bfe42876eaeb74b4c32df6904e3
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date:   Wed Nov 13 19:02:59 2019 -0300

    15067: Creates project tags by id when possible.
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <ldipentima at veritasgenetics.com>

diff --git a/src/store/details-panel/details-panel-action.ts b/src/store/details-panel/details-panel-action.ts
index 8083716e..68746714 100644
--- a/src/store/details-panel/details-panel-action.ts
+++ b/src/store/details-panel/details-panel-action.ts
@@ -60,8 +60,14 @@ export const createProjectProperty = (data: TagProperty) =>
         dispatch(startSubmit(PROJECT_PROPERTIES_FORM_NAME));
         try {
             if (project) {
-                project.properties[data.key] = data.value;
-                const updatedProject = await services.projectService.update(project.uuid, { properties: project.properties });
+                const updatedProject = await services.projectService.update(
+                    project.uuid, {
+                        properties: {
+                            ...JSON.parse(JSON.stringify(project.properties)),
+                            [data.keyID || data.key]: data.valueID || data.value
+                        }
+                    }
+                );
                 dispatch(resourcesActions.SET_RESOURCES([updatedProject]));
                 dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Property has been successfully added.", hideDuration: 2000, kind: SnackbarKind.SUCCESS }));
                 dispatch(stopSubmit(PROJECT_PROPERTIES_FORM_NAME));

commit 70e0ef7baeb7a27e2048b359b5b3ae204d3b4528
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date:   Wed Nov 13 19:01:53 2019 -0300

    15067: Generalizes Key/Value fields to be reused on different forms.
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <ldipentima at veritasgenetics.com>

diff --git a/src/views-components/resource-properties-form/property-key-field.tsx b/src/views-components/resource-properties-form/property-key-field.tsx
index eb3c8050..ef51d250 100644
--- a/src/views-components/resource-properties-form/property-key-field.tsx
+++ b/src/views-components/resource-properties-form/property-key-field.tsx
@@ -3,13 +3,13 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import * as React from 'react';
-import { change, WrappedFieldProps, WrappedFieldMetaProps, WrappedFieldInputProps, Field } from 'redux-form';
+import { change, WrappedFieldProps, WrappedFieldMetaProps, WrappedFieldInputProps,
+    Field, FormName } from 'redux-form';
 import { memoize } from 'lodash';
 import { Autocomplete } from '~/components/autocomplete/autocomplete';
 import { Vocabulary, getTags, getTagKeyID, PropFieldSuggestion } from '~/models/vocabulary';
 import { connectVocabulary, VocabularyProp, buildProps } from '~/views-components/resource-properties-form/property-field-common';
 import { TAG_KEY_VALIDATION } from '~/validators/validators';
-import { COLLECTION_TAG_FORM_NAME } from '~/store/collection-panel/collection-panel-action';
 import { escapeRegExp } from '~/common/regexp.ts';
 
 export const PROPERTY_KEY_FIELD_NAME = 'key';
@@ -25,13 +25,15 @@ export const PropertyKeyField = connectVocabulary(
 );
 
 export const PropertyKeyInput = ({ vocabulary, ...props }: WrappedFieldProps & VocabularyProp) =>
-    <Autocomplete
-        label='Key'
-        suggestions={getSuggestions(props.input.value, vocabulary)}
-        onSelect={handleSelect(props.input, props.meta)}
-        {...buildProps(props)}
-        onBlur={handleBlur(props.meta, props.input, vocabulary)}
-    />;
+    <FormName children={data => (
+        <Autocomplete
+            label='Key'
+            suggestions={getSuggestions(props.input.value, vocabulary)}
+            onSelect={handleSelect(data.form, props.input, props.meta)}
+            {...buildProps(props)}
+            onBlur={handleBlur(data.form, props.meta, props.input, vocabulary)}
+        />
+    )}/>;
 
 const getValidation = memoize(
     (vocabulary: Vocabulary) =>
@@ -53,20 +55,22 @@ const getSuggestions = (value: string, vocabulary: Vocabulary) => {
 // Attempts to match a manually typed key label with a key ID, when the user
 // doesn't select the key from the suggestions list.
 const handleBlur = (
+    formName: string,
     { dispatch }: WrappedFieldMetaProps,
     { onBlur, value }: WrappedFieldInputProps,
     vocabulary: Vocabulary) =>
     () => {
-        dispatch(change(COLLECTION_TAG_FORM_NAME, PROPERTY_KEY_FIELD_ID, getTagKeyID(value, vocabulary)));
+        dispatch(change(formName, PROPERTY_KEY_FIELD_ID, getTagKeyID(value, vocabulary)));
         onBlur(value);
     };
 
 // When selecting a property key, save its ID for later usage.
 const handleSelect = (
+    formName: string,
     { onChange }: WrappedFieldInputProps,
     { dispatch }: WrappedFieldMetaProps) => {
         return (item:PropFieldSuggestion) => {
             onChange(item.label);
-            dispatch(change(COLLECTION_TAG_FORM_NAME, PROPERTY_KEY_FIELD_ID, item.id));
+            dispatch(change(formName, PROPERTY_KEY_FIELD_ID, item.id));
     };
 };
diff --git a/src/views-components/resource-properties-form/property-value-field.tsx b/src/views-components/resource-properties-form/property-value-field.tsx
index c2474735..e34170bc 100644
--- a/src/views-components/resource-properties-form/property-value-field.tsx
+++ b/src/views-components/resource-properties-form/property-value-field.tsx
@@ -3,14 +3,14 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import * as React from 'react';
-import { change, WrappedFieldProps, WrappedFieldMetaProps, WrappedFieldInputProps, Field, formValues } from 'redux-form';
+import { change, WrappedFieldProps, WrappedFieldMetaProps, WrappedFieldInputProps,
+    Field, formValues, FormName } from 'redux-form';
 import { compose } from 'redux';
 import { Autocomplete } from '~/components/autocomplete/autocomplete';
 import { Vocabulary, getTagValueID, isStrictTag, getTagValues, PropFieldSuggestion } from '~/models/vocabulary';
 import { PROPERTY_KEY_FIELD_ID } from '~/views-components/resource-properties-form/property-key-field';
 import { VocabularyProp, connectVocabulary, buildProps } from '~/views-components/resource-properties-form/property-field-common';
 import { TAG_VALUE_VALIDATION } from '~/validators/validators';
-import { COLLECTION_TAG_FORM_NAME } from '~/store/collection-panel/collection-panel-action';
 import { escapeRegExp } from '~/common/regexp.ts';
 
 interface PropertyKeyProp {
@@ -35,13 +35,15 @@ export const PropertyValueField = compose(
 );
 
 export const PropertyValueInput = ({ vocabulary, propertyKey, ...props }: WrappedFieldProps & PropertyValueFieldProps) =>
-    <Autocomplete
-        label='Value'
-        suggestions={getSuggestions(props.input.value, propertyKey, vocabulary)}
-        onSelect={handleSelect(props.input, props.meta)}
-        {...buildProps(props)}
-        onBlur={handleBlur(props.meta, props.input, vocabulary, propertyKey)}
-    />;
+    <FormName children={data => (
+        <Autocomplete
+            label='Value'
+            suggestions={getSuggestions(props.input.value, propertyKey, vocabulary)}
+            onSelect={handleSelect(data.form, props.input, props.meta)}
+            {...buildProps(props)}
+            onBlur={handleBlur(data.form, props.meta, props.input, vocabulary, propertyKey)}
+        />
+    )}/>;
 
 const getValidation = (props: PropertyValueFieldProps) =>
     isStrictTag(props.propertyKey, props.vocabulary)
@@ -62,21 +64,23 @@ const getSuggestions = (value: string, tagName: string, vocabulary: Vocabulary)
 // Attempts to match a manually typed value label with a value ID, when the user
 // doesn't select the value from the suggestions list.
 const handleBlur = (
+    formName: string,
     { dispatch }: WrappedFieldMetaProps,
     { onBlur, value }: WrappedFieldInputProps,
     vocabulary: Vocabulary,
     tagKeyID: string) =>
         () => {
-            dispatch(change(COLLECTION_TAG_FORM_NAME, PROPERTY_VALUE_FIELD_ID, getTagValueID(tagKeyID, value, vocabulary)));
+            dispatch(change(formName, PROPERTY_VALUE_FIELD_ID, getTagValueID(tagKeyID, value, vocabulary)));
             onBlur(value);
         };
 
 // When selecting a property value, save its ID for later usage.
 const handleSelect = (
+    formName: string,
     { onChange }: WrappedFieldInputProps,
     { dispatch }: WrappedFieldMetaProps) => {
         return (item:PropFieldSuggestion) => {
             onChange(item.label);
-            dispatch(change(COLLECTION_TAG_FORM_NAME, PROPERTY_VALUE_FIELD_ID, item.id));
+            dispatch(change(formName, PROPERTY_VALUE_FIELD_ID, item.id));
     };
 };

commit 83df67242fa95dd321a19189e68e3ce82f1a0837
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date:   Wed Nov 13 17:31:31 2019 -0300

    15067: Removes unnecesssary hidden Field components.
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <ldipentima at veritasgenetics.com>

diff --git a/src/views-components/resource-properties-form/property-key-field.tsx b/src/views-components/resource-properties-form/property-key-field.tsx
index f91b6a62..eb3c8050 100644
--- a/src/views-components/resource-properties-form/property-key-field.tsx
+++ b/src/views-components/resource-properties-form/property-key-field.tsx
@@ -17,17 +17,11 @@ export const PROPERTY_KEY_FIELD_ID = 'keyID';
 
 export const PropertyKeyField = connectVocabulary(
     ({ vocabulary }: VocabularyProp) =>
-        <div>
-            <Field
-                name={PROPERTY_KEY_FIELD_NAME}
-                component={PropertyKeyInput}
-                vocabulary={vocabulary}
-                validate={getValidation(vocabulary)} />
-            <Field
-                name={PROPERTY_KEY_FIELD_ID}
-                type='hidden'
-                component='input' />
-        </div>
+        <Field
+            name={PROPERTY_KEY_FIELD_NAME}
+            component={PropertyKeyInput}
+            vocabulary={vocabulary}
+            validate={getValidation(vocabulary)} />
 );
 
 export const PropertyKeyInput = ({ vocabulary, ...props }: WrappedFieldProps & VocabularyProp) =>
diff --git a/src/views-components/resource-properties-form/property-value-field.tsx b/src/views-components/resource-properties-form/property-value-field.tsx
index 959b98ec..c2474735 100644
--- a/src/views-components/resource-properties-form/property-value-field.tsx
+++ b/src/views-components/resource-properties-form/property-value-field.tsx
@@ -27,17 +27,11 @@ export const PropertyValueField = compose(
     formValues({ propertyKey: PROPERTY_KEY_FIELD_ID })
 )(
     (props: PropertyValueFieldProps) =>
-        <div>
-            <Field
-                name={PROPERTY_VALUE_FIELD_NAME}
-                component={PropertyValueInput}
-                validate={getValidation(props)}
-                {...props} />
-            <Field
-                name={PROPERTY_VALUE_FIELD_ID}
-                type='hidden'
-                component='input' />
-        </div>
+        <Field
+            name={PROPERTY_VALUE_FIELD_NAME}
+            component={PropertyValueInput}
+            validate={getValidation(props)}
+            {...props} />
 );
 
 export const PropertyValueInput = ({ vocabulary, propertyKey, ...props }: WrappedFieldProps & PropertyValueFieldProps) =>

commit 0369ee1292c296942219b9ed49654f7343680eca
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date:   Wed Nov 13 17:20:57 2019 -0300

    15067: Clicking on a property chip copies its visual representation.
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <ldipentima at veritasgenetics.com>

diff --git a/src/views/collection-panel/collection-panel.tsx b/src/views/collection-panel/collection-panel.tsx
index f4d6532e..87768e64 100644
--- a/src/views/collection-panel/collection-panel.tsx
+++ b/src/views/collection-panel/collection-panel.tsx
@@ -136,17 +136,14 @@ export const CollectionPanel = compose(
                                         <CollectionTagForm />
                                     </Grid>
                                     <Grid item xs={12}>
-                                        {
-                                            Object.keys(item.properties).map(k => {
-                                                const ids = `${k}: ${item.properties[k]}`;
-                                                const label = `${getTagKeyLabel(k, vocabulary)}: ${getTagValueLabel(k, item.properties[k], vocabulary)}`;
-                                                return <CopyToClipboard key={k} text={ids} onCopy={() => this.onCopy("Copied")}>
-                                                    <Chip className={classes.tag}
-                                                        onDelete={this.handleDelete(k)}
-                                                        label={label} />
-                                                </CopyToClipboard>;
-                                            })
-                                        }
+                                        {Object.keys(item.properties).map(k => {
+                                            const label = `${getTagKeyLabel(k, vocabulary)}: ${getTagValueLabel(k, item.properties[k], vocabulary)}`;
+                                            return <CopyToClipboard key={k} text={label} onCopy={() => this.onCopy("Copied")}>
+                                                <Chip className={classes.tag}
+                                                    onDelete={this.handleDelete(k)}
+                                                    label={label} />
+                                            </CopyToClipboard>;
+                                        })}
                                     </Grid>
                                 </Grid>
                             </CardContent>

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list