Skip to content

Commit 94a0be9

Browse files
committed
Merged branch develop into master
2 parents 95fd790 + 9c6cb34 commit 94a0be9

File tree

8 files changed

+153
-43
lines changed

8 files changed

+153
-43
lines changed

README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,21 @@ Delta data structure :
117117
### readOnly
118118
| Key | Description | Type | Required | Default |
119119
|:--------:|:--------------------------------:|:-------:|:---------:|:---------:|
120-
| readOnly | Read only boolean for all object | Boolean | False | false |
120+
| readOnly | Read only boolean for all object when a boolean is provided,
121+
read only for specific keys when function is provided | Boolean | Function | False | `(keyName, data, keyPath, deep, dataType) => false` |
122+
123+
This function must return a boolean.
124+
125+
Function parameters :
126+
127+
| Key | Description | Type | Example |
128+
|:-----------:|:-------------------------------:|:-------:|:---------------------------------------------------------------:|
129+
| keyName | Key name of current node/value | String | 'object' for data: { object: { string: 'test' } } |
130+
| data | data of current node/value | Any | { string: 'test' } for data: { object: { string: 'test' } } |
131+
| keyPath | key path | Array | ['object'] for data: { object: { string: 'test' } } |
132+
| deep | Deep of current node | Number | 1 for data: { object: { string: 'test' } } on 'object' node |
133+
| dataType | data type of current node/value | String | 'Object', 'Array', 'Null', 'Undefined', 'Error', 'Number', ... |
134+
121135

122136
### getStyle
123137
| Key | Description | Type | Required | Default |

dev/components/Body.jsx

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,12 @@ class Body extends Component {
5454
deltaUpdateString: '{}',
5555
globalUpdateString: '{}',
5656
textareaRef: null,
57+
readOnlyBooleanRef: null,
58+
readOnlyFunctionRef: null,
5759
readOnlyRef: null,
60+
readOnlyEnable: false,
61+
readOnlyFunctionEnable: false,
62+
readOnlyBooleanEnable: false,
5863
readOnly: false,
5964
customInputRef: null,
6065
customInput: false,
@@ -66,8 +71,12 @@ class Body extends Component {
6671
this.onDeltaUpdate = this.onDeltaUpdate.bind(this);
6772
this.refTextarea = this.refTextarea.bind(this);
6873
this.refReadOnlyCheckbox = this.refReadOnlyCheckbox.bind(this);
74+
this.refReadOnlyFunctionCheckbox = this.refReadOnlyFunctionCheckbox.bind(this);
75+
this.refReadOnlyBooleanCheckbox = this.refReadOnlyBooleanCheckbox.bind(this);
6976
this.handleSubmit = this.handleSubmit.bind(this);
7077
this.handleResetToDefault = this.handleResetToDefault.bind(this);
78+
this.handleChangeReadOnlyBoolean = this.handleChangeReadOnlyBoolean.bind(this);
79+
this.handleChangeReadOnlyFunction = this.handleChangeReadOnlyFunction.bind(this);
7180
this.handleChangeReadOnly = this.handleChangeReadOnly.bind(this);
7281
this.handleClearGlobalUpdateString = this.handleClearGlobalUpdateString.bind(this);
7382
this.handleClearDeltaUpdateString = this.handleClearDeltaUpdateString.bind(this);
@@ -93,6 +102,16 @@ class Body extends Component {
93102
this.state.textareaRef = node;
94103
}
95104

105+
refReadOnlyFunctionCheckbox(node) {
106+
this.state.readOnlyFunctionRef = node;
107+
this.state.readOnlyFunctionRef.disabled = true;
108+
}
109+
110+
refReadOnlyBooleanCheckbox(node) {
111+
this.state.readOnlyBooleanRef = node;
112+
this.state.readOnlyBooleanRef.disabled = true;
113+
}
114+
96115
refReadOnlyCheckbox(node) {
97116
this.state.readOnlyRef = node;
98117
}
@@ -146,10 +165,53 @@ class Body extends Component {
146165
}
147166

148167
handleChangeReadOnly() {
149-
const { readOnlyRef } = this.state;
168+
const { readOnlyRef, readOnlyBooleanRef, readOnlyFunctionRef } = this.state;
169+
170+
this.setState({
171+
readOnlyEnable: readOnlyRef.checked,
172+
});
173+
174+
if (readOnlyRef.checked) {
175+
readOnlyBooleanRef.disabled = false;
176+
readOnlyFunctionRef.disabled = false;
177+
if (readOnlyBooleanRef.checked) {
178+
this.handleChangeReadOnlyBoolean();
179+
} else if (readOnlyFunctionRef.checked) {
180+
this.handleChangeReadOnlyFunction();
181+
}
182+
} else {
183+
readOnlyBooleanRef.disabled = true;
184+
readOnlyFunctionRef.disabled = true;
185+
this.setState({
186+
readOnly: false,
187+
});
188+
}
189+
}
190+
191+
handleChangeReadOnlyBoolean() {
192+
const { readOnlyBooleanRef, readOnlyFunctionRef } = this.state;
193+
194+
readOnlyFunctionRef.disabled = readOnlyBooleanRef.checked;
195+
196+
this.setState({
197+
readOnly: readOnlyBooleanRef.checked,
198+
});
199+
}
200+
201+
handleChangeReadOnlyFunction() {
202+
const { readOnlyFunctionRef, readOnlyBooleanRef } = this.state;
203+
204+
readOnlyBooleanRef.disabled = readOnlyFunctionRef.checked;
205+
206+
let result = null;
207+
if (readOnlyFunctionRef.checked) {
208+
result = (name, value, keyPath) => (keyPath[keyPath.length - 1] === 'text');
209+
} else {
210+
result = () => false;
211+
}
150212

151213
this.setState({
152-
readOnly: readOnlyRef.checked,
214+
readOnly: result,
153215
});
154216
}
155217

@@ -200,6 +262,20 @@ class Body extends Component {
200262
onChange={this.handleChangeReadOnly}
201263
/>Read Only
202264
</span>
265+
<span>
266+
<input
267+
type="checkbox"
268+
ref={this.refReadOnlyBooleanCheckbox}
269+
onChange={this.handleChangeReadOnlyBoolean}
270+
/>Read Only Boolean
271+
</span>
272+
<span>
273+
<input
274+
type="checkbox"
275+
ref={this.refReadOnlyFunctionCheckbox}
276+
onChange={this.handleChangeReadOnlyFunction}
277+
/>Read Only Function (read only for all 'text' key)
278+
</span>
203279
<span>
204280
<input
205281
type="checkbox"

src/JsonTree.js

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ const propTypes = {
2222
isCollapsed: PropTypes.func,
2323
onFullyUpdate: PropTypes.func,
2424
onDeltaUpdate: PropTypes.func,
25-
readOnly: PropTypes.bool,
25+
readOnly: PropTypes.oneOfType([
26+
PropTypes.bool,
27+
PropTypes.func,
28+
]),
2629
getStyle: PropTypes.func,
2730
addButtonElement: PropTypes.element,
2831
cancelButtonElement: PropTypes.element,
@@ -39,11 +42,6 @@ const propTypes = {
3942
const defaultProps = {
4043
rootName: 'root',
4144
isCollapsed: (keyPath, deep) => (deep !== 0),
42-
onFullyUpdate: () => {
43-
},
44-
onDeltaUpdate: () => {
45-
},
46-
readOnly: false,
4745
getStyle: (keyName, data, keyPath, deep, dataType) => {
4846
switch (dataType) {
4947
case 'Object':
@@ -56,10 +54,15 @@ const defaultProps = {
5654
}
5755
},
5856
/* eslint-disable no-unused-vars */
57+
readOnly: (keyName, data, keyPath, deep, dataType) => false,
58+
onFullyUpdate: (data) => {
59+
},
60+
onDeltaUpdate: (type, keyPath, deep, key, newValue, oldValue) => {
61+
},
5962
beforeRemoveAction: (key, keyPath, deep, oldValue) => new Promise(resolve => resolve()),
6063
beforeAddAction: (key, keyPath, deep, newValue) => new Promise(resolve => resolve()),
6164
beforeUpdateAction: (key, keyPath, deep, oldValue, newValue) => new Promise(resolve => resolve()),
62-
/* esling-enable */
65+
/* eslint-enable */
6366
};
6467

6568
/* ************************************* */
@@ -114,6 +117,11 @@ class JsonTree extends Component {
114117
// Node type
115118
const dataType = getObjectType(data);
116119
let node = null;
120+
let readOnlyFunction = readOnly;
121+
if (getObjectType(readOnly) === 'Boolean') {
122+
readOnlyFunction = () => (readOnly);
123+
}
124+
117125
if (dataType === 'Object' || dataType === 'Array') {
118126
node = (<JsonNode
119127
data={data}
@@ -123,7 +131,7 @@ class JsonTree extends Component {
123131
isCollapsed={isCollapsed}
124132
onUpdate={this.onUpdate}
125133
onDeltaUpdate={onDeltaUpdate}
126-
readOnly={readOnly}
134+
readOnly={readOnlyFunction}
127135
getStyle={getStyle}
128136
addButtonElement={addButtonElement}
129137
cancelButtonElement={cancelButtonElement}

src/components/JsonArray.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const propTypes = {
2525
handleRemove: PropTypes.func,
2626
onUpdate: PropTypes.func.isRequired,
2727
onDeltaUpdate: PropTypes.func.isRequired,
28-
readOnly: PropTypes.bool.isRequired,
28+
readOnly: PropTypes.func.isRequired,
2929
dataType: PropTypes.string,
3030
getStyle: PropTypes.func.isRequired,
3131
addButtonElement: PropTypes.element,
@@ -216,7 +216,7 @@ class JsonArray extends Component {
216216
const numberOfItems = data.length;
217217
let minusElement = null;
218218
// Check if readOnly is activated
219-
if (!readOnly) {
219+
if (!readOnly(name, data, keyPath, deep, dataType)) {
220220
const minusMenuLayout = React.cloneElement(minusMenuElement, {
221221
onClick: handleRemove,
222222
className: 'rejt-minus-menu',
@@ -260,8 +260,9 @@ class JsonArray extends Component {
260260
const { minus, plus, delimiter, ul, addForm } = getStyle(name, data, keyPath, deep, dataType);
261261

262262
let minusElement = null;
263+
const readOnlyResult = readOnly(name, data, keyPath, deep, dataType);
263264
// Check if readOnly is activated
264-
if (!readOnly) {
265+
if (!readOnlyResult) {
265266
const minusMenuLayout = React.cloneElement(minusMenuElement, {
266267
onClick: handleRemove,
267268
className: 'rejt-minus-menu',
@@ -299,7 +300,7 @@ class JsonArray extends Component {
299300
const onlyValue = true;
300301
let menu = null;
301302
// Check if readOnly is activated
302-
if (!readOnly) {
303+
if (!readOnlyResult) {
303304
const plusMenuLayout = React.cloneElement(plusMenuElement, {
304305
onClick: this.handleAddMode,
305306
className: 'rejt-plus-menu',

src/components/JsonFunctionValue.js

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const propTypes = {
2323
deep: PropTypes.number,
2424
handleRemove: PropTypes.func,
2525
handleUpdateValue: PropTypes.func,
26-
readOnly: PropTypes.bool.isRequired,
26+
readOnly: PropTypes.func.isRequired,
2727
dataType: PropTypes.string,
2828
getStyle: PropTypes.func.isRequired,
2929
editButtonElement: PropTypes.element,
@@ -46,7 +46,7 @@ const defaultProps = {
4646
/* ************************************* */
4747
/* ******** COMPONENT ******** */
4848
/* ************************************* */
49-
class JsonValue extends Component {
49+
class JsonFunctionValue extends Component {
5050
constructor(props) {
5151
super(props);
5252
const keyPath = [
@@ -76,10 +76,11 @@ class JsonValue extends Component {
7676
}
7777

7878
componentDidUpdate() {
79-
const { editEnabled, inputRef } = this.state;
80-
const { readOnly } = this.props;
79+
const { editEnabled, inputRef, name, value, keyPath, deep } = this.state;
80+
const { readOnly, dataType } = this.props;
81+
const readOnlyResult = readOnly(name, value, keyPath, deep, dataType);
8182

82-
if (editEnabled && !readOnly && (typeof inputRef.focus === 'function')) {
83+
if (editEnabled && !readOnlyResult && (typeof inputRef.focus === 'function')) {
8384
inputRef.focus();
8485
}
8586
}
@@ -138,8 +139,9 @@ class JsonValue extends Component {
138139
const style = getStyle(name, value, keyPath, deep, dataType);
139140
let result = null;
140141
let minusElement = null;
142+
const resultOnlyResult = readOnly(name, value, keyPath, deep, dataType);
141143

142-
if (editEnabled && !readOnly) {
144+
if (editEnabled && !resultOnlyResult) {
143145
const editButtonElementLayout = React.cloneElement(editButtonElement, {
144146
onClick: this.handleEdit,
145147
});
@@ -157,16 +159,20 @@ class JsonValue extends Component {
157159
minusElement = null;
158160
} else {
159161
/* eslint-disable jsx-a11y/no-static-element-interactions */
160-
result = (<span className="rejt-value" style={style.value} onClick={readOnly ? null : this.handleEditMode}>
161-
{value}
162-
</span>);
162+
result = (
163+
<span
164+
className="rejt-value" style={style.value} onClick={resultOnlyResult ? null : this.handleEditMode}
165+
>
166+
{value}
167+
</span>
168+
);
163169
/* eslint-enable */
164170
const minusMenuLayout = React.cloneElement(minusMenuElement, {
165171
onClick: handleRemove,
166172
className: 'rejt-minus-menu',
167173
style: style.minus,
168174
});
169-
minusElement = (readOnly) ? null : minusMenuLayout;
175+
minusElement = (resultOnlyResult) ? null : minusMenuLayout;
170176
}
171177

172178
const handlers = {
@@ -184,11 +190,11 @@ class JsonValue extends Component {
184190
}
185191

186192
// Add prop types
187-
JsonValue.propTypes = propTypes;
193+
JsonFunctionValue.propTypes = propTypes;
188194
// Add default props
189-
JsonValue.defaultProps = defaultProps;
195+
JsonFunctionValue.defaultProps = defaultProps;
190196

191197
/* ************************************* */
192198
/* ******** EXPORTS ******** */
193199
/* ************************************* */
194-
export default JsonValue;
200+
export default JsonFunctionValue;

src/components/JsonNode.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const propTypes = {
2727
handleUpdateValue: PropTypes.func,
2828
onUpdate: PropTypes.func.isRequired,
2929
onDeltaUpdate: PropTypes.func.isRequired,
30-
readOnly: PropTypes.bool.isRequired,
30+
readOnly: PropTypes.func.isRequired,
3131
getStyle: PropTypes.func.isRequired,
3232
addButtonElement: PropTypes.element,
3333
cancelButtonElement: PropTypes.element,
@@ -87,7 +87,7 @@ class JsonNode extends Component {
8787
beforeAddAction,
8888
beforeUpdateAction,
8989
} = this.props;
90-
const readOnlyTrue = true;
90+
const readOnlyTrue = () => (true);
9191

9292
const dataType = getObjectType(data);
9393
switch (dataType) {

src/components/JsonObject.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const propTypes = {
2525
handleRemove: PropTypes.func,
2626
onUpdate: PropTypes.func.isRequired,
2727
onDeltaUpdate: PropTypes.func.isRequired,
28-
readOnly: PropTypes.bool.isRequired,
28+
readOnly: PropTypes.func.isRequired,
2929
dataType: PropTypes.string,
3030
getStyle: PropTypes.func.isRequired,
3131
addButtonElement: PropTypes.element,
@@ -225,7 +225,7 @@ class JsonObject extends Component {
225225
const itemName = (numberOfItems > 1) ? 'keys' : 'key';
226226
let minusElement = null;
227227
// Check if readOnly is activated
228-
if (!readOnly) {
228+
if (!readOnly(name, data, keyPath, deep, dataType)) {
229229
const minusMenuLayout = React.cloneElement(minusMenuElement, {
230230
onClick: handleRemove,
231231
className: 'rejt-minus-menu',
@@ -268,8 +268,9 @@ class JsonObject extends Component {
268268
const { minus, plus, addForm, ul, delimiter } = getStyle(name, data, keyPath, deep, dataType);
269269
const keyList = Object.getOwnPropertyNames(data);
270270
let minusElement = null;
271+
const readOnlyResult = readOnly(name, data, keyPath, deep, dataType);
271272
// Check if readOnly is activated
272-
if (!readOnly) {
273+
if (!readOnlyResult) {
273274
const minusMenuLayout = React.cloneElement(minusMenuElement, {
274275
onClick: handleRemove,
275276
className: 'rejt-minus-menu',
@@ -309,7 +310,7 @@ class JsonObject extends Component {
309310

310311
let menu = null;
311312
// Check if readOnly is activated
312-
if (!readOnly) {
313+
if (!readOnlyResult) {
313314
const plusMenuLayout = React.cloneElement(plusMenuElement, {
314315
onClick: this.handleAddMode,
315316
className: 'rejt-plus-menu',

0 commit comments

Comments
 (0)