[ARVADOS-WORKBENCH2] created: 1.4.1-262-g41658ace
Git user
git at public.arvados.org
Mon Feb 3 21:40:32 UTC 2020
at 41658ace1742a1bc6af651962a6207f7de8ecd92 (commit)
commit 41658ace1742a1bc6af651962a6207f7de8ecd92
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Mon Feb 3 18:39:51 2020 -0300
15781: Adds tests for resource properties util functions.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/src/lib/resource-properties.test.ts b/src/lib/resource-properties.test.ts
new file mode 100644
index 00000000..c70b2315
--- /dev/null
+++ b/src/lib/resource-properties.test.ts
@@ -0,0 +1,59 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as _ from "./resource-properties";
+import { omit } from "lodash";
+
+describe("Resource properties lib", () => {
+
+ let properties: any;
+
+ beforeEach(() => {
+ properties = {
+ animal: 'dog',
+ color: ['brown', 'black'],
+ name: ['Toby']
+ }
+ })
+
+ it("should convert a single string value into a list when adding values", () => {
+ expect(
+ _.addProperty(properties, 'animal', 'cat')
+ ).toEqual({
+ ...properties, animal: ['dog', 'cat']
+ });
+ });
+
+ it("should convert a 2 value list into a string when removing values", () => {
+ expect(
+ _.deleteProperty(properties, 'color', 'brown')
+ ).toEqual({
+ ...properties, color: 'black'
+ });
+ });
+
+ it("shouldn't add duplicated key:value items", () => {
+ expect(
+ _.addProperty(properties, 'animal', 'dog')
+ ).toEqual(properties);
+ });
+
+ it("should remove the key when deleting from a one value list", () => {
+ expect(
+ _.deleteProperty(properties, 'name', 'Toby')
+ ).toEqual(omit(properties, 'name'));
+ });
+
+ it("should return the same when deleting non-existant value", () => {
+ expect(
+ _.deleteProperty(properties, 'animal', 'dolphin')
+ ).toEqual(properties);
+ });
+
+ it("should return the same when deleting non-existant key", () => {
+ expect(
+ _.deleteProperty(properties, 'doesntexist', 'something')
+ ).toEqual(properties);
+ });
+});
\ No newline at end of file
commit 4a18204b2d02945a4f828f8f180bf6a333e6f8d9
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Mon Feb 3 18:02:59 2020 -0300
15781: Allows multi-value properties on the search bar/editor.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/src/store/search-bar/search-bar-actions.ts b/src/store/search-bar/search-bar-actions.ts
index c12fcbe4..4af132ea 100644
--- a/src/store/search-bar/search-bar-actions.ts
+++ b/src/store/search-bar/search-bar-actions.ts
@@ -232,9 +232,16 @@ const buildQueryFromKeyMap = (data: any, keyMap: string[][], mode: 'rebuild' | '
const v = data[key];
if (data.hasOwnProperty(key)) {
- const pattern = v === false
- ? `${field.replace(':', '\\:\\s*')}\\s*`
- : `${field.replace(':', '\\:\\s*')}\\:\\s*"[\\w|\\#|\\-|\\/]*"\\s*`;
+ let pattern: string;
+ if (v === false) {
+ pattern = `${field.replace(':', '\\:\\s*')}\\s*`;
+ } else if (key.startsWith('prop-')) {
+ // On properties, only remove key:value duplicates, allowing
+ // multiple properties with the same key.
+ pattern = `${field.replace(':', '\\:\\s*')}\\:\\s*${v}\\s*`;
+ } else {
+ pattern = `${field.replace(':', '\\:\\s*')}\\:\\s*[\\w|\\#|\\-|\\/]*\\s*`;
+ }
value = value.replace(new RegExp(pattern), '');
}
diff --git a/src/views-components/search-bar/search-bar-advanced-properties-view.tsx b/src/views-components/search-bar/search-bar-advanced-properties-view.tsx
index eb049b76..8add4b02 100644
--- a/src/views-components/search-bar/search-bar-advanced-properties-view.tsx
+++ b/src/views-components/search-bar/search-bar-advanced-properties-view.tsx
@@ -67,7 +67,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({
setProp: (propertyValue: PropertyValue, properties: PropertyValue[]) => {
dispatch<any>(changeAdvancedFormProperty(
'properties',
- [...properties.filter(e => e.keyID! !== propertyValue.keyID!), propertyValue]
+ [...properties, propertyValue]
));
dispatch<any>(resetAdvancedFormProperty('key'));
dispatch<any>(resetAdvancedFormProperty('value'));
commit 32c4bd51747de281957d7bbcd3f90879270ad6fa
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Fri Jan 31 15:38:36 2020 -0300
15781: Uses 'contains' filter operator to search for properties.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/src/services/api/filter-builder.test.ts b/src/services/api/filter-builder.test.ts
index d9656934..a4e2b229 100644
--- a/src/services/api/filter-builder.test.ts
+++ b/src/services/api/filter-builder.test.ts
@@ -36,6 +36,12 @@ describe("FilterBuilder", () => {
).toEqual(`["etag","ilike","%etagValue%"]`);
});
+ it("should add 'contains' rule", () => {
+ expect(
+ filters.addContains("properties.someProp", "someValue").getFilters()
+ ).toEqual(`["properties.someProp","contains","someValue"]`);
+ });
+
it("should add 'is_a' rule", () => {
expect(
filters.addIsA("etag", "etagValue").getFilters()
diff --git a/src/services/api/filter-builder.ts b/src/services/api/filter-builder.ts
index 102ff62c..489f7b89 100644
--- a/src/services/api/filter-builder.ts
+++ b/src/services/api/filter-builder.ts
@@ -25,6 +25,10 @@ export class FilterBuilder {
return this.addCondition(field, "ilike", value, "%", "%", resourcePrefix);
}
+ public addContains(field: string, value?: string, resourcePrefix?: string) {
+ return this.addCondition(field, "contains", value, "", "", resourcePrefix);
+ }
+
public addIsA(field: string, value?: string | string[], resourcePrefix?: string) {
return this.addCondition(field, "is_a", value, "", "", resourcePrefix);
}
diff --git a/src/store/search-bar/search-bar-actions.ts b/src/store/search-bar/search-bar-actions.ts
index b91dc9d1..c12fcbe4 100644
--- a/src/store/search-bar/search-bar-actions.ts
+++ b/src/store/search-bar/search-bar-actions.ts
@@ -353,8 +353,8 @@ export const queryToFilters = (query: string) => {
data.properties.forEach(p => {
if (p.value) {
filter
- .addILike(`properties.${p.key}`, p.value, GroupContentsResourcePrefix.PROJECT)
- .addILike(`properties.${p.key}`, p.value, GroupContentsResourcePrefix.COLLECTION);
+ .addContains(`properties.${p.key}`, p.value, GroupContentsResourcePrefix.PROJECT)
+ .addContains(`properties.${p.key}`, p.value, GroupContentsResourcePrefix.COLLECTION);
}
filter.addExists(p.key);
});
commit dd0e60751f2551d78344283105e8c91adb9c3e19
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Fri Jan 31 14:05:50 2020 -0300
15781: Adds multi-value property support for projects.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/src/lib/resource-properties.ts b/src/lib/resource-properties.ts
new file mode 100644
index 00000000..02f13b62
--- /dev/null
+++ b/src/lib/resource-properties.ts
@@ -0,0 +1,35 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+export const deleteProperty = (properties: any, key: string, value: string) => {
+ if (Array.isArray(properties[key])) {
+ properties[key] = properties[key].filter((v: string) => v !== value);
+ if (properties[key].length === 1) {
+ properties[key] = properties[key][0];
+ } else if (properties[key].length === 0) {
+ delete properties[key];
+ }
+ } else if (properties[key] === value) {
+ delete properties[key];
+ }
+ return properties;
+}
+
+export const addProperty = (properties: any, key: string, value: string) => {
+ if (properties[key]) {
+ if (Array.isArray(properties[key])) {
+ properties[key] = [...properties[key], value];
+ } else {
+ properties[key] = [properties[key], value];
+ }
+ // Remove potential duplicate and save as single value if needed
+ properties[key] = Array.from(new Set(properties[key]));
+ if (properties[key].length === 1) {
+ properties[key] = properties[key][0];
+ }
+ } else {
+ properties[key] = value;
+ }
+ return properties;
+}
\ No newline at end of file
diff --git a/src/store/collection-panel/collection-panel-action.ts b/src/store/collection-panel/collection-panel-action.ts
index f4244389..fee5bcd6 100644
--- a/src/store/collection-panel/collection-panel-action.ts
+++ b/src/store/collection-panel/collection-panel-action.ts
@@ -16,6 +16,7 @@ import { unionize, ofType, UnionOf } from '~/common/unionize';
import { SnackbarKind } from '~/store/snackbar/snackbar-actions';
import { navigateTo } from '~/store/navigation/navigation-action';
import { loadDetailsPanel } from '~/store/details-panel/details-panel-action';
+import { deleteProperty, addProperty } from "~/lib/resource-properties";
export const collectionPanelActions = unionize({
SET_COLLECTION: ofType<CollectionResource>(),
@@ -47,20 +48,10 @@ export const createCollectionTag = (data: TagProperty) =>
if (item) {
const key = data.keyID || data.key;
const value = data.valueID || data.value;
- if (item.properties[key]) {
- if (Array.isArray(item.properties[key])) {
- item.properties[key] = [...item.properties[key], value];
- // Remove potential duplicates
- item.properties[key] = Array.from(new Set(item.properties[key]));
- } else {
- item.properties[key] = [item.properties[key], value];
- }
- } else {
- item.properties[key] = value;
- }
+ item.properties = addProperty(item.properties, key, value);
const updatedCollection = await services.collectionService.update(
uuid, {
- properties: {...JSON.parse(JSON.stringify(item.properties))}
+ properties: {...item.properties}
}
);
item.properties = updatedCollection.properties;
@@ -91,16 +82,7 @@ export const deleteCollectionTag = (key: string, value: string) =>
const uuid = item ? item.uuid : '';
try {
if (item) {
- if (Array.isArray(item.properties[key])) {
- item.properties[key] = item.properties[key].filter((v: string) => v !== value);
- if (item.properties[key].length === 1) {
- item.properties[key] = item.properties[key][0];
- } else if (item.properties[key].length === 0) {
- delete item.properties[key];
- }
- } else if (item.properties[key] === value) {
- delete item.properties[key];
- }
+ item.properties = deleteProperty(item.properties, key, value);
const updatedCollection = await services.collectionService.update(
uuid, {
diff --git a/src/store/details-panel/details-panel-action.ts b/src/store/details-panel/details-panel-action.ts
index 68746714..e0d72017 100644
--- a/src/store/details-panel/details-panel-action.ts
+++ b/src/store/details-panel/details-panel-action.ts
@@ -13,6 +13,7 @@ import { TagProperty } from '~/models/tag';
import { startSubmit, stopSubmit } from 'redux-form';
import { resourcesActions } from '~/store/resources/resources-actions';
import {snackbarActions, SnackbarKind} from '~/store/snackbar/snackbar-actions';
+import { addProperty, deleteProperty } from '~/lib/resource-properties';
export const SLIDE_TIMEOUT = 500;
@@ -36,13 +37,13 @@ export const openProjectPropertiesDialog = () =>
dispatch<any>(dialogActions.OPEN_DIALOG({ id: PROJECT_PROPERTIES_DIALOG_NAME, data: { } }));
};
-export const deleteProjectProperty = (key: string) =>
+export const deleteProjectProperty = (key: string, value: string) =>
async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
const { detailsPanel, resources } = getState();
const project = getResource(detailsPanel.resourceUuid)(resources) as ProjectResource;
try {
if (project) {
- delete project.properties[key];
+ project.properties = deleteProperty(project.properties, key, value);
const updatedProject = await services.projectService.update(project.uuid, { properties: project.properties });
dispatch(resourcesActions.SET_RESOURCES([updatedProject]));
dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Property has been successfully deleted.", hideDuration: 2000, kind: SnackbarKind.SUCCESS }));
@@ -60,12 +61,12 @@ export const createProjectProperty = (data: TagProperty) =>
dispatch(startSubmit(PROJECT_PROPERTIES_FORM_NAME));
try {
if (project) {
+ const key = data.keyID || data.key;
+ const value = data.valueID || data.value;
+ project.properties = addProperty(project.properties, key, value);
const updatedProject = await services.projectService.update(
project.uuid, {
- properties: {
- ...JSON.parse(JSON.stringify(project.properties)),
- [data.keyID || data.key]: data.valueID || data.value
- }
+ properties: {...project.properties}
}
);
dispatch(resourcesActions.SET_RESOURCES([updatedProject]));
diff --git a/src/views-components/details-panel/project-details.tsx b/src/views-components/details-panel/project-details.tsx
index 59035da1..1be04b00 100644
--- a/src/views-components/details-panel/project-details.tsx
+++ b/src/views-components/details-panel/project-details.tsx
@@ -16,7 +16,7 @@ import { RichTextEditorLink } from '~/components/rich-text-editor-link/rich-text
import { withStyles, StyleRulesCallback, WithStyles } from '@material-ui/core';
import { ArvadosTheme } from '~/common/custom-theme';
import { Dispatch } from 'redux';
-import { PropertyChipComponent } from '../resource-properties-form/property-chip';
+import { getPropertyChip } from '../resource-properties-form/property-chip';
export class ProjectDetails extends DetailsData<ProjectResource> {
getIcon(className?: string) {
@@ -83,9 +83,10 @@ const ProjectDetailsComponent = connect(null, mapDispatchToProps)(
</DetailsAttribute>
{
Object.keys(project.properties).map(k =>
- <PropertyChipComponent key={k}
- propKey={k} propValue={project.properties[k]}
- className={classes.tag} />
+ Array.isArray(project.properties[k])
+ ? project.properties[k].map((v: string) =>
+ getPropertyChip(k, v, undefined, classes.tag))
+ : getPropertyChip(k, project.properties[k], undefined, classes.tag)
)
}
</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 7a4cfba6..e1874d95 100644
--- a/src/views-components/project-properties-dialog/project-properties-dialog.tsx
+++ b/src/views-components/project-properties-dialog/project-properties-dialog.tsx
@@ -13,7 +13,7 @@ import { Dialog, DialogTitle, DialogContent, DialogActions, Button, withStyles,
import { ArvadosTheme } from '~/common/custom-theme';
import { ProjectPropertiesForm } from '~/views-components/project-properties-dialog/project-properties-form';
import { getResource } from '~/store/resources/resources';
-import { PropertyChipComponent } from "../resource-properties-form/property-chip";
+import { getPropertyChip } from "../resource-properties-form/property-chip";
type CssRules = 'tag';
@@ -29,7 +29,7 @@ interface ProjectPropertiesDialogDataProps {
}
interface ProjectPropertiesDialogActionProps {
- handleDelete: (key: string) => void;
+ handleDelete: (key: string, value: string) => void;
}
const mapStateToProps = ({ detailsPanel, resources, properties }: RootState): ProjectPropertiesDialogDataProps => ({
@@ -37,7 +37,7 @@ const mapStateToProps = ({ detailsPanel, resources, properties }: RootState): Pr
});
const mapDispatchToProps = (dispatch: Dispatch): ProjectPropertiesDialogActionProps => ({
- handleDelete: (key: string) => dispatch<any>(deleteProjectProperty(key)),
+ handleDelete: (key: string, value: string) => () => dispatch<any>(deleteProjectProperty(key, value)),
});
type ProjectPropertiesDialogProps = ProjectPropertiesDialogDataProps & ProjectPropertiesDialogActionProps & WithDialogProps<{}> & WithStyles<CssRules>;
@@ -55,10 +55,17 @@ export const ProjectPropertiesDialog = connect(mapStateToProps, mapDispatchToPro
<ProjectPropertiesForm />
{project && project.properties &&
Object.keys(project.properties).map(k =>
- <PropertyChipComponent
- onDelete={() => handleDelete(k)}
- key={k} className={classes.tag}
- propKey={k} propValue={project.properties[k]} />)
+ Array.isArray(project.properties[k])
+ ? project.properties[k].map((v: string) =>
+ getPropertyChip(
+ k, v,
+ handleDelete(k, v),
+ classes.tag))
+ : getPropertyChip(
+ k, project.properties[k],
+ handleDelete(k, project.properties[k]),
+ classes.tag)
+ )
}
</DialogContent>
<DialogActions>
diff --git a/src/views-components/resource-properties-form/property-chip.tsx b/src/views-components/resource-properties-form/property-chip.tsx
index c51a8d8e..f25deb70 100644
--- a/src/views-components/resource-properties-form/property-chip.tsx
+++ b/src/views-components/resource-properties-form/property-chip.tsx
@@ -50,3 +50,9 @@ export const PropertyChipComponent = connect(mapStateToProps, mapDispatchToProps
);
}
);
+
+export const getPropertyChip = (k:string, v:string, handleDelete:any, className:string) =>
+ <PropertyChipComponent
+ key={k} className={className}
+ onDelete={handleDelete}
+ propKey={k} propValue={v} />;
diff --git a/src/views/collection-panel/collection-panel.tsx b/src/views/collection-panel/collection-panel.tsx
index cc918808..c4221937 100644
--- a/src/views/collection-panel/collection-panel.tsx
+++ b/src/views/collection-panel/collection-panel.tsx
@@ -23,7 +23,7 @@ import { ContextMenuKind } from '~/views-components/context-menu/context-menu';
import { formatFileSize } from "~/common/formatters";
import { openDetailsPanel } from '~/store/details-panel/details-panel-action';
import { snackbarActions, SnackbarKind } from '~/store/snackbar/snackbar-actions';
-import { PropertyChipComponent } from '~/views-components/resource-properties-form/property-chip';
+import { getPropertyChip } from '~/views-components/resource-properties-form/property-chip';
import { IllegalNamingWarning } from '~/components/warning/warning';
type CssRules = 'card' | 'iconHeader' | 'tag' | 'label' | 'value' | 'link';
@@ -130,8 +130,14 @@ export const CollectionPanel = withStyles(styles)(
{Object.keys(item.properties).map(k =>
Array.isArray(item.properties[k])
? item.properties[k].map((v: string) =>
- getPropertyChip(k, v, this.handleDelete, classes.tag))
- : getPropertyChip(k, item.properties[k], this.handleDelete, classes.tag)
+ getPropertyChip(
+ k, v,
+ this.handleDelete(k, v),
+ classes.tag))
+ : getPropertyChip(
+ k, item.properties[k],
+ this.handleDelete(k, item.properties[k]),
+ classes.tag)
)}
</Grid>
</Grid>
@@ -184,10 +190,3 @@ export const CollectionPanel = withStyles(styles)(
}
)
);
-
-const getPropertyChip = (k:string, v:string, handleDelete:any, className:string) =>
- <PropertyChipComponent
- key={k} className={className}
- onDelete={handleDelete(k, v)}
- propKey={k} propValue={v} />;
-
commit 0cc06c813afc8373f3c6675c3519960382a7067f
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Thu Jan 30 18:05:45 2020 -0300
15781: Adds support for multi-value property additions on collections.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/src/store/collection-panel/collection-panel-action.ts b/src/store/collection-panel/collection-panel-action.ts
index 122fc5e3..f4244389 100644
--- a/src/store/collection-panel/collection-panel-action.ts
+++ b/src/store/collection-panel/collection-panel-action.ts
@@ -45,12 +45,22 @@ export const createCollectionTag = (data: TagProperty) =>
const uuid = item ? item.uuid : '';
try {
if (item) {
+ const key = data.keyID || data.key;
+ const value = data.valueID || data.value;
+ if (item.properties[key]) {
+ if (Array.isArray(item.properties[key])) {
+ item.properties[key] = [...item.properties[key], value];
+ // Remove potential duplicates
+ item.properties[key] = Array.from(new Set(item.properties[key]));
+ } else {
+ item.properties[key] = [item.properties[key], value];
+ }
+ } else {
+ item.properties[key] = value;
+ }
const updatedCollection = await services.collectionService.update(
uuid, {
- properties: {
- ...JSON.parse(JSON.stringify(item.properties)),
- [data.keyID || data.key]: data.valueID || data.value
- }
+ properties: {...JSON.parse(JSON.stringify(item.properties))}
}
);
item.properties = updatedCollection.properties;
commit f6669f3c7b2184ae4175e43f05cd6ea972624145
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Thu Jan 30 17:15:26 2020 -0300
15781: Renders multi-value properties as multiple chips.
Also, adds support for single-value property deletion.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/src/store/collection-panel/collection-panel-action.ts b/src/store/collection-panel/collection-panel-action.ts
index 540b8c6a..122fc5e3 100644
--- a/src/store/collection-panel/collection-panel-action.ts
+++ b/src/store/collection-panel/collection-panel-action.ts
@@ -75,13 +75,23 @@ export const navigateToProcess = (uuid: string) =>
}
};
-export const deleteCollectionTag = (key: string) =>
+export const deleteCollectionTag = (key: string, value: string) =>
async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
const item = getState().collectionPanel.item;
const uuid = item ? item.uuid : '';
try {
if (item) {
- delete item.properties[key];
+ if (Array.isArray(item.properties[key])) {
+ item.properties[key] = item.properties[key].filter((v: string) => v !== value);
+ if (item.properties[key].length === 1) {
+ item.properties[key] = item.properties[key][0];
+ } else if (item.properties[key].length === 0) {
+ delete item.properties[key];
+ }
+ } else if (item.properties[key] === value) {
+ delete item.properties[key];
+ }
+
const updatedCollection = await services.collectionService.update(
uuid, {
properties: {...item.properties}
diff --git a/src/views/collection-panel/collection-panel.tsx b/src/views/collection-panel/collection-panel.tsx
index b92557f9..cc918808 100644
--- a/src/views/collection-panel/collection-panel.tsx
+++ b/src/views/collection-panel/collection-panel.tsx
@@ -128,10 +128,10 @@ export const CollectionPanel = withStyles(styles)(
</Grid>
<Grid item xs={12}>
{Object.keys(item.properties).map(k =>
- <PropertyChipComponent
- key={k} className={classes.tag}
- onDelete={this.handleDelete(k)}
- propKey={k} propValue={item.properties[k]} />
+ Array.isArray(item.properties[k])
+ ? item.properties[k].map((v: string) =>
+ getPropertyChip(k, v, this.handleDelete, classes.tag))
+ : getPropertyChip(k, item.properties[k], this.handleDelete, classes.tag)
)}
</Grid>
</Grid>
@@ -166,8 +166,8 @@ export const CollectionPanel = withStyles(styles)(
kind: SnackbarKind.SUCCESS
}))
- handleDelete = (key: string) => () => {
- this.props.dispatch<any>(deleteCollectionTag(key));
+ handleDelete = (key: string, value: string) => () => {
+ this.props.dispatch<any>(deleteCollectionTag(key, value));
}
openCollectionDetails = () => {
@@ -184,3 +184,10 @@ export const CollectionPanel = withStyles(styles)(
}
)
);
+
+const getPropertyChip = (k:string, v:string, handleDelete:any, className:string) =>
+ <PropertyChipComponent
+ key={k} className={className}
+ onDelete={handleDelete(k, v)}
+ propKey={k} propValue={v} />;
+
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list