Skip to content
This repository has been archived by the owner on Oct 23, 2023. It is now read-only.

Commit

Permalink
fix: add element contents for unoccupied pattern slots
Browse files Browse the repository at this point in the history
Adresses a bug where adding a pattern slot to a pattern with
callsites would not update the appropriate elements inside Alva.

Steps to reproduce

1. Create new file
2. Connect DesignKit
3. Add element with Button pattern
4. Remove children prop from Button interface
5. Update the library inside Alva
6. Readd children prop to Button interface
7. Update the library inside Alva again
7a) Before fix: The button still does not accept children
7b) After fix: The button accepts children a
  • Loading branch information
marionebl authored and faselbaum committed Sep 14, 2018
1 parent f2f6c3c commit c487b5d
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 19 deletions.
14 changes: 14 additions & 0 deletions src/model/element/element-content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,20 @@ export class ElementContent {
);
}

public static fromSlot(slot: PatternSlot, context: ElementContentContext): ElementContent {
return new ElementContent(
{
elementIds: [],
forcedOpen: false,
highlighted: false,
id: uuid.v4(),
open: false,
slotId: slot.getId()
},
context
);
}

public accepts(child: Element): boolean {
const parentElementId = this.getParentElementId();

Expand Down
9 changes: 7 additions & 2 deletions src/model/element/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,11 @@ export class Element {
});
}

@Mobx.action
public addContent(content: ElementContent): void {
this.contentIds.push(content.getId());
}

@Mobx.action
public clone(opts?: { withState: boolean }): Element {
const withState = Boolean(opts && opts.withState);
Expand Down Expand Up @@ -259,7 +264,7 @@ export class Element {
return clones;
}, new Map());

const clonedContents = this.contentIds
const clonedContents = [...this.contentIds]
.map(contentId => this.project.getElementContentById(contentId))
.filter((content): content is ElementContent => typeof content !== 'undefined')
.map(content => content.clone({ withState }));
Expand Down Expand Up @@ -415,7 +420,7 @@ export class Element {
}

public getContents(): ElementContent[] {
return this.contentIds
return [...this.contentIds]
.map(contentId => this.project.getElementContentById(contentId))
.filter(
(elementContent): elementContent is ElementContent =>
Expand Down
26 changes: 25 additions & 1 deletion src/model/pattern-library/pattern-library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Box, Conditional, Image, Link, Page, Text } from './builtins';
import { isEqual } from 'lodash';
import * as Mobx from 'mobx';
import { Pattern, PatternSlot } from '../pattern';
import { ElementContent } from '../element';
import { AnyPatternProperty, PatternEnumProperty, PatternProperty } from '../pattern-property';
import { Project } from '../project';
import * as Types from '../../types';
Expand Down Expand Up @@ -139,10 +140,13 @@ export class PatternLibrary {
@Mobx.action
public import(analysis: Types.LibraryAnalysis, { project }: { project: Project }): void {
const patternsBefore = this.getPatterns();
const patternsAfter = analysis.patterns.map(item =>
Pattern.from(item.pattern, { patternLibrary: this })
);

const patternChanges = computeDifference({
before: patternsBefore,
after: analysis.patterns.map(item => Pattern.from(item.pattern, { patternLibrary: this }))
after: patternsAfter
});

patternChanges.removed.map(change => {
Expand Down Expand Up @@ -192,6 +196,26 @@ export class PatternLibrary {

propChanges.changed.map(change => change.before.update(change.after));

// TODO: This might be solved via a bigger refactoring that
// computes available element contents from pattern slots directly
patternsAfter.forEach(pattern => {
project.getElementsByPattern(pattern).forEach(element => {
const contents = element.getContents();

pattern
.getSlots()
// Check if there is a corresponding element content for each pattern slot
.filter(slot => !contents.some(content => content.getSlot() === slot))
.forEach(slot => {
// No element content, create a new one and add it to element
const content = ElementContent.fromSlot(slot, { project });
content.setParentElement(element);
element.addContent(content);
project.addElementContent(content);
});
});
});

this.setState(Types.PatternLibraryState.Connected);

this.setBundle(analysis.bundle);
Expand Down
4 changes: 2 additions & 2 deletions src/model/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -831,11 +831,11 @@ export class Project {
const removed = message.payload.change.removed;
const member = mayBeMember as unknown[];

if (removed.length > 0) {
if (Array.isArray(member) && removed.length > 0) {
member.splice(message.payload.change.index, removed.length);
}

if (added.length > 0) {
if (Array.isArray(member) && added.length > 0) {
member.splice(message.payload.change.index, 0, ...added);
}
});
Expand Down
17 changes: 3 additions & 14 deletions src/store/view-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,20 +175,9 @@ export class ViewStore {
public createElement(init: { dragged?: boolean; pattern: Model.Pattern }): Model.Element {
const project = this.getProject();

const elementContents = init.pattern.getSlots().map(
slot =>
new Model.ElementContent(
{
elementIds: [],
forcedOpen: false,
highlighted: false,
id: uuid.v4(),
open: false,
slotId: slot.getId()
},
{ project }
)
);
const elementContents = init.pattern
.getSlots()
.map(slot => Model.ElementContent.fromSlot(slot, { project }));

const element = new Model.Element(
{
Expand Down

0 comments on commit c487b5d

Please sign in to comment.