Skip to content

Commit f00ba9c

Browse files
committed
Make ReadonlyDocument expandable
1 parent 05a557b commit f00ba9c

File tree

1 file changed

+80
-2
lines changed

1 file changed

+80
-2
lines changed

packages/compass-crud/src/components/readonly-document.tsx

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type Document from 'hadron-document';
55
import type { TypeCastMap } from 'hadron-type-checker';
66
import { withPreferences } from 'compass-preferences-model/provider';
77
import { getInsightsForDocument } from '../utils';
8+
import { DocumentEvents } from 'hadron-document';
89
type BSONObject = TypeCastMap['Object'];
910

1011
export const documentStyles = css({
@@ -30,10 +31,73 @@ export type ReadonlyDocumentProps = {
3031
showInsights?: boolean;
3132
};
3233

34+
type ReadonlyDocumentState = {
35+
expanded: boolean;
36+
};
37+
3338
/**
3439
* Component for a single readonly document in a list of documents.
3540
*/
36-
class ReadonlyDocument extends React.Component<ReadonlyDocumentProps> {
41+
class ReadonlyDocument extends React.Component<
42+
ReadonlyDocumentProps,
43+
ReadonlyDocumentState
44+
> {
45+
constructor(props: ReadonlyDocumentProps) {
46+
super(props);
47+
this.state = {
48+
expanded: props.doc.expanded,
49+
};
50+
}
51+
52+
/**
53+
* Subscribe to the update store on mount.
54+
*/
55+
componentDidMount() {
56+
this.subscribeToDocumentEvents(this.props.doc);
57+
}
58+
59+
/**
60+
* Refreshing the list updates the doc in the props so we should update the
61+
* document on the instance.
62+
*/
63+
componentDidUpdate(prevProps: ReadonlyDocumentProps) {
64+
if (prevProps.doc !== this.props.doc) {
65+
this.unsubscribeFromDocumentEvents(prevProps.doc);
66+
this.subscribeToDocumentEvents(this.props.doc);
67+
}
68+
}
69+
70+
/**
71+
* Unsubscribe from the update store on unmount.
72+
*/
73+
componentWillUnmount() {
74+
this.unsubscribeFromDocumentEvents(this.props.doc);
75+
}
76+
77+
/**
78+
* Subscribe to the document events.
79+
*/
80+
subscribeToDocumentEvents(doc: Document) {
81+
doc.on(DocumentEvents.Expanded, this.handleExpanded);
82+
doc.on(DocumentEvents.Collapsed, this.handleCollapsed);
83+
}
84+
85+
/**
86+
* Unsubscribe from the document events.
87+
*/
88+
unsubscribeFromDocumentEvents(doc: Document) {
89+
doc.on(DocumentEvents.Expanded, this.handleExpanded);
90+
doc.on(DocumentEvents.Collapsed, this.handleCollapsed);
91+
}
92+
93+
handleExpanded = () => {
94+
this.setState({ expanded: true });
95+
};
96+
97+
handleCollapsed = () => {
98+
this.setState({ expanded: false });
99+
};
100+
37101
handleClone = () => {
38102
const clonedDoc = this.props.doc.generateObject({
39103
excludeInternalFields: true,
@@ -48,6 +112,19 @@ class ReadonlyDocument extends React.Component<ReadonlyDocumentProps> {
48112
this.props.copyToClipboard?.(this.props.doc);
49113
};
50114

115+
/**
116+
* Handle clicking the expand all button.
117+
*/
118+
handleExpandAll = () => {
119+
const { doc } = this.props;
120+
// Update the doc directly - the components internal state will update via events
121+
if (doc.expanded) {
122+
doc.collapse();
123+
} else {
124+
doc.expand();
125+
}
126+
};
127+
51128
/**
52129
* Get the elements for the document.
53130
*
@@ -64,6 +141,8 @@ class ReadonlyDocument extends React.Component<ReadonlyDocumentProps> {
64141
onClone={
65142
this.props.openInsertDocumentDialog ? this.handleClone : undefined
66143
}
144+
onExpand={this.handleExpandAll}
145+
expanded={this.state.expanded}
67146
insights={
68147
this.props.showInsights
69148
? getInsightsForDocument(this.props.doc)
@@ -94,7 +173,6 @@ class ReadonlyDocument extends React.Component<ReadonlyDocumentProps> {
94173
static propTypes = {
95174
copyToClipboard: PropTypes.func,
96175
doc: PropTypes.object.isRequired,
97-
expandAll: PropTypes.bool,
98176
openInsertDocumentDialog: PropTypes.func,
99177
showInsights: PropTypes.bool,
100178
};

0 commit comments

Comments
 (0)