@rh-support/cases 2.1.29 → 2.1.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/esm/components/case-list/case-list-filters/AccountsFilter.d.ts.map +1 -1
- package/lib/esm/components/case-list/case-list-filters/AccountsFilter.js +5 -3
- package/lib/esm/components/case-list/case-list-filters/CreatorSsoNameFilter.d.ts.map +1 -1
- package/lib/esm/components/case-list/case-list-filters/CreatorSsoNameFilter.js +17 -5
- package/lib/esm/components/case-list/case-list-filters/InternalSsoNameFilter.d.ts.map +1 -1
- package/lib/esm/components/case-list/case-list-filters/InternalSsoNameFilter.js +30 -6
- package/lib/esm/components/case-list/case-list-filters/ProductsFilter.d.ts.map +1 -1
- package/lib/esm/components/case-list/case-list-filters/ProductsFilter.js +2 -1
- package/lib/esm/css/caseList.css +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccountsFilter.d.ts","sourceRoot":"","sources":["../../../../../src/components/case-list/case-list-filters/AccountsFilter.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AAe1F,UAAU,MAAM;IACZ,uBAAuB,EAAE,OAAO,CAAC;CACpC;AAED,eAAO,MAAM,gCAAgC,YAAa,QAAQ,WAMjE,CAAC;AACF,eAAO,MAAM,+BAA+B,YAAa,QAAQ,sBAAsB,CAAC,WAEvF,CAAC;AAEF,eAAO,MAAM,QAAQ,0CACyD,CAAC;AAE/E,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"AccountsFilter.d.ts","sourceRoot":"","sources":["../../../../../src/components/case-list/case-list-filters/AccountsFilter.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AAe1F,UAAU,MAAM;IACZ,uBAAuB,EAAE,OAAO,CAAC;CACpC;AAED,eAAO,MAAM,gCAAgC,YAAa,QAAQ,WAMjE,CAAC;AACF,eAAO,MAAM,+BAA+B,YAAa,QAAQ,sBAAsB,CAAC,WAEvF,CAAC;AAEF,eAAO,MAAM,QAAQ,0CACyD,CAAC;AAE/E,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,eA+F3C"}
|
|
@@ -14,7 +14,7 @@ import differenceBy from 'lodash/differenceBy';
|
|
|
14
14
|
import filter from 'lodash/filter';
|
|
15
15
|
import remove from 'lodash/remove';
|
|
16
16
|
import uniqBy from 'lodash/uniqBy';
|
|
17
|
-
import React, { useContext, useEffect } from 'react';
|
|
17
|
+
import React, { useContext, useEffect, useMemo } from 'react';
|
|
18
18
|
import { Trans, useTranslation } from 'react-i18next';
|
|
19
19
|
import { SolrKeys } from '../../../enums/filters';
|
|
20
20
|
import { CaseListFilterDispatchContext, CaseListFilterStateContext } from '../CaseListFilterContext';
|
|
@@ -35,12 +35,14 @@ export function AccountsFilter(props) {
|
|
|
35
35
|
const { canReadBookmarkAccounts } = props;
|
|
36
36
|
const { filterInfo } = useContext(CaseListFilterStateContext);
|
|
37
37
|
const dispatch = useContext(CaseListFilterDispatchContext);
|
|
38
|
-
const selectedAccounts = filterInfo[SolrKeys.accountNumber]
|
|
38
|
+
const selectedAccounts = useMemo(() => filterInfo[SolrKeys.accountNumber]
|
|
39
39
|
.filter((item) => !Array.isArray(item.key))
|
|
40
40
|
.map((item) => ({
|
|
41
41
|
name: item.value,
|
|
42
42
|
accountNumber: item.key,
|
|
43
|
-
}))
|
|
43
|
+
})),
|
|
44
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
45
|
+
[filterInfo, filterInfo[SolrKeys.accountNumber]]);
|
|
44
46
|
const onAccountsFilterChange = (selected) => {
|
|
45
47
|
const toAdd = differenceBy(selected, selectedAccounts, 'accountNumber');
|
|
46
48
|
const toRemove = differenceBy(selectedAccounts, selected, 'accountNumber');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CreatorSsoNameFilter.d.ts","sourceRoot":"","sources":["../../../../../src/components/case-list/case-list-filters/CreatorSsoNameFilter.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CreatorSsoNameFilter.d.ts","sourceRoot":"","sources":["../../../../../src/components/case-list/case-list-filters/CreatorSsoNameFilter.tsx"],"names":[],"mappings":"AAiCA,eAAO,MAAM,WAAW,0BAIvB,CAAC;AAYF,eAAO,MAAM,eAAe;;;;;;;GAA6E,CAAC;AAE1G,eAAO,MAAM,kBAAkB,iEAyC9B,CAAC;AAEF,wBAAgB,oBAAoB,gBA0OnC"}
|
|
@@ -8,12 +8,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { accounts } from '@cee-eng/hydrajs';
|
|
11
|
-
import { Button, MenuToggle, Select, SelectGroup, SelectOption, TextInputGroup, TextInputGroupMain, TextInputGroupUtilities, } from '@patternfly/react-core';
|
|
11
|
+
import { Button, MenuToggle, Select, SelectGroup, SelectList, SelectOption, TextInputGroup, TextInputGroupMain, TextInputGroupUtilities, } from '@patternfly/react-core';
|
|
12
12
|
import TimesCircleIcon from '@patternfly/react-icons/dist/js/icons/times-circle-icon';
|
|
13
13
|
import { LoadingIndicator, useFetch, useSelectKeyboardNavigator } from '@rh-support/components';
|
|
14
14
|
import { GlobalMetadataStateContext } from '@rh-support/react-context';
|
|
15
15
|
import { getDropdownBtnPlaceholder } from '@rh-support/utils';
|
|
16
|
-
import { isEmpty } from 'lodash';
|
|
16
|
+
import { isEmpty, isNull } from 'lodash';
|
|
17
|
+
import isUndefined from 'lodash/isUndefined';
|
|
17
18
|
import uniqBy from 'lodash/uniqBy';
|
|
18
19
|
import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
|
|
19
20
|
import { Trans, useTranslation } from 'react-i18next';
|
|
@@ -92,8 +93,11 @@ export function CreatorSsoNameFilter() {
|
|
|
92
93
|
const externalInputRef = useRef();
|
|
93
94
|
const [externalContactList, setExternalContactList] = useState([]);
|
|
94
95
|
const [isExternalOpen, setIsExternalOpen] = useState(false);
|
|
96
|
+
const [noResults, setNoResults] = useState(false);
|
|
95
97
|
const [externalQuery, setExternalQuery] = useState('');
|
|
96
98
|
const onSelectExternal = (contact) => {
|
|
99
|
+
if (isNull(contact) || isUndefined(contact))
|
|
100
|
+
return;
|
|
97
101
|
let list = [];
|
|
98
102
|
if (selectedExternalContacts.some((item) => item.value === contact.value)) {
|
|
99
103
|
list = selectedExternalContacts.filter((item) => item.value !== contact.value);
|
|
@@ -118,6 +122,7 @@ export function CreatorSsoNameFilter() {
|
|
|
118
122
|
const filteredValues = getFilterValues(externalContactList, own);
|
|
119
123
|
const input = new RegExp(externalQuery, 'i');
|
|
120
124
|
const newOptions = filteredValues.filter((v) => input.test(v.value || ''));
|
|
125
|
+
setNoResults(isEmpty(newOptions));
|
|
121
126
|
return newOptions;
|
|
122
127
|
}, [externalContactList, own, externalQuery]);
|
|
123
128
|
const { onInputKeyDown, focusedItemIndex } = useSelectKeyboardNavigator({
|
|
@@ -173,19 +178,25 @@ export function CreatorSsoNameFilter() {
|
|
|
173
178
|
}, [dispatch, isExternalNonOrgAdmin, loggedInUserRights.data]);
|
|
174
179
|
const filteredExternalList = useMemo(() => {
|
|
175
180
|
return [
|
|
181
|
+
...(noResults
|
|
182
|
+
? [
|
|
183
|
+
React.createElement("div", { key: "no-results", className: "pf-v5-u-p-sm" },
|
|
184
|
+
React.createElement(Trans, null, "No results found")),
|
|
185
|
+
]
|
|
186
|
+
: []),
|
|
176
187
|
...dropdownHeader.map((contact, index) => (React.createElement(SelectOption, { key: contact.value, isFocused: focusedItemIndex === index, value: contact, hasCheckbox: true, isSelected: selectedExternalContacts.some((c) => c.value === contact.value) }, contact.label))),
|
|
177
188
|
...(!isEmpty(filteredOptions)
|
|
178
189
|
? [
|
|
179
190
|
React.createElement("div", { className: "pf-v5-c-divider", role: "separator", key: "separator" }),
|
|
180
191
|
React.createElement(SelectGroup, { key: "created-or-owned-by-accounts-group" },
|
|
181
|
-
React.createElement("
|
|
192
|
+
React.createElement("h6", { className: "pf-v5-u-pl-md" },
|
|
182
193
|
React.createElement(Trans, null, "Created or owned by")),
|
|
183
194
|
filteredOptions.map((contact, index) => (React.createElement(SelectOption, { key: contact.value, isFocused: focusedItemIndex === index + dropdownHeader.length, value: contact, hasCheckbox: true, isSelected: selectedExternalContacts.some((c) => c.value === contact.value) }, contact.label)))),
|
|
184
195
|
]
|
|
185
196
|
: []),
|
|
186
197
|
];
|
|
187
198
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
188
|
-
}, [filteredOptions, selectedExternalContacts, focusedItemIndex]);
|
|
199
|
+
}, [filteredOptions, selectedExternalContacts, focusedItemIndex, noResults]);
|
|
189
200
|
const onExternalQueryChange = (_v, query) => {
|
|
190
201
|
setExternalQuery(query);
|
|
191
202
|
};
|
|
@@ -199,5 +210,6 @@ export function CreatorSsoNameFilter() {
|
|
|
199
210
|
return (React.createElement("div", null,
|
|
200
211
|
React.createElement("label", { htmlFor: "case-list-username-filter" },
|
|
201
212
|
React.createElement(Trans, null, filterNamesMap['usernameFilterTitle'])),
|
|
202
|
-
!loggedInUserRights.data.isInternal() ? (React.createElement(Select, { id: "external-ssousername-filter", "data-tracking-id": "external-ssousername-filter", isOpen: isExternalOpen, onOpenChange: () => setIsExternalOpen(false), toggle: externalToggle, popperProps: { direction: 'down', enableFlip: false }, isScrollable: true, onSelect: (_e, v) => onSelectExternal(v) },
|
|
213
|
+
!loggedInUserRights.data.isInternal() ? (React.createElement(Select, { id: "external-ssousername-filter", "data-tracking-id": "external-ssousername-filter", isOpen: isExternalOpen, onOpenChange: () => setIsExternalOpen(false), toggle: externalToggle, popperProps: { direction: 'down', enableFlip: false }, isScrollable: true, onSelect: (_e, v) => onSelectExternal(v) },
|
|
214
|
+
React.createElement(SelectList, null, filteredExternalList))) : (React.createElement(InternalSsoNameFilter, null))));
|
|
203
215
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InternalSsoNameFilter.d.ts","sourceRoot":"","sources":["../../../../../src/components/case-list/case-list-filters/InternalSsoNameFilter.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"InternalSsoNameFilter.d.ts","sourceRoot":"","sources":["../../../../../src/components/case-list/case-list-filters/InternalSsoNameFilter.tsx"],"names":[],"mappings":"AAkCA,MAAM,CAAC,OAAO,UAAU,qBAAqB,gBA6R5C"}
|
|
@@ -8,13 +8,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { contacts } from '@cee-eng/hydrajs';
|
|
11
|
-
import { Button, Flex, FlexItem, MenuToggle, Select, SelectGroup, SelectOption, TextInputGroup, TextInputGroupMain, TextInputGroupUtilities, } from '@patternfly/react-core';
|
|
11
|
+
import { Button, Flex, FlexItem, MenuToggle, Select, SelectGroup, SelectList, SelectOption, TextInputGroup, TextInputGroupMain, TextInputGroupUtilities, } from '@patternfly/react-core';
|
|
12
12
|
import TimesCircleIcon from '@patternfly/react-icons/dist/js/icons/times-circle-icon';
|
|
13
13
|
import { LoadingIndicator, useFetch, useSelectKeyboardNavigator } from '@rh-support/components';
|
|
14
14
|
import { GlobalMetadataStateContext } from '@rh-support/react-context';
|
|
15
15
|
import { getDropdownBtnPlaceholder } from '@rh-support/utils';
|
|
16
|
-
import { isUndefined } from 'lodash';
|
|
17
16
|
import isEmpty from 'lodash/isEmpty';
|
|
17
|
+
import isNull from 'lodash/isNull';
|
|
18
|
+
import isUndefined from 'lodash/isUndefined';
|
|
18
19
|
import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
|
|
19
20
|
import { Trans, useTranslation } from 'react-i18next';
|
|
20
21
|
import { SolrKeys } from '../../../enums/filters';
|
|
@@ -39,6 +40,7 @@ export default function InternalSsoNameFilter() {
|
|
|
39
40
|
const [internalContactList, setInternalContactList] = useState([]);
|
|
40
41
|
const [renderedList, setRenderedList] = useState([]);
|
|
41
42
|
const [isInternalOpen, setIsInternalOpen] = useState(false);
|
|
43
|
+
const [noResults, setNoResults] = useState(false);
|
|
42
44
|
const [internalQuery, setInternalQuery] = useState('');
|
|
43
45
|
const filteredOptions = getFilterValues(renderedList, own);
|
|
44
46
|
const dropdownHeader = [
|
|
@@ -55,7 +57,7 @@ export default function InternalSsoNameFilter() {
|
|
|
55
57
|
setRenderedList(internalContactList.slice(0, PER_PAGE));
|
|
56
58
|
}, [internalContactList]);
|
|
57
59
|
const onSelectInternal = (contact) => {
|
|
58
|
-
if (isUndefined(contact) || contact === 'show-more')
|
|
60
|
+
if (isNull(contact) || isUndefined(contact) || contact === 'show-more')
|
|
59
61
|
return;
|
|
60
62
|
let list = [];
|
|
61
63
|
if (selectedInternalContacts.some((item) => item.value === contact.value)) {
|
|
@@ -137,6 +139,7 @@ export default function InternalSsoNameFilter() {
|
|
|
137
139
|
const contacts = response && response.items && response.items.length !== 0
|
|
138
140
|
? response.items.filter((c) => !isEmpty(c.ssoUsername))
|
|
139
141
|
: [];
|
|
142
|
+
setNoResults(isEmpty(contacts));
|
|
140
143
|
setInternalContactList(contacts);
|
|
141
144
|
});
|
|
142
145
|
const onDisplayMoreClick = () => {
|
|
@@ -145,12 +148,24 @@ export default function InternalSsoNameFilter() {
|
|
|
145
148
|
};
|
|
146
149
|
const filteredInternalList = useMemo(() => {
|
|
147
150
|
return [
|
|
151
|
+
...(isFetchingInternalContacts
|
|
152
|
+
? [
|
|
153
|
+
React.createElement("div", { key: "searching", className: "pf-v5-u-p-sm" },
|
|
154
|
+
React.createElement(Trans, null, "Searching...")),
|
|
155
|
+
]
|
|
156
|
+
: []),
|
|
157
|
+
...(noResults && !isFetchingInternalContacts
|
|
158
|
+
? [
|
|
159
|
+
React.createElement("div", { key: "no-results", className: "pf-v5-u-p-sm" },
|
|
160
|
+
React.createElement(Trans, null, "No results found")),
|
|
161
|
+
]
|
|
162
|
+
: []),
|
|
148
163
|
...dropdownHeader.map((contact, index) => (React.createElement(SelectOption, { key: contact.value, isFocused: focusedItemIndex === index, value: contact, hasCheckbox: true, isSelected: selectedInternalContacts.some((c) => c.value === contact.value) }, contact.label))),
|
|
149
164
|
...(!isEmpty(filteredOptions)
|
|
150
165
|
? [
|
|
151
166
|
React.createElement("div", { className: "pf-v5-c-divider", role: "separator" }),
|
|
152
167
|
React.createElement(SelectGroup, null,
|
|
153
|
-
React.createElement("
|
|
168
|
+
React.createElement("h6", { className: "pf-v5-u-pl-md" },
|
|
154
169
|
React.createElement(Trans, null, "Created or owned by")),
|
|
155
170
|
filteredOptions.map((contact, index) => (React.createElement(SelectOption, { key: contact.value, isFocused: focusedItemIndex === index + dropdownHeader.length, value: contact, hasCheckbox: true, isSelected: selectedInternalContacts.some((c) => c.value === contact.value) }, contact.label)))),
|
|
156
171
|
]
|
|
@@ -167,7 +182,15 @@ export default function InternalSsoNameFilter() {
|
|
|
167
182
|
: []),
|
|
168
183
|
];
|
|
169
184
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
170
|
-
}, [
|
|
185
|
+
}, [
|
|
186
|
+
internalContactList,
|
|
187
|
+
own,
|
|
188
|
+
selectedInternalContacts,
|
|
189
|
+
renderedList,
|
|
190
|
+
focusedItemIndex,
|
|
191
|
+
isFetchingInternalContacts,
|
|
192
|
+
noResults,
|
|
193
|
+
]);
|
|
171
194
|
const onInternalQueryChange = (_v, query) => {
|
|
172
195
|
setInternalQuery(query);
|
|
173
196
|
onSearchAsync(query);
|
|
@@ -179,5 +202,6 @@ export default function InternalSsoNameFilter() {
|
|
|
179
202
|
React.createElement(TextInputGroup, { isPlain: true },
|
|
180
203
|
React.createElement(TextInputGroupMain, { value: internalQuery, onClick: onInternalToggle, onKeyDown: onInputKeyDown, placeholder: getDropdownBtnPlaceholder(t('Search for a name'), selectedInternalContacts.map((i) => i.label), ' ', filteredInternalList.length, t('All contacts')), onChange: onInternalQueryChange, isExpanded: isInternalOpen, innerRef: internalInputRef }),
|
|
181
204
|
React.createElement(TextInputGroupUtilities, null, !isEmpty(internalQuery) && (React.createElement(Button, { variant: "plain", onClick: () => setInternalQuery(''), isDisabled: isFetchingInternalContacts, "aria-label": t('Clear') }, isFetchingInternalContacts ? (React.createElement(LoadingIndicator, { show: true, size: "sm" })) : (React.createElement(TimesCircleIcon, { "aria-hidden": true }))))))));
|
|
182
|
-
return (React.createElement(Select, { id: "internal-ssousername-filter", "data-tracking-id": "internal-ssousername-filter", isOpen: isInternalOpen, onOpenChange: () => setIsInternalOpen(false), toggle: internalToggle, popperProps: { direction: 'down', enableFlip: false }, isScrollable: true, onSelect: (_e, v) => onSelectInternal(v) },
|
|
205
|
+
return (React.createElement(Select, { id: "internal-ssousername-filter", "data-tracking-id": "internal-ssousername-filter", isOpen: isInternalOpen, onOpenChange: () => setIsInternalOpen(false), toggle: internalToggle, popperProps: { direction: 'down', enableFlip: false }, isScrollable: true, onSelect: (_e, v) => onSelectInternal(v) },
|
|
206
|
+
React.createElement(SelectList, null, filteredInternalList)));
|
|
183
207
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProductsFilter.d.ts","sourceRoot":"","sources":["../../../../../src/components/case-list/case-list-filters/ProductsFilter.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAW1D,UAAU,MAAM;IACZ,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,WAAW,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"ProductsFilter.d.ts","sourceRoot":"","sources":["../../../../../src/components/case-list/case-list-filters/ProductsFilter.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAW1D,UAAU,MAAM;IACZ,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,WAAW,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,eAgH3C"}
|
|
@@ -59,7 +59,8 @@ export function ProductsFilter(props) {
|
|
|
59
59
|
const onFilter = (_, value) => {
|
|
60
60
|
if (!value)
|
|
61
61
|
return getProductSelectOptions(productOptions);
|
|
62
|
-
const
|
|
62
|
+
const formattedValue = value === null || value === void 0 ? void 0 : value.replace(/\\/g, ''); // Removes '\' from search query as it creates SyntaxError for RegEx
|
|
63
|
+
const input = new RegExp(formattedValue, 'i');
|
|
63
64
|
const newOptions = productOptions.filter((product) => input.test(product.value));
|
|
64
65
|
return getProductSelectOptions(newOptions);
|
|
65
66
|
};
|
package/lib/esm/css/caseList.css
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rh-support/cases",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.31",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"registry": "https://registry.npmjs.org"
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"@patternfly/pfe-collapse": "1.12.3",
|
|
47
47
|
"@patternfly/react-core": "5.1.1",
|
|
48
48
|
"@patternfly/react-table": "5.1.1",
|
|
49
|
-
"@rh-support/components": "2.1.
|
|
50
|
-
"@rh-support/react-context": "2.1.
|
|
49
|
+
"@rh-support/components": "2.1.27",
|
|
50
|
+
"@rh-support/react-context": "2.1.30",
|
|
51
51
|
"@rh-support/types": "2.0.2",
|
|
52
52
|
"@rh-support/user-permissions": "2.1.19",
|
|
53
53
|
"@rh-support/utils": "2.1.12",
|
|
@@ -93,5 +93,5 @@
|
|
|
93
93
|
"defaults and supports es6-module",
|
|
94
94
|
"maintained node versions"
|
|
95
95
|
],
|
|
96
|
-
"gitHead": "
|
|
96
|
+
"gitHead": "c70ed8ffa9b5dbe8abdd50e1549e92b8af2a6f27"
|
|
97
97
|
}
|