Skip to content

Commit

Permalink
187690238 v3 DI Collection Requests (#1280)
Browse files Browse the repository at this point in the history
* Handle update collection requests.

* Handle delete collection requests.
  • Loading branch information
tealefristoe authored May 28, 2024
1 parent 2fd4642 commit 52c415b
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 9 deletions.
10 changes: 7 additions & 3 deletions v3/src/data-interactive/data-interactive-type-utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getSnapshot } from "mobx-state-tree"
import { IAttribute, IAttributeSnapshot } from "../models/data/attribute"
import { ICollectionModel, ICollectionPropsModel } from "../models/data/collection"
import { IDataSet } from "../models/data/data-set"
Expand Down Expand Up @@ -138,8 +139,9 @@ export function convertAttributeToV2FromResources(resources: DIResources) {
}

export function convertCollectionToV2(collection: ICollectionModel, dataContext?: IDataSet): ICodapV2CollectionV3 {
const { name, title, id } = collection
const { name, title, id, labels: _labels } = collection
const v2Id = toV2Id(id)
const labels = _labels ? getSnapshot(_labels) : undefined
const v2Attrs = collection.attributes.map(attribute => {
if (attribute) return convertAttributeToV2(attribute, dataContext)
})
Expand All @@ -154,7 +156,7 @@ export function convertCollectionToV2(collection: ICollectionModel, dataContext?
// collapseChildren,
guid: v2Id,
id: v2Id,
// labels: { singleCase, pluralCase }
labels,
name,
// parent,
title,
Expand All @@ -165,13 +167,15 @@ export function convertCollectionToV2(collection: ICollectionModel, dataContext?
export function convertUngroupedCollectionToV2(dataContext: IDataSet): ICodapV2CollectionV3 | undefined {
// TODO This will probably need to be reworked after upcoming v3 collection overhaul,
// so I'm leaving it bare bones for now.
const { name, title, id } = dataContext.ungrouped
const { name, title, id, labels: _labels } = dataContext.ungrouped
const v2Id = toV2Id(id)
const labels = _labels ? getSnapshot(_labels) : undefined
const ungroupedAttributes = dataContext.ungroupedAttributes
if (ungroupedAttributes.length > 0) {
return {
guid: v2Id,
id: v2Id,
labels,
name,
title,
attrs: ungroupedAttributes.map(attr => convertAttributeToV2(attr, dataContext)),
Expand Down
11 changes: 9 additions & 2 deletions v3/src/data-interactive/data-interactive-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { IDataSet } from "../models/data/data-set"
import { ICase } from "../models/data/data-set-types"
import { IGlobalValue } from "../models/global/global-value"
import { ITileModel } from "../models/tiles/tile-model"
import { ICollectionPropsModel } from "../models/data/collection"
import { ICollectionLabels, ICollectionPropsModel } from "../models/data/collection"
import { V2Component } from "./data-interactive-component-types"

export type DICaseValue = string | number | boolean | undefined
Expand Down Expand Up @@ -107,6 +107,13 @@ export interface DINewCase {
export interface DIUpdateCase {
values: DICaseValues
}
export interface DIDeleteCollectionResult {
collections?: number[]
}
export interface DIUpdateCollection {
title?: string
labels?: Partial<ICollectionLabels>
}
export interface DINotification {
request?: string
}
Expand Down Expand Up @@ -143,7 +150,7 @@ export type DIValues = DISingleValues | DISingleValues[] | number | string[]
export type DIResultAttributes = { attrs: ICodapV2AttributeV3[] }
export type DIResultSingleValues = DICase | DIComponentInfo | DIGetCaseResult | DIGlobal | DIInteractiveFrame
export type DIResultValues = DIResultSingleValues | DIResultSingleValues[] |
DIAllCases | DIResultAttributes | number
DIAllCases | DIDeleteCollectionResult | DIResultAttributes | number

export interface DIMetadata {
dirtyDocument?: boolean
Expand Down
31 changes: 30 additions & 1 deletion v3/src/data-interactive/handlers/collection-handler.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ICodapV2CollectionV3 } from "../../v2/codap-v2-types"
import { toV2Id, toV3CollectionId } from "../../utilities/codap-utils"
import { DICollection } from "../data-interactive-types"
import { DICollection, DIDeleteCollectionResult, DIValues } from "../data-interactive-types"
import { diCollectionHandler } from "./collection-handler"
import { setupTestDataset } from "./handler-test-utils"

Expand Down Expand Up @@ -62,18 +62,34 @@ describe("DataInteractive CollectionHandler", () => {
expect(dataset.collections[4].attributes[1]?.name).toBe("a7")
})

it("delete works", () => {
const { dataset: dataContext, c1: collection } = setupTestDataset()
expect(handler.delete?.({ dataContext }).success).toBe(false)
expect(handler.delete?.({ collection }).success).toBe(false)

const collectionId = collection.id
const result = handler.delete?.({ dataContext, collection })
expect(result?.success).toBe(true)
expect((result?.values as DIDeleteCollectionResult).collections?.[0]).toBe(toV2Id(collectionId))
expect(dataContext.attributes.length).toBe(2)
expect(dataContext.collections.length).toBe(1)
expect(dataContext.getCollection(collectionId)).toBeUndefined()
})

it("get works", () => {
const { dataset, c1 } = setupTestDataset()
expect(handler.get?.({}).success).toBe(false)
expect(handler.get?.({ dataContext: dataset }).success).toBe(false)

// Grouped collection
c1.setLabels({ singleCase: "singleCase" })
const groupedResult = handler.get?.({ dataContext: dataset, collection: c1 })
expect(groupedResult?.success).toBe(true)
const groupedValues = groupedResult?.values as ICodapV2CollectionV3
expect(groupedValues.name).toEqual(c1.name)
expect(groupedValues.id).toEqual(toV2Id(c1.id))
expect(groupedValues.attrs.length).toEqual(c1.attributes.length)
expect(groupedValues.labels?.singleCase).toBe("singleCase")

// Ungrouped collection
const ungrouped = dataset.ungrouped
Expand All @@ -84,4 +100,17 @@ describe("DataInteractive CollectionHandler", () => {
expect(ungroupedValues.id).toEqual(toV2Id(ungrouped.id))
expect(ungroupedValues.attrs.length).toEqual(dataset.ungroupedAttributes.length)
})

it("update works", () => {
const { dataset: dataContext, c1: collection } = setupTestDataset()
expect(handler.update?.({ dataContext }).success).toBe(false)
expect(handler.update?.({ collection }).success).toBe(false)
expect(handler.update?.({ dataContext, collection }).success).toBe(true)

expect(handler.update?.(
{ dataContext, collection }, { title: "newTitle", labels: { singleCase: "singleCase" } } as DIValues
).success).toBe(true)
expect(collection._title).toBe("newTitle")
expect(collection.labels?.singleCase).toBe("singleCase")
})
})
35 changes: 32 additions & 3 deletions v3/src/data-interactive/handlers/collection-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { getSharedCaseMetadataFromDataset } from "../../models/shared/shared-dat
import { toV2Id } from "../../utilities/codap-utils"
import { registerDIHandler } from "../data-interactive-handler"
import {
DIHandler, DIResources, diNotImplementedYet, DIValues, DICreateCollection, DICollection
DIHandler, DIResources, DIValues, DICreateCollection, DICollection, DIUpdateCollection
} from "../data-interactive-types"
import { convertCollectionToV2, convertUngroupedCollectionToV2 } from "../data-interactive-type-utils"
import { getCollection } from "../data-interactive-utils"
Expand Down Expand Up @@ -78,7 +78,21 @@ export const diCollectionHandler: DIHandler = {
return { success: true, values: returnValues }
},

delete: diNotImplementedYet,
delete(resources: DIResources) {
const { collection: _collection, dataContext } = resources
if (!dataContext) return dataContextNotFoundResult
if (!_collection) return collectionNotFoundResult
const collectionId = _collection.id
// For now, it's only possible to delete a grouped collection.
const collection = dataContext.getGroupedCollection(collectionId)
if (!collection) return collectionNotFoundResult

dataContext.applyModelChange(() => {
dataContext.removeCollectionWithAttributes(collection)
})

return { success: true, values: { collections: [toV2Id(collectionId)] } }
},

get(resources: DIResources) {
const { collection, dataContext } = resources
Expand All @@ -94,7 +108,22 @@ export const diCollectionHandler: DIHandler = {
}
},

update: diNotImplementedYet
update(resources: DIResources, values?: DIValues) {
const { collection, dataContext } = resources
if (!dataContext) return dataContextNotFoundResult
if (!collection) return collectionNotFoundResult

if (values) {
const { title, labels } = values as DIUpdateCollection

dataContext.applyModelChange(() => {
if (title) collection.setTitle(title)
if (labels) collection.setLabels(labels)
})
}

return { success: true }
}
}

registerDIHandler("collection", diCollectionHandler)
40 changes: 40 additions & 0 deletions v3/src/models/data/collection.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,46 @@ describe("CollectionModel", () => {
expect(isCollectionModel(withNameAndTitle)).toBe(false)
})

it("labels work as expected", () => {
const c1 = CollectionPropsModel.create({ name: "c1" })
expect(c1.labels).toBeUndefined()
c1.setSingleCase("singleCase")
expect(c1.labels?.singleCase).toBe("singleCase")
c1.setLabels({
pluralCase: "pluralCase",
singleCaseWithArticle: "singleCaseWithArticle",
setOfCases: "setOfCases",
setOfCasesWithArticle: "setOfCasesWithArticle"
})
expect(c1.labels?.singleCase).toBe("singleCase")
expect(c1.labels?.pluralCase).toBe("pluralCase")
expect(c1.labels?.singleCaseWithArticle).toBe("singleCaseWithArticle")
expect(c1.labels?.setOfCases).toBe("setOfCases")
expect(c1.labels?.setOfCasesWithArticle).toBe("setOfCasesWithArticle")

const c2 = CollectionPropsModel.create({ name: "c2" })
expect(c2.labels).toBeUndefined()
c2.setPluralCase("pluralCase")
expect(c2.labels?.pluralCase).toBe("pluralCase")
c2.setSingleCase("singleCase")
expect(c2.labels?.singleCase).toBe("singleCase")

const c3 = CollectionPropsModel.create({ name: "c3" })
expect(c3.labels).toBeUndefined()
c3.setSingleCaseWithArticle("singleCaseWithArticles")
expect(c3.labels?.singleCaseWithArticle).toBe("singleCaseWithArticles")

const c4 = CollectionPropsModel.create({ name: "c4" })
expect(c4.labels).toBeUndefined()
c4.setSetOfCases("setOfCases")
expect(c4.labels?.setOfCases).toBe("setOfCases")

const c5 = CollectionPropsModel.create({ name: "c5" })
expect(c5.labels).toBeUndefined()
c5.setSetOfCasesWithArticle("setOfCasesWithArticle")
expect(c5.labels?.setOfCasesWithArticle).toBe("setOfCasesWithArticle")
})

it("handles undefined references", () => {
const tree = Tree.create()
const collection = CollectionModel.create()
Expand Down
47 changes: 47 additions & 0 deletions v3/src/models/data/collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,58 @@ export const CollectionLabels = types.model("CollectionLabels", {
setOfCases: "",
setOfCasesWithArticle: ""
})
export interface ICollectionLabels extends Instance<typeof CollectionLabels> {}

export const CollectionPropsModel = V2Model.named("CollectionProps").props({
id: typeV3Id(kCollectionIdPrefix),
labels: types.maybe(CollectionLabels)
})
.actions(self => ({
setSingleCase(singleCase: string) {
if (self.labels) {
self.labels.singleCase = singleCase
} else {
self.labels = CollectionLabels.create({ singleCase })
}
},
setPluralCase(pluralCase: string) {
if (self.labels) {
self.labels.pluralCase = pluralCase
} else {
self.labels = CollectionLabels.create({ pluralCase })
}
},
setSingleCaseWithArticle(singleCaseWithArticle: string) {
if (self.labels) {
self.labels.singleCaseWithArticle = singleCaseWithArticle
} else {
self.labels = CollectionLabels.create({ singleCaseWithArticle })
}
},
setSetOfCases(setOfCases: string) {
if (self.labels) {
self.labels.setOfCases = setOfCases
} else {
self.labels = CollectionLabels.create({ setOfCases })
}
},
setSetOfCasesWithArticle(setOfCasesWithArticle: string) {
if (self.labels) {
self.labels.setOfCasesWithArticle = setOfCasesWithArticle
} else {
self.labels = CollectionLabels.create({ setOfCasesWithArticle })
}
}
}))
.actions(self => ({
setLabels(labels: Partial<ICollectionLabels>) {
if (labels.singleCase) self.setSingleCase(labels.singleCase)
if (labels.pluralCase) self.setPluralCase(labels.pluralCase)
if (labels.singleCaseWithArticle) self.setSingleCaseWithArticle(labels.singleCaseWithArticle)
if (labels.setOfCases) self.setSetOfCases(labels.setOfCases)
if (labels.setOfCasesWithArticle) self.setSetOfCasesWithArticle(labels.setOfCasesWithArticle)
}
}))
export interface ICollectionPropsModel extends Instance<typeof CollectionPropsModel> {}

export const CollectionModel = CollectionPropsModel
Expand Down
9 changes: 9 additions & 0 deletions v3/src/models/data/data-set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1140,6 +1140,15 @@ export const DataSet = V2Model.named("DataSet").props({
commitCache && this.commitCache()
self.clearCache()
}
},
removeCollectionWithAttributes(collection: ICollectionModel) {
collection.attributes.forEach(attribute => {
if (attribute) {
collection.removeAttribute(attribute.id)
self.removeAttribute(attribute.id)
}
})
self.removeCollection(collection)
}
}))
// performs the specified action so that response actions are included and undo/redo strings assigned
Expand Down

0 comments on commit 52c415b

Please sign in to comment.