handles single & multiple values for metadata columns (#5121)
handles single & multiple values for metadata columns Similar to `Hyperlink` and `Column` columns, `Metadata` column too is unrecognizable from GRAPH API response. Hence identifying from the field column names. `Metadata` fields are like tags. A `Metadata` fields can be configured to hold multiple values/tags **Original List with `Metadata` column (Department) with single value/tag**:  **Restored List with `Metadata` column with single value/tag**:  **Original List with `Metadata` column (Department) with multiple value/tag**:  **Restored List with `Metadata` column with multiple value/tag**:  #### Does this PR need a docs update or release note? - [ ] ✅ Yes, it's included - [ ] 🕐 Yes, but in a later PR - [x] ⛔ No #### Type of change <!--- Please check the type of change your PR introduces: ---> - [x] 🌻 Feature - [ ] 🐛 Bugfix - [ ] 🗺️ Documentation - [ ] 🤖 Supportability/Tests - [ ] 💻 CI/Deployment - [ ] 🧹 Tech Debt/Cleanup #### Issue(s) #5084 #5108 #### Test Plan <!-- How will this be tested prior to merging.--> - [x] 💪 Manual - [x] ⚡ Unit test - [x] 💚 E2E
This commit is contained in:
parent
08d4803ebe
commit
576c9f6b53
@ -62,6 +62,10 @@ const (
|
|||||||
|
|
||||||
PersonEmailKey = "Email"
|
PersonEmailKey = "Email"
|
||||||
|
|
||||||
|
MetadataLabelKey = "Label"
|
||||||
|
MetadataTermGUIDKey = "TermGuid"
|
||||||
|
MetadataWssIDKey = "WssId"
|
||||||
|
|
||||||
LinkTitleFieldNamePart = "LinkTitle"
|
LinkTitleFieldNamePart = "LinkTitle"
|
||||||
ChildCountFieldNamePart = "ChildCount"
|
ChildCountFieldNamePart = "ChildCount"
|
||||||
LookupIDFieldNamePart = "LookupId"
|
LookupIDFieldNamePart = "LookupId"
|
||||||
|
|||||||
@ -511,6 +511,10 @@ func retrieveFieldData(orig models.FieldValueSetable, columnNames map[string]*co
|
|||||||
additionalData[fieldName] = concatenatedHyperlink
|
additionalData[fieldName] = concatenatedHyperlink
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if metadataField, fieldName, ok := hasMetadataFields(additionalData); ok {
|
||||||
|
additionalData[fieldName] = concatenateMetadataFields(metadataField)
|
||||||
|
}
|
||||||
|
|
||||||
fields.SetAdditionalData(additionalData)
|
fields.SetAdditionalData(additionalData)
|
||||||
|
|
||||||
return fields
|
return fields
|
||||||
@ -647,6 +651,44 @@ func hasHyperLinkFields(additionalData map[string]any) (map[string]any, string,
|
|||||||
return nil, "", false
|
return nil, "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hasMetadataFields(additionalData map[string]any) ([]map[string]any, string, bool) {
|
||||||
|
for fieldName, value := range additionalData {
|
||||||
|
switch valType := reflect.TypeOf(value).Kind(); valType {
|
||||||
|
case reflect.Map:
|
||||||
|
metadataFields, areMetadataFields := getMetadataFields(value)
|
||||||
|
if areMetadataFields {
|
||||||
|
return []map[string]any{metadataFields}, fieldName, true
|
||||||
|
}
|
||||||
|
|
||||||
|
case reflect.Slice:
|
||||||
|
mmdfs := make([]map[string]any, 0)
|
||||||
|
|
||||||
|
multiMetadataFields, ok := value.([]any)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, mdfs := range multiMetadataFields {
|
||||||
|
metadataFields, areMetadataFields := getMetadataFields(mdfs)
|
||||||
|
if areMetadataFields {
|
||||||
|
mmdfs = append(mmdfs, metadataFields)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(mmdfs) > 0 {
|
||||||
|
return mmdfs, fieldName, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMetadataFields(metadataFieldvalue any) (map[string]any, bool) {
|
||||||
|
nestedFields, ok := metadataFieldvalue.(map[string]any)
|
||||||
|
return nestedFields, ok && keys.HasKeys(nestedFields, MetadataLabelKey, MetadataTermGUIDKey, MetadataWssIDKey)
|
||||||
|
}
|
||||||
|
|
||||||
func concatenateAddressFields(addressFields map[string]any) string {
|
func concatenateAddressFields(addressFields map[string]any) string {
|
||||||
parts := make([]string, 0)
|
parts := make([]string, 0)
|
||||||
|
|
||||||
@ -692,6 +734,23 @@ func concatenateHyperLinkFields(hyperlinkFields map[string]any) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func concatenateMetadataFields(metadataFieldsArr []map[string]any) string {
|
||||||
|
labels := make([]string, 0)
|
||||||
|
|
||||||
|
for _, md := range metadataFieldsArr {
|
||||||
|
mdVal, ok := md[MetadataLabelKey].(*string)
|
||||||
|
if ok {
|
||||||
|
labels = append(labels, ptr.Val(mdVal))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(labels) > 0 {
|
||||||
|
return strings.Join(labels, ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func addressKeyToVal(fields map[string]any, key string) string {
|
func addressKeyToVal(fields map[string]any, key string) string {
|
||||||
if v, err := str.AnyValueToString(key, fields); err == nil {
|
if v, err := str.AnyValueToString(key, fields); err == nil {
|
||||||
return v
|
return v
|
||||||
|
|||||||
@ -941,6 +941,161 @@ func (suite *ListsUnitSuite) TestSetAdditionalDataByColumnNames() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *ListsUnitSuite) TestHasMetadataFields() {
|
||||||
|
t := suite.T()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
additionalData map[string]any
|
||||||
|
expectedFields []map[string]any
|
||||||
|
expectedFieldName string
|
||||||
|
hasMetadataFields bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Single metadata fields, has all keys",
|
||||||
|
additionalData: map[string]any{
|
||||||
|
"MdCol": map[string]any{
|
||||||
|
MetadataLabelKey: ptr.To("Engineering"),
|
||||||
|
MetadataTermGUIDKey: ptr.To("6b5d3ce9-3043-499f-8be6-e92fb57bed96"),
|
||||||
|
MetadataWssIDKey: ptr.To(4),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedFields: []map[string]any{
|
||||||
|
{
|
||||||
|
MetadataLabelKey: ptr.To("Engineering"),
|
||||||
|
MetadataTermGUIDKey: ptr.To("6b5d3ce9-3043-499f-8be6-e92fb57bed96"),
|
||||||
|
MetadataWssIDKey: ptr.To(4),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedFieldName: "MdCol",
|
||||||
|
hasMetadataFields: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Multiple metadata fields, has all keys",
|
||||||
|
additionalData: map[string]any{
|
||||||
|
"MdCol": []any{
|
||||||
|
map[string]any{
|
||||||
|
MetadataLabelKey: ptr.To("Engineering"),
|
||||||
|
MetadataTermGUIDKey: ptr.To("6b5d3ce9-3043-499f-8be6-e92fb57bed96"),
|
||||||
|
MetadataWssIDKey: ptr.To(4),
|
||||||
|
},
|
||||||
|
map[string]any{
|
||||||
|
MetadataLabelKey: ptr.To("Marketing"),
|
||||||
|
MetadataTermGUIDKey: ptr.To("312347ce-3043-499f-8be6-e92fb57bed96"),
|
||||||
|
MetadataWssIDKey: ptr.To(2),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedFields: []map[string]any{
|
||||||
|
{
|
||||||
|
MetadataLabelKey: ptr.To("Engineering"),
|
||||||
|
MetadataTermGUIDKey: ptr.To("6b5d3ce9-3043-499f-8be6-e92fb57bed96"),
|
||||||
|
MetadataWssIDKey: ptr.To(4),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MetadataLabelKey: ptr.To("Marketing"),
|
||||||
|
MetadataTermGUIDKey: ptr.To("312347ce-3043-499f-8be6-e92fb57bed96"),
|
||||||
|
MetadataWssIDKey: ptr.To(2),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedFieldName: "MdCol",
|
||||||
|
hasMetadataFields: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Single metadata fields, missing few keys",
|
||||||
|
additionalData: map[string]any{
|
||||||
|
"MdCol": map[string]any{
|
||||||
|
MetadataLabelKey: ptr.To("Engineering"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedFields: nil,
|
||||||
|
expectedFieldName: "",
|
||||||
|
hasMetadataFields: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Multiple metadata fields, missing few keys",
|
||||||
|
additionalData: map[string]any{
|
||||||
|
"MdCol": []any{
|
||||||
|
map[string]any{
|
||||||
|
MetadataLabelKey: ptr.To("Engineering"),
|
||||||
|
MetadataTermGUIDKey: ptr.To("6b5d3ce9-3043-499f-8be6-e92fb57bed96"),
|
||||||
|
MetadataWssIDKey: ptr.To(4),
|
||||||
|
},
|
||||||
|
map[string]any{
|
||||||
|
MetadataLabelKey: ptr.To("Marketing"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedFields: []map[string]any{
|
||||||
|
{
|
||||||
|
MetadataLabelKey: ptr.To("Engineering"),
|
||||||
|
MetadataTermGUIDKey: ptr.To("6b5d3ce9-3043-499f-8be6-e92fb57bed96"),
|
||||||
|
MetadataWssIDKey: ptr.To(4),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedFieldName: "MdCol",
|
||||||
|
hasMetadataFields: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
suite.Run(test.name, func() {
|
||||||
|
nestedFields, fName, isMetadata := hasMetadataFields(test.additionalData)
|
||||||
|
assert.Equal(t, test.expectedFields, nestedFields)
|
||||||
|
assert.Equal(t, test.expectedFieldName, fName)
|
||||||
|
assert.Equal(t, test.hasMetadataFields, isMetadata)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *ListsUnitSuite) TestConcatenateMetadataFields() {
|
||||||
|
t := suite.T()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
metadataFields []map[string]any
|
||||||
|
expectedFieldName string
|
||||||
|
expectedResult string
|
||||||
|
hasMetadataFields bool
|
||||||
|
columnNames map[string]any
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Single metadata fields",
|
||||||
|
metadataFields: []map[string]any{
|
||||||
|
{
|
||||||
|
MetadataLabelKey: ptr.To("Engineering"),
|
||||||
|
MetadataTermGUIDKey: ptr.To("6b5d3ce9-3043-499f-8be6-e92fb57bed96"),
|
||||||
|
MetadataWssIDKey: ptr.To(4),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedResult: "Engineering",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Multiple metadata fields",
|
||||||
|
metadataFields: []map[string]any{
|
||||||
|
{
|
||||||
|
MetadataLabelKey: ptr.To("Engineering"),
|
||||||
|
MetadataTermGUIDKey: ptr.To("6b5d3ce9-3043-499f-8be6-e92fb57bed96"),
|
||||||
|
MetadataWssIDKey: ptr.To(4),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MetadataLabelKey: ptr.To("Marketing"),
|
||||||
|
MetadataTermGUIDKey: ptr.To("312347ce-3043-499f-8be6-e92fb57bed96"),
|
||||||
|
MetadataWssIDKey: ptr.To(2),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedResult: "Engineering,Marketing",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
suite.Run(test.name, func() {
|
||||||
|
res := concatenateMetadataFields(test.metadataFields)
|
||||||
|
assert.Equal(t, test.expectedResult, res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (suite *ListsUnitSuite) TestCheckFields() {
|
func (suite *ListsUnitSuite) TestCheckFields() {
|
||||||
t := suite.T()
|
t := suite.T()
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user