@lblod/ember-rdfa-editor-lblod-plugins 19.1.0 → 19.2.0
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/CHANGELOG.md +22 -0
- package/addon/components/au-native-input.ts +12 -13
- package/addon/components/{worship-plugin → common/sort}/sortable-table-header.hbs +3 -9
- package/addon/components/{worship-plugin → common/sort}/sortable-table-header.ts +3 -6
- package/addon/components/lmb-plugin/insert.hbs +18 -0
- package/addon/components/lmb-plugin/insert.ts +121 -0
- package/addon/components/lmb-plugin/list.hbs +58 -0
- package/addon/components/lmb-plugin/search-modal.hbs +71 -0
- package/addon/components/lmb-plugin/search-modal.ts +173 -0
- package/addon/components/loading-alert.hbs +3 -1
- package/addon/components/location-plugin/edit.gts +380 -0
- package/addon/components/location-plugin/insert-variable.gts +67 -0
- package/addon/components/location-plugin/insert.gts +153 -0
- package/addon/components/location-plugin/nodeview.hbs +20 -0
- package/addon/components/location-plugin/nodeview.ts +49 -0
- package/addon/components/lpdc-plugin/lpdc-insert.hbs +19 -0
- package/addon/components/lpdc-plugin/lpdc-insert.ts +93 -0
- package/addon/components/lpdc-plugin/lpdc-modal.hbs +44 -0
- package/addon/components/lpdc-plugin/lpdc-modal.ts +79 -0
- package/addon/components/lpdc-plugin/lpdc-table-view.hbs +53 -0
- package/addon/components/lpdc-plugin/lpdc-table-view.ts +23 -0
- package/addon/components/variable-plugin/address/edit.ts +1 -1
- package/addon/components/variable-plugin/address/nodeview.ts +1 -1
- package/addon/components/worship-plugin/list.hbs +1 -1
- package/addon/models/mandatee.ts +35 -0
- package/addon/plugins/lmb-plugin/index.ts +3 -0
- package/addon/plugins/location-plugin/address.ts +405 -0
- package/addon/plugins/location-plugin/utils/address-helpers.ts +395 -0
- package/addon/plugins/location-plugin/utils/node-utils.ts +51 -0
- package/addon/plugins/lpdc-plugin/api.ts +114 -0
- package/addon/plugins/lpdc-plugin/index.ts +2 -0
- package/addon/plugins/lpdc-plugin/types.ts +5 -0
- package/addon/plugins/snippet-plugin/nodes/snippet-placeholder.ts +5 -3
- package/addon/plugins/variable-plugin/utils/address-helpers.ts +130 -12
- package/addon/plugins/variable-plugin/utils/dom-constructors.ts +3 -19
- package/addon/plugins/variable-plugin/variables/address.ts +122 -84
- package/addon/plugins/variable-plugin/variables/codelist.ts +1 -1
- package/addon/plugins/variable-plugin/variables/date.ts +1 -1
- package/addon/plugins/variable-plugin/variables/location.ts +2 -2
- package/addon/plugins/variable-plugin/variables/number.ts +1 -1
- package/addon/plugins/variable-plugin/variables/text.ts +1 -1
- package/addon/utils/constants.ts +15 -1
- package/addon/utils/dom-output-spec-helpers.ts +20 -3
- package/app/components/{worship-plugin → common/sort}/sortable-table-header.js +1 -1
- package/app/components/lmb-plugin/insert.js +1 -0
- package/app/components/lmb-plugin/list.js +1 -0
- package/app/components/lmb-plugin/search-modal.js +1 -0
- package/app/components/location-plugin/edit.js +1 -0
- package/app/components/location-plugin/insert-variable.js +1 -0
- package/app/components/location-plugin/insert.js +1 -0
- package/app/components/location-plugin/nodeview.js +1 -0
- package/app/components/lpdc-plugin/lpdc-insert.js +1 -0
- package/app/components/lpdc-plugin/lpdc-modal.js +1 -0
- package/app/components/lpdc-plugin/lpdc-table-view.js +1 -0
- package/app/styles/article-structure-plugin.scss +12 -6
- package/app/styles/snippet-plugin.scss +19 -0
- package/declarations/addon/components/au-native-input.d.ts +12 -10
- package/declarations/addon/components/{worship-plugin → common/sort}/sortable-table-header.d.ts +3 -3
- package/declarations/addon/components/lmb-plugin/insert.d.ts +17 -0
- package/declarations/addon/components/lmb-plugin/list.d.ts +1 -0
- package/declarations/addon/components/lmb-plugin/search-modal.d.ts +31 -0
- package/declarations/addon/components/location-plugin/edit.d.ts +47 -0
- package/declarations/addon/components/location-plugin/insert-variable.d.ts +17 -0
- package/declarations/addon/components/location-plugin/insert.d.ts +29 -0
- package/declarations/addon/components/location-plugin/nodeview.d.ts +22 -0
- package/declarations/addon/components/lpdc-plugin/lpdc-insert.d.ts +17 -0
- package/declarations/addon/components/lpdc-plugin/lpdc-modal.d.ts +42 -0
- package/declarations/addon/components/lpdc-plugin/lpdc-table-view.d.ts +37 -0
- package/declarations/addon/components/variable-plugin/address/edit.d.ts +1 -1
- package/declarations/addon/components/variable-plugin/address/nodeview.d.ts +1 -1
- package/declarations/addon/models/mandatee.d.ts +13 -0
- package/declarations/addon/plugins/lmb-plugin/index.d.ts +3 -0
- package/declarations/addon/plugins/location-plugin/address.d.ts +2 -0
- package/declarations/addon/plugins/location-plugin/utils/address-helpers.d.ts +65 -0
- package/declarations/addon/plugins/location-plugin/utils/node-utils.d.ts +2 -0
- package/declarations/addon/plugins/lpdc-plugin/api.d.ts +29 -0
- package/declarations/addon/plugins/lpdc-plugin/index.d.ts +2 -0
- package/declarations/addon/plugins/lpdc-plugin/types.d.ts +7 -0
- package/declarations/addon/plugins/variable-plugin/utils/address-helpers.d.ts +34 -1
- package/declarations/addon/plugins/variable-plugin/utils/dom-constructors.d.ts +5 -11
- package/declarations/addon/plugins/variable-plugin/variables/address.d.ts +0 -13
- package/declarations/addon/utils/constants.d.ts +5 -0
- package/declarations/addon/utils/dom-output-spec-helpers.d.ts +6 -2
- package/package.json +2 -2
- package/pnpm-lock.yaml +19 -8
- package/translations/en-US.yaml +41 -14
- package/translations/nl-BE.yaml +41 -13
- package/types/ember-concurrency/helpers/perform.d.ts +48 -0
- package/types/ember-power-select/components/power-select.d.ts +160 -0
- /package/addon/{plugins/variable-plugin/utils/attribute-parsers.ts → utils/variable-attribute-parsers.ts} +0 -0
- /package/declarations/addon/{plugins/variable-plugin/utils/attribute-parsers.d.ts → utils/variable-attribute-parsers.d.ts} +0 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { action } from '@ember/object';
|
|
2
|
+
import Component from '@glimmer/component';
|
|
3
|
+
import { tracked } from '@glimmer/tracking';
|
|
4
|
+
import { AddIcon } from '@appuniversum/ember-appuniversum/components/icons/add';
|
|
5
|
+
|
|
6
|
+
import { SayController } from '@lblod/ember-rdfa-editor';
|
|
7
|
+
import { sayDataFactory } from '@lblod/ember-rdfa-editor/core/say-data-factory';
|
|
8
|
+
import { addProperty } from '@lblod/ember-rdfa-editor/commands';
|
|
9
|
+
import {
|
|
10
|
+
LPDC,
|
|
11
|
+
type LpdcPluginConfig,
|
|
12
|
+
} from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/lpdc-plugin';
|
|
13
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
14
|
+
import { getCurrentBesluitRange } from '../../plugins/besluit-topic-plugin/utils/helpers';
|
|
15
|
+
import { SRO } from '../../utils/constants';
|
|
16
|
+
|
|
17
|
+
interface Args {
|
|
18
|
+
controller: SayController;
|
|
19
|
+
config: LpdcPluginConfig;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default class LpdcPluginsInsertComponent extends Component<Args> {
|
|
23
|
+
AddIcon = AddIcon;
|
|
24
|
+
|
|
25
|
+
@tracked showModal = false;
|
|
26
|
+
|
|
27
|
+
get controller() {
|
|
28
|
+
return this.args.controller;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@action
|
|
32
|
+
openModal() {
|
|
33
|
+
this.controller.focus();
|
|
34
|
+
this.showModal = true;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@action
|
|
38
|
+
closeModal() {
|
|
39
|
+
this.showModal = false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
get isButtonDisabled() {
|
|
43
|
+
return !getCurrentBesluitRange(this.controller);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@action
|
|
47
|
+
onLpdcInsert(lpdc: LPDC) {
|
|
48
|
+
const currentBesluitRange = getCurrentBesluitRange(this.controller);
|
|
49
|
+
|
|
50
|
+
const resource =
|
|
51
|
+
(currentBesluitRange &&
|
|
52
|
+
'node' in currentBesluitRange &&
|
|
53
|
+
(currentBesluitRange.node.attrs.subject as string)) ||
|
|
54
|
+
undefined;
|
|
55
|
+
|
|
56
|
+
if (!resource) {
|
|
57
|
+
throw new Error('No besluit found in selection');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const rdfaId = uuidv4();
|
|
61
|
+
const uri = lpdc.uri;
|
|
62
|
+
const name = lpdc.name;
|
|
63
|
+
|
|
64
|
+
this.controller.withTransaction(
|
|
65
|
+
(tr) => {
|
|
66
|
+
const node = this.controller.schema.node(
|
|
67
|
+
'inline_rdfa',
|
|
68
|
+
{
|
|
69
|
+
rdfaNodeType: 'resource',
|
|
70
|
+
__rdfaId: rdfaId,
|
|
71
|
+
subject: uri,
|
|
72
|
+
},
|
|
73
|
+
[this.controller.schema.text(name)],
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
return tr.replaceSelectionWith(node);
|
|
77
|
+
},
|
|
78
|
+
{ view: this.controller.mainEditorView },
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
this.controller.doCommand(
|
|
82
|
+
addProperty({
|
|
83
|
+
resource,
|
|
84
|
+
property: {
|
|
85
|
+
predicate: SRO('bekrachtigt').full,
|
|
86
|
+
object: sayDataFactory.resourceNode(uri),
|
|
87
|
+
},
|
|
88
|
+
}),
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
this.closeModal();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{{! @glint-nocheck: not typesafe yet }}
|
|
2
|
+
<AuModal
|
|
3
|
+
@modalOpen={{@open}}
|
|
4
|
+
@closeModal={{this.closeModal}}
|
|
5
|
+
@title={{t 'lpdc-plugin.modal.title'}}
|
|
6
|
+
@size='large'
|
|
7
|
+
@padding='none'
|
|
8
|
+
as |modal|
|
|
9
|
+
>
|
|
10
|
+
<modal.Body>
|
|
11
|
+
<AuMainContainer class='snippet-modal--main-container' as |mc|>
|
|
12
|
+
<mc.content @scroll={{true}}>
|
|
13
|
+
<div class='snippet-modal--list-container'>
|
|
14
|
+
{{#if this.error}}
|
|
15
|
+
<Common::Search::AlertLoadError
|
|
16
|
+
@error={{this.error}}
|
|
17
|
+
class='au-u-margin-top-none'
|
|
18
|
+
/>
|
|
19
|
+
{{else}}
|
|
20
|
+
<LpdcPlugin::LpdcTableView
|
|
21
|
+
@lpdc={{this.lpdcResource.value}}
|
|
22
|
+
@isLoading={{this.lpdcResource.isRunning}}
|
|
23
|
+
@onLpdcInsert={{@onLpdcInsert}}
|
|
24
|
+
@nameFilter={{this.searchText}}
|
|
25
|
+
@pageNumber={{this.pageNumber}}
|
|
26
|
+
/>
|
|
27
|
+
{{/if}}
|
|
28
|
+
</div>
|
|
29
|
+
<AuToolbar
|
|
30
|
+
@border='top'
|
|
31
|
+
@size='large'
|
|
32
|
+
@nowrap={{true}}
|
|
33
|
+
@reverse={{true}}
|
|
34
|
+
>
|
|
35
|
+
<AuButtonGroup>
|
|
36
|
+
<AuButton @skin='secondary' {{on 'click' this.closeModal}}>
|
|
37
|
+
{{t 'lpdc-plugin.modal.close'}}
|
|
38
|
+
</AuButton>
|
|
39
|
+
</AuButtonGroup>
|
|
40
|
+
</AuToolbar>
|
|
41
|
+
</mc.content>
|
|
42
|
+
</AuMainContainer>
|
|
43
|
+
</modal.Body>
|
|
44
|
+
</AuModal>
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { action } from '@ember/object';
|
|
3
|
+
import { restartableTask, timeout } from 'ember-concurrency';
|
|
4
|
+
import { task as trackedTask } from 'ember-resources/util/ember-concurrency';
|
|
5
|
+
|
|
6
|
+
import { tracked } from '@glimmer/tracking';
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
fetchLpdcs,
|
|
10
|
+
LPDC,
|
|
11
|
+
type LpdcPluginConfig,
|
|
12
|
+
} from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/lpdc-plugin';
|
|
13
|
+
import { trackedReset } from 'tracked-toolbox';
|
|
14
|
+
|
|
15
|
+
interface Signature {
|
|
16
|
+
Args: {
|
|
17
|
+
config: LpdcPluginConfig;
|
|
18
|
+
onLpdcInsert: (lpdc: LPDC) => void;
|
|
19
|
+
closeModal: () => void;
|
|
20
|
+
open: boolean;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default class LpdcPluginModalComponent extends Component<Signature> {
|
|
25
|
+
// Filtering
|
|
26
|
+
@tracked searchText: string | null = null;
|
|
27
|
+
|
|
28
|
+
// Display
|
|
29
|
+
@tracked error: unknown;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Paginating the search results
|
|
33
|
+
*/
|
|
34
|
+
@trackedReset('searchText')
|
|
35
|
+
pageNumber = 0;
|
|
36
|
+
|
|
37
|
+
get config() {
|
|
38
|
+
return this.args.config;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@action
|
|
42
|
+
closeModal() {
|
|
43
|
+
this.args.closeModal();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
lpdcSearch = restartableTask(async () => {
|
|
47
|
+
await timeout(100);
|
|
48
|
+
this.error = null;
|
|
49
|
+
const abortController = new AbortController();
|
|
50
|
+
try {
|
|
51
|
+
const results = await fetchLpdcs({
|
|
52
|
+
filter: {
|
|
53
|
+
name: this.searchText ?? undefined,
|
|
54
|
+
},
|
|
55
|
+
pageNumber: this.pageNumber,
|
|
56
|
+
config: this.args.config,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
return Object.assign(results.lpdc, {
|
|
60
|
+
meta: results.meta,
|
|
61
|
+
});
|
|
62
|
+
} catch (error) {
|
|
63
|
+
this.error = error;
|
|
64
|
+
return [];
|
|
65
|
+
} finally {
|
|
66
|
+
//Abort all requests now that this task has either successfully finished or has been cancelled
|
|
67
|
+
abortController.abort();
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
lpdcResource = trackedTask(this, this.lpdcSearch, () => [
|
|
72
|
+
this.searchText,
|
|
73
|
+
this.pageNumber,
|
|
74
|
+
]);
|
|
75
|
+
|
|
76
|
+
@action onSearchTextChange(event: InputEvent): void {
|
|
77
|
+
this.searchText = (event.target as HTMLInputElement).value;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{{! @glint-nocheck: not typesafe yet }}
|
|
2
|
+
<div class='say-snippet-lists-table'>
|
|
3
|
+
{{#let
|
|
4
|
+
(t 'lpdc-plugin.table.header.name')
|
|
5
|
+
(t 'lpdc-plugin.search.placeholder')
|
|
6
|
+
(t 'lpdc-plugin.modal.insert')
|
|
7
|
+
as |name search insert|
|
|
8
|
+
}}
|
|
9
|
+
<AuDataTable
|
|
10
|
+
@content={{this.lpdc}}
|
|
11
|
+
@isLoading={{@isLoading}}
|
|
12
|
+
@noDataMessage={{t 'common.search.no-results'}}
|
|
13
|
+
@sort={{@sort}}
|
|
14
|
+
@page={{@pageNumber}}
|
|
15
|
+
@size={{25}}
|
|
16
|
+
as |t|
|
|
17
|
+
>
|
|
18
|
+
<t.menu as |menu|>
|
|
19
|
+
<menu.general>
|
|
20
|
+
<AuToolbar class='au-o-box' as |Group|>
|
|
21
|
+
<Group />
|
|
22
|
+
<Group class='au-c-toolbar__group--center'>
|
|
23
|
+
<AuDataTableTextSearch
|
|
24
|
+
@wait={{500}}
|
|
25
|
+
@filter={{@nameFilter}}
|
|
26
|
+
@placeholder={{search}}
|
|
27
|
+
/>
|
|
28
|
+
</Group>
|
|
29
|
+
</AuToolbar>
|
|
30
|
+
</menu.general>
|
|
31
|
+
</t.menu>
|
|
32
|
+
<t.content as |c|>
|
|
33
|
+
<c.header>
|
|
34
|
+
<AuDataTableThSortable
|
|
35
|
+
@field='name'
|
|
36
|
+
@label={{name}}
|
|
37
|
+
@currentSorting={{@sort}}
|
|
38
|
+
@class='data-table__header-title'
|
|
39
|
+
/>
|
|
40
|
+
<th class='snippet-list-table-select-column'>{{insert}}</th>
|
|
41
|
+
</c.header>
|
|
42
|
+
<c.body as |row|>
|
|
43
|
+
<td>{{row.name}}</td>
|
|
44
|
+
<td class='snippet-list-table-select-column'>
|
|
45
|
+
<AuButton {{on 'click' (fn @onLpdcInsert row)}}>
|
|
46
|
+
{{insert}}
|
|
47
|
+
</AuButton>
|
|
48
|
+
</td>
|
|
49
|
+
</c.body>
|
|
50
|
+
</t.content>
|
|
51
|
+
</AuDataTable>
|
|
52
|
+
{{/let}}
|
|
53
|
+
</div>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { LPDC } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/lpdc-plugin';
|
|
3
|
+
|
|
4
|
+
interface Args {
|
|
5
|
+
lpdc: LPDC[] & {
|
|
6
|
+
meta: {
|
|
7
|
+
count: number;
|
|
8
|
+
pagination: { first: { number: number }; last: { number: number } };
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
isLoading: boolean;
|
|
12
|
+
onLpdcInsert: (lpdc: LPDC) => void;
|
|
13
|
+
// Filtering
|
|
14
|
+
nameFilter: string | null;
|
|
15
|
+
// Pagination
|
|
16
|
+
pageNumber: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default class LpdcTableViewComponent extends Component<Args> {
|
|
20
|
+
get lpdc() {
|
|
21
|
+
return this.args.lpdc;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { action } from '@ember/object';
|
|
2
2
|
import Component from '@glimmer/component';
|
|
3
3
|
import { NodeSelection, SayController } from '@lblod/ember-rdfa-editor';
|
|
4
|
-
import { Address } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/variable-plugin/variables';
|
|
5
4
|
import {
|
|
5
|
+
Address,
|
|
6
6
|
AddressError,
|
|
7
7
|
fetchMunicipalities,
|
|
8
8
|
fetchStreets,
|
|
@@ -4,7 +4,7 @@ import IntlService from 'ember-intl/services/intl';
|
|
|
4
4
|
import { PencilIcon } from '@appuniversum/ember-appuniversum/components/icons/pencil';
|
|
5
5
|
|
|
6
6
|
import { PNode, SayController } from '@lblod/ember-rdfa-editor';
|
|
7
|
-
import { Address } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/variable-plugin/
|
|
7
|
+
import { Address } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/variable-plugin/utils/address-helpers';
|
|
8
8
|
import { getOutgoingTriple } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/namespace';
|
|
9
9
|
import { EXT } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/constants';
|
|
10
10
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { IBindings } from 'fetch-sparql-endpoint';
|
|
2
|
+
import { unwrap } from '../utils/option';
|
|
3
|
+
|
|
4
|
+
export default class Mandatee {
|
|
5
|
+
constructor(
|
|
6
|
+
readonly personUri: string,
|
|
7
|
+
readonly mandateeUri: string,
|
|
8
|
+
readonly firstName: string,
|
|
9
|
+
readonly lastName: string,
|
|
10
|
+
readonly fullName: string,
|
|
11
|
+
readonly status: string,
|
|
12
|
+
readonly fractie: string,
|
|
13
|
+
readonly role: string,
|
|
14
|
+
) {}
|
|
15
|
+
static fromBinding(binding: IBindings) {
|
|
16
|
+
const personUri = unwrap(binding['person']?.value);
|
|
17
|
+
const mandateeUri = unwrap(binding['mandatee']?.value);
|
|
18
|
+
const firstName = unwrap(binding['firstName']?.value);
|
|
19
|
+
const lastName = unwrap(binding['lastName']?.value);
|
|
20
|
+
const fullName = `${firstName} ${lastName}`;
|
|
21
|
+
const status = unwrap(binding['statusLabel']?.value);
|
|
22
|
+
const fractie = unwrap(binding['fractieLabel']?.value);
|
|
23
|
+
const role = unwrap(binding['roleLabel']?.value);
|
|
24
|
+
return new Mandatee(
|
|
25
|
+
personUri,
|
|
26
|
+
mandateeUri,
|
|
27
|
+
firstName,
|
|
28
|
+
lastName,
|
|
29
|
+
fullName,
|
|
30
|
+
status,
|
|
31
|
+
fractie,
|
|
32
|
+
role,
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
}
|