Skip to content

Commit 0d72158

Browse files
feat(elements): pos-container-contents reactively updates contents
1 parent 0bdfc4d commit 0d72158

File tree

2 files changed

+112
-43
lines changed

2 files changed

+112
-43
lines changed

elements/src/components/pos-container-contents/pos-container-contents.spec.tsx

Lines changed: 100 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,24 @@ import { PosContainerContents } from './pos-container-contents';
88
import { Components, LdpContainer } from '../../components';
99
import PosCreateNewContainerItem = Components.PosCreateNewContainerItem;
1010
import { pressKey } from '../../test/pressKey';
11+
import { Subject } from 'rxjs';
12+
import { ContainerContent, Thing } from '@pod-os/core';
1113

1214
describe('pos-container-contents', () => {
15+
let container: LdpContainer, observed$: Subject<ContainerContent[]>, resource: Thing;
16+
beforeEach(() => {
17+
// Given a container
18+
observed$ = new Subject<ContainerContent[]>();
19+
container = {
20+
observeContains: () => observed$,
21+
} as unknown as LdpContainer;
22+
23+
// available as a resource
24+
resource = {
25+
assume: () => container,
26+
} as unknown as Thing;
27+
});
28+
1329
it('are empty initially', async () => {
1430
const page = await newSpecPage({
1531
components: [PosContainerContents],
@@ -28,16 +44,13 @@ describe('pos-container-contents', () => {
2844
html: `<pos-container-contents />`,
2945
supportsShadowDom: false,
3046
});
31-
await page.rootInstance.receiveResource({
32-
assume: () => ({
33-
contains: () => [
34-
{
35-
uri: 'https://pod.test/container/file',
36-
name: 'file',
37-
},
38-
],
39-
}),
40-
});
47+
await page.rootInstance.receiveResource(resource);
48+
observed$.next([
49+
{
50+
uri: 'https://pod.test/container/file',
51+
name: 'file',
52+
},
53+
]);
4154
await page.waitForChanges();
4255

4356
expect(page.root).toEqualHtml(`
@@ -60,11 +73,8 @@ describe('pos-container-contents', () => {
6073
components: [PosContainerContents],
6174
html: `<pos-container-contents />`,
6275
});
63-
await page.rootInstance.receiveResource({
64-
assume: () => ({
65-
contains: () => [],
66-
}),
67-
});
76+
await page.rootInstance.receiveResource(resource);
77+
observed$.next([]);
6878
await page.waitForChanges();
6979

7080
expect(page.root).toEqualHtml(`<pos-container-contents>
@@ -84,24 +94,21 @@ describe('pos-container-contents', () => {
8494
html: `<pos-container-contents />`,
8595
supportsShadowDom: false,
8696
});
87-
await page.rootInstance.receiveResource({
88-
assume: () => ({
89-
contains: () => [
90-
{
91-
uri: 'https://pod.test/container/file',
92-
name: 'file',
93-
},
94-
{
95-
uri: 'https://pod.test/container/subdir/',
96-
name: 'subdir',
97-
},
98-
{
99-
uri: 'https://pod.test/container/a-file-on-top-of-the-list',
100-
name: 'a-file-on-top-of-the-list',
101-
},
102-
],
103-
}),
104-
});
97+
await page.rootInstance.receiveResource(resource);
98+
observed$.next([
99+
{
100+
uri: 'https://pod.test/container/file',
101+
name: 'file',
102+
},
103+
{
104+
uri: 'https://pod.test/container/subdir/',
105+
name: 'subdir',
106+
},
107+
{
108+
uri: 'https://pod.test/container/a-file-on-top-of-the-list',
109+
name: 'a-file-on-top-of-the-list',
110+
},
111+
]);
105112
await page.waitForChanges();
106113

107114
expect(page.root).toEqualHtml(`
@@ -134,24 +141,75 @@ describe('pos-container-contents', () => {
134141
`);
135142
});
136143

144+
it('re-renders when container contents in store change', async () => {
145+
const page = await newSpecPage({
146+
components: [PosContainerContents],
147+
html: `<pos-container-contents />`,
148+
supportsShadowDom: false,
149+
});
150+
151+
await page.rootInstance.receiveResource(resource);
152+
153+
observed$.next([
154+
{
155+
uri: 'https://pod.test/container/file',
156+
name: 'file',
157+
},
158+
]);
159+
await page.waitForChanges();
160+
161+
expect(page.root).toEqualHtml(`
162+
<pos-container-contents>
163+
<pos-container-toolbar></pos-container-toolbar>
164+
<ul aria-label="Container contents">
165+
<li>
166+
<pos-resource lazy="" uri="https://pod.test/container/file">
167+
<pos-container-item>
168+
file
169+
</pos-container-item>
170+
</pos-resource>
171+
</li>
172+
</ul>
173+
</pos-container-contents>`);
174+
175+
observed$.next([
176+
{
177+
uri: 'https://pod.test/container/file-1',
178+
name: 'file-1',
179+
},
180+
]);
181+
await page.waitForChanges();
182+
183+
expect(page.root).toEqualHtml(`
184+
<pos-container-contents>
185+
<pos-container-toolbar></pos-container-toolbar>
186+
<ul aria-label="Container contents">
187+
<li>
188+
<pos-resource lazy="" uri="https://pod.test/container/file-1">
189+
<pos-container-item>
190+
file-1
191+
</pos-container-item>
192+
</pos-resource>
193+
</li>
194+
</ul>
195+
</pos-container-contents>`);
196+
});
197+
137198
describe('new files and folders', () => {
138-
let page;
139-
let container: LdpContainer;
199+
let page: any;
140200
beforeEach(async () => {
141-
// Given a page with container contents
201+
// and given a page with container contents
142202
page = await newSpecPage({
143203
components: [PosContainerContents],
144204
html: `<pos-container-contents />`,
145205
supportsShadowDom: false,
146206
});
147207

148208
// and a container resource is available
149-
container = {
150-
contains: () => [],
151-
} as LdpContainer;
152-
await page.rootInstance.receiveResource({
153-
assume: () => container,
154-
});
209+
await page.rootInstance.receiveResource(resource);
210+
211+
// as well as (empty) container contents
212+
observed$.next([]);
155213
await page.waitForChanges();
156214
});
157215

elements/src/components/pos-container-contents/pos-container-contents.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ContainerContent, LdpContainer, Thing } from '@pod-os/core';
22
import { Component, Event, EventEmitter, h, Host, Listen, State } from '@stencil/core';
33
import { ResourceAware, subscribeResource } from '../events/ResourceAware';
4+
import { Subject, takeUntil } from 'rxjs';
45

56
@Component({
67
tag: 'pos-container-contents',
@@ -21,6 +22,8 @@ export class PosContainerContents implements ResourceAware {
2122
@State()
2223
private createNewItem: 'file' | 'folder' | null = null;
2324

25+
private readonly disconnected$ = new Subject<void>();
26+
2427
onCreateNewFile() {
2528
this.createNewItem = 'file';
2629
}
@@ -43,7 +46,10 @@ export class PosContainerContents implements ResourceAware {
4346
receiveResource = (resource: Thing) => {
4447
this.container = resource.assume(LdpContainer);
4548
this.loading = false;
46-
this.contents = this.container.contains().sort((a, b) => a.name.localeCompare(b.name));
49+
this.container
50+
.observeContains()
51+
.pipe(takeUntil(this.disconnected$))
52+
.subscribe(contains => (this.contents = contains.sort((a, b) => a.name.localeCompare(b.name))));
4753
};
4854

4955
render() {
@@ -75,4 +81,9 @@ export class PosContainerContents implements ResourceAware {
7581
</Host>
7682
);
7783
}
84+
85+
disconnectedCallback() {
86+
this.disconnected$.next();
87+
this.disconnected$.unsubscribe();
88+
}
7889
}

0 commit comments

Comments
 (0)