• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

eclipsesource / jsonforms / 9464337030

11 Jun 2024 10:58AM UTC coverage: 83.237% (-0.1%) from 83.337%
9464337030

push

github

lucas-koehler
change path to JSON pointer

9365 of 21368 branches covered (43.83%)

35 of 42 new or added lines in 12 files covered. (83.33%)

217 existing lines in 37 files now uncovered.

16500 of 19823 relevant lines covered (83.24%)

28.26 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.33
/packages/vanilla-renderers/src/complex/TableArrayControl.tsx
1
/*
2
  The MIT License
3
  
4
  Copyright (c) 2017-2019 EclipseSource Munich
5
  https://github.com/eclipsesource/jsonforms
6
  
7
  Permission is hereby granted, free of charge, to any person obtaining a copy
8
  of this software and associated documentation files (the "Software"), to deal
9
  in the Software without restriction, including without limitation the rights
10
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
  copies of the Software, and to permit persons to whom the Software is
12
  furnished to do so, subject to the following conditions:
13
  
14
  The above copyright notice and this permission notice shall be included in
15
  all copies or substantial portions of the Software.
16
  
17
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
  THE SOFTWARE.
24
*/
25
import React from 'react';
7✔
26
import fpfilter from 'lodash/fp/filter';
7✔
27
import fpmap from 'lodash/fp/map';
7✔
28
import fpflow from 'lodash/fp/flow';
7✔
29
import filter from 'lodash/filter';
7✔
30
import join from 'lodash/join';
7✔
31
import fpkeys from 'lodash/fp/keys';
7✔
32
import fpstartCase from 'lodash/fp/startCase';
7✔
33
import {
7✔
34
  ArrayControlProps,
35
  ControlElement,
36
  createDefaultValue,
37
  Helpers,
38
  Paths,
39
  RankedTester,
40
  Resolve,
41
  Test,
42
  getControlPath,
43
  encode,
44
} from '@jsonforms/core';
45
import { DispatchCell, withJsonFormsArrayControlProps } from '@jsonforms/react';
7✔
46
import { withVanillaControlProps } from '../util';
7✔
47
import type { VanillaRendererProps } from '../index';
48

49
const { convertToValidClassName } = Helpers;
7✔
50

51
const { or, isObjectArrayControl, isPrimitiveArrayControl, rankWith } = Test;
28✔
52

53
/**
54
 * Alternative tester for an array that also checks whether the 'table'
55
 * option is set.
56
 * @type {RankedTester}
57
 */
58
export const tableArrayControlTester: RankedTester = rankWith(
7✔
59
  3,
60
  or(isObjectArrayControl, isPrimitiveArrayControl)
61
);
62

63
class TableArrayControl extends React.Component<
15✔
64
  ArrayControlProps & VanillaRendererProps,
65
  any
66
> {
67
  confirmDelete = (path: string, index: number) => {
15✔
NEW
68
    const p = path.substring(0, path.lastIndexOf('/'));
×
69
    this.props.removeItems(p, [index])();
×
70
  };
71

72
  render() {
25✔
73
    const {
74
      addItem,
25✔
75
      uischema,
25✔
76
      schema,
25✔
77
      rootSchema,
25✔
78
      path,
25✔
79
      data,
25✔
80
      visible,
25✔
81
      errors,
25✔
82
      label,
25✔
83
      getStyleAsClassName,
25✔
84
      childErrors,
25✔
85
      translations,
25✔
86
    } = this.props;
25✔
87

88
    const controlElement = uischema as ControlElement;
25✔
89
    const tableClass = getStyleAsClassName('array.table.table');
25✔
90
    const labelClass = getStyleAsClassName('array.table.label');
25✔
91
    const buttonClass = getStyleAsClassName('array.table.button');
25✔
92
    const validationClass = getStyleAsClassName('array.table.validation');
25✔
93
    const controlClass = [
25✔
94
      getStyleAsClassName('array.table'),
95
      convertToValidClassName(controlElement.scope),
96
    ].join(' ');
97
    const createControlElement = (key?: string): ControlElement => ({
40✔
98
      type: 'Control',
99
      label: false,
100
      scope: schema.type === 'object' ? `#/properties/${key}` : '#',
40✔
101
    });
102
    const isValid = errors.length === 0;
25✔
103
    const divClassNames = [validationClass]
25✔
104
      .concat(
105
        isValid ? '' : getStyleAsClassName('array.table.validation.error')
25✔
106
      )
107
      .join(' ');
108

109
    return (
25✔
110
      <div className={controlClass} hidden={!visible}>
111
        <header>
112
          <label className={labelClass}>{label}</label>
113
          <button
114
            type='button'
115
            className={buttonClass}
116
            onClick={addItem(path, createDefaultValue(schema, rootSchema))}
117
          >
118
            {translations.addTooltip}
119
          </button>
120
        </header>
121
        <div className={divClassNames}>{!isValid ? errors : ''}</div>
25✔
122
        <table className={tableClass}>
123
          <thead>
124
            <tr>
125
              {schema.properties ? (
25✔
126
                fpflow(
127
                  fpkeys,
128
                  fpfilter((prop) => schema.properties[prop].type !== 'array'),
48✔
129
                  fpmap((prop) => (
48✔
130
                    <th key={prop}>
131
                      {schema.properties[prop].title ?? fpstartCase(prop)}
144✔
132
                    </th>
133
                  ))
134
                )(schema.properties)
135
              ) : (
136
                <th>Items</th>
137
              )}
138
              <th>Valid</th>
139
              <th>&nbsp;</th>
140
            </tr>
141
          </thead>
142
          <tbody>
143
            {!data || !Array.isArray(data) || data.length === 0 ? (
91✔
144
              <tr>
145
                <td>{translations.noDataMessage}</td>
146
              </tr>
147
            ) : (
148
              data.map((_child, index) => {
149
                const childPath = Paths.compose(path, `/${index}`);
21✔
150
                // TODO
151
                const errorsPerEntry: any[] = filter(childErrors, (error) => {
21✔
152
                  const errorPath = getControlPath(error);
2✔
153
                  return errorPath.startsWith(childPath);
2✔
154
                });
155

156
                const validationClassName =
157
                  getStyleAsClassName('array.validation');
21✔
158
                const errorValidationClassName = getStyleAsClassName(
21✔
159
                  'array.validation.error'
160
                );
161
                const errorClassNames = errorsPerEntry
21!
162
                  ? [validationClassName]
163
                      .concat(errorValidationClassName)
164
                      .join(' ')
165
                  : validationClassName;
166

167
                return (
21✔
168
                  <tr key={childPath}>
169
                    {schema.properties ? (
21✔
170
                      fpflow(
171
                        fpkeys,
172
                        fpfilter(
173
                          (prop) => schema.properties[prop].type !== 'array'
38✔
174
                        ),
175
                        fpmap((prop) => {
176
                          const childPropPath = Paths.compose(
38✔
177
                            childPath,
178
                            '/' + prop.toString()
179
                          );
180
                          return (
38✔
181
                            <td key={childPropPath}>
182
                              <DispatchCell
183
                                schema={Resolve.schema(
184
                                  schema,
185
                                  `#/properties/${encode(prop)}`,
186
                                  rootSchema
187
                                )}
188
                                uischema={createControlElement(encode(prop))}
189
                                path={childPath + '/' + prop}
190
                              />
191
                            </td>
192
                          );
193
                        })
194
                      )(schema.properties)
195
                    ) : (
196
                      <td
197
                        key={Paths.compose(childPath, '/' + index.toString())}
198
                      >
199
                        <DispatchCell
200
                          schema={schema}
201
                          uischema={createControlElement()}
202
                          path={childPath}
203
                        />
204
                      </td>
205
                    )}
206
                    <td>
207
                      {errorsPerEntry ? (
21!
208
                        <span className={errorClassNames}>
209
                          {join(
210
                            errorsPerEntry.map((e) => e.message),
1✔
211
                            ' and '
212
                          )}
213
                        </span>
214
                      ) : (
215
                        <span className={errorClassNames}>OK</span>
216
                      )}
217
                    </td>
218
                    <td>
219
                      <button
220
                        type='button'
221
                        aria-label={translations.removeAriaLabel}
222
                        onClick={() => {
223
                          if (
×
224
                            window.confirm(translations.deleteDialogMessage)
225
                          ) {
226
                            this.confirmDelete(childPath, index);
×
227
                          }
228
                        }}
229
                      >
230
                        {translations.removeTooltip}
231
                      </button>
232
                    </td>
233
                  </tr>
234
                );
235
              })
236
            )}
237
          </tbody>
238
        </table>
239
      </div>
240
    );
241
  }
242
}
7✔
243

244
export default withVanillaControlProps(
7✔
245
  withJsonFormsArrayControlProps(TableArrayControl)
246
);
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc