@lblod/ember-rdfa-editor-lblod-plugins 38.2.0 → 38.3.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 +8 -0
- package/addon/components/lmb-plugin/insert.ts +11 -5
- package/addon/components/variable-plugin/date/{date-time-picker.ts → date-picker.gts} +46 -42
- package/addon/components/variable-plugin/date/date-time-picker.gts +42 -0
- package/addon/components/variable-plugin/date/{edit.ts → edit.gts} +176 -11
- package/addon/components/variable-plugin/date/floating-date-container.gts +54 -0
- package/addon/components/variable-plugin/date/time-picker.gts +61 -0
- package/addon/components/variable-plugin/person/edit.ts +15 -41
- package/addon/plugins/lmb-plugin/index.ts +84 -0
- package/addon/plugins/location-plugin/contextual-actions/index.ts +11 -5
- package/addon/plugins/location-plugin/utils/replace-location.ts +2 -30
- package/addon/plugins/variable-plugin/contextual-actions/person.ts +140 -0
- package/addon/plugins/variable-plugin/utils/replace-person.ts +64 -0
- package/addon/plugins/variable-plugin/variables/person.ts +30 -1
- package/addon/{plugins/location-plugin/utils/get-document-locations.ts → utils/get-ranked-pnodes.ts} +34 -34
- package/addon/utils/move-node-selection-forward.ts +27 -0
- package/app/styles/variable-plugin.scss +10 -0
- package/declarations/addon/components/lmb-plugin/insert.d.ts +1 -1
- package/declarations/addon/components/variable-plugin/date/date-picker.d.ts +44 -0
- package/declarations/addon/components/variable-plugin/date/date-time-picker.d.ts +11 -27
- package/declarations/addon/components/variable-plugin/date/edit.d.ts +15 -12
- package/declarations/addon/components/variable-plugin/date/floating-date-container.d.ts +21 -0
- package/declarations/addon/components/variable-plugin/date/time-picker.d.ts +22 -0
- package/declarations/addon/components/variable-plugin/person/edit.d.ts +3 -6
- package/declarations/addon/plugins/lmb-plugin/index.d.ts +11 -0
- package/declarations/addon/plugins/location-plugin/contextual-actions/index.d.ts +2 -7
- package/declarations/addon/plugins/variable-plugin/contextual-actions/person.d.ts +4 -0
- package/declarations/addon/plugins/variable-plugin/utils/replace-person.d.ts +5 -0
- package/declarations/addon/plugins/variable-plugin/variables/person.d.ts +4 -0
- package/declarations/addon/utils/get-ranked-pnodes.d.ts +6 -0
- package/declarations/addon/utils/move-node-selection-forward.d.ts +2 -0
- package/package.json +2 -2
- package/translations/en-US.yaml +4 -0
- package/translations/nl-BE.yaml +6 -0
- package/addon/components/variable-plugin/date/date-time-picker.hbs +0 -26
- package/addon/components/variable-plugin/date/edit.hbs +0 -113
- package/declarations/addon/plugins/location-plugin/utils/get-document-locations.d.ts +0 -4
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { SayController } from '@lblod/ember-rdfa-editor';
|
|
2
2
|
import { BestuursperiodeLabel } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/constants';
|
|
3
3
|
import { Person } from '../variable-plugin/variables';
|
|
4
|
+
import {
|
|
5
|
+
ProsePlugin,
|
|
6
|
+
PluginKey,
|
|
7
|
+
EditorState,
|
|
8
|
+
EditorView,
|
|
9
|
+
Command,
|
|
10
|
+
} from '@lblod/ember-rdfa-editor';
|
|
4
11
|
|
|
5
12
|
export type LmbPluginConfig = {
|
|
6
13
|
endpoint: string;
|
|
@@ -21,3 +28,80 @@ export function createPersonNode(controller: SayController, person: Person) {
|
|
|
21
28
|
);
|
|
22
29
|
return electeeNode;
|
|
23
30
|
}
|
|
31
|
+
|
|
32
|
+
type PluginState = {
|
|
33
|
+
modalOpen: boolean;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
type LmbModalMeta =
|
|
37
|
+
| { action: 'open_lmb_modal' }
|
|
38
|
+
| { action: 'close_lmb_modal' }
|
|
39
|
+
| undefined;
|
|
40
|
+
|
|
41
|
+
function isLmbModalMeta(meta: unknown): meta is LmbModalMeta {
|
|
42
|
+
if (!meta || typeof meta !== 'object') return false;
|
|
43
|
+
return 'action' in meta;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const lmbModalsPluginKey = new PluginKey<PluginState>(
|
|
47
|
+
'LMB_MODALS_PLUGIN',
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
export function closeLmbModal(view: EditorView) {
|
|
51
|
+
const tr = view.state.tr;
|
|
52
|
+
tr.setMeta(lmbModalsPluginKey, { action: 'close_lmb_modal' });
|
|
53
|
+
view.dispatch(tr);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function openLmbModal(view: EditorView) {
|
|
57
|
+
const tr = view.state.tr;
|
|
58
|
+
tr.setMeta(lmbModalsPluginKey, {
|
|
59
|
+
action: 'open_lmb_modal',
|
|
60
|
+
});
|
|
61
|
+
view.dispatch(tr);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function openLmbModalCommand(): Command {
|
|
65
|
+
return function (state, dispatch) {
|
|
66
|
+
if (!dispatch) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
const tr = state.tr;
|
|
70
|
+
tr.setMeta(lmbModalsPluginKey, {
|
|
71
|
+
action: 'open_lmb_modal',
|
|
72
|
+
});
|
|
73
|
+
dispatch(tr);
|
|
74
|
+
return true;
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function lmbModalsPlugin() {
|
|
79
|
+
return new ProsePlugin<PluginState>({
|
|
80
|
+
key: lmbModalsPluginKey,
|
|
81
|
+
state: {
|
|
82
|
+
init() {
|
|
83
|
+
return { modalOpen: false };
|
|
84
|
+
},
|
|
85
|
+
apply(tr, pluginState) {
|
|
86
|
+
const meta = tr.getMeta(lmbModalsPluginKey);
|
|
87
|
+
if (!isLmbModalMeta(meta)) return pluginState;
|
|
88
|
+
|
|
89
|
+
if (meta?.action === 'open_lmb_modal') {
|
|
90
|
+
return {
|
|
91
|
+
modalOpen: true,
|
|
92
|
+
};
|
|
93
|
+
} else if (meta?.action === 'close_lmb_modal') {
|
|
94
|
+
return { modalOpen: false };
|
|
95
|
+
} else {
|
|
96
|
+
return pluginState;
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function getLmbModalsPluginState(
|
|
104
|
+
state: EditorState,
|
|
105
|
+
): PluginState | undefined {
|
|
106
|
+
return lmbModalsPluginKey.getState(state);
|
|
107
|
+
}
|
|
@@ -3,12 +3,15 @@ import { v4 as uuidv4 } from 'uuid';
|
|
|
3
3
|
import { getTranslationFunction } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/translation';
|
|
4
4
|
import { openLocationModalCommand } from '..';
|
|
5
5
|
import { LocationType } from '@lblod/ember-rdfa-editor-lblod-plugins/components/location-plugin/map';
|
|
6
|
-
import
|
|
6
|
+
import { getRankedPNodes } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/get-ranked-pnodes';
|
|
7
7
|
import { replaceLocationCommand } from '../utils/replace-location';
|
|
8
8
|
import { Area, Place } from '../utils/geo-helpers';
|
|
9
9
|
import { Address } from '../utils/address-helpers';
|
|
10
10
|
import { getLocationUri } from '../_private/utils/location-helpers';
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
ContextualAction,
|
|
13
|
+
ContextualActionGroup,
|
|
14
|
+
} from '@lblod/ember-rdfa-editor/plugins/contextual-actions';
|
|
12
15
|
|
|
13
16
|
const otherElementsGroupId =
|
|
14
17
|
'other-elements-e01f46a0-b323-4add-8035-d81dc2e8578d';
|
|
@@ -29,14 +32,17 @@ function getLocationSuggestionOptions(state: EditorState) {
|
|
|
29
32
|
| Area
|
|
30
33
|
| undefined;
|
|
31
34
|
|
|
32
|
-
return
|
|
35
|
+
return getRankedPNodes(state, 'oslo_location', (node) =>
|
|
36
|
+
getLocationUri(node.attrs.value),
|
|
37
|
+
)
|
|
38
|
+
.map((rankedNode) => rankedNode.node.value.attrs.value)
|
|
33
39
|
.filter(
|
|
34
40
|
(location) =>
|
|
35
41
|
!selectedLocation ||
|
|
36
42
|
getLocationUri(selectedLocation) !== getLocationUri(location),
|
|
37
43
|
)
|
|
38
44
|
.slice(0, SUGGESTION_AMOUNT)
|
|
39
|
-
.map((location) => ({
|
|
45
|
+
.map((location: Address | Area | Place) => ({
|
|
40
46
|
label: location.formatted,
|
|
41
47
|
id: uuidv4(),
|
|
42
48
|
group: recentLocationsGroupId,
|
|
@@ -87,7 +93,7 @@ function getOtherElementsOptions(state: EditorState) {
|
|
|
87
93
|
|
|
88
94
|
export function getContextualActions(type: 'suggestions' | 'other_elements') {
|
|
89
95
|
return function (state: EditorState, searchQuery?: string) {
|
|
90
|
-
const options =
|
|
96
|
+
const options: ContextualAction[] =
|
|
91
97
|
type === 'suggestions'
|
|
92
98
|
? getLocationSuggestionOptions(state)
|
|
93
99
|
: getOtherElementsOptions(state);
|
|
@@ -1,41 +1,13 @@
|
|
|
1
1
|
import { ResolvedPNode } from '@lblod/ember-rdfa-editor/utils/_private/types';
|
|
2
2
|
import { Address } from './address-helpers';
|
|
3
3
|
import { Area, Place } from './geo-helpers';
|
|
4
|
-
import {
|
|
5
|
-
EditorState,
|
|
6
|
-
Transaction,
|
|
7
|
-
NodeSelection,
|
|
8
|
-
TextSelection,
|
|
9
|
-
PNode,
|
|
10
|
-
Selection,
|
|
11
|
-
Command,
|
|
12
|
-
} from '@lblod/ember-rdfa-editor';
|
|
4
|
+
import { EditorState, Transaction, Command } from '@lblod/ember-rdfa-editor';
|
|
13
5
|
import type { FullTriple } from '@lblod/ember-rdfa-editor/core/rdfa-processor';
|
|
14
6
|
import { PROV } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/constants';
|
|
15
7
|
import { SayDataFactory } from '@lblod/ember-rdfa-editor/core/say-data-factory';
|
|
16
8
|
import { transactionCombinator } from '@lblod/ember-rdfa-editor/utils/transaction-utils';
|
|
17
9
|
import { updateSubject } from '@lblod/ember-rdfa-editor/plugins/rdfa-info/utils';
|
|
18
|
-
|
|
19
|
-
function moveNodeSelectionForward(selection: Selection, doc: PNode) {
|
|
20
|
-
if (!(selection instanceof NodeSelection)) {
|
|
21
|
-
return selection;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const $from = selection.$from;
|
|
25
|
-
|
|
26
|
-
const index = $from.index();
|
|
27
|
-
const parent = $from.parent;
|
|
28
|
-
|
|
29
|
-
if (index + 1 < parent.childCount) {
|
|
30
|
-
const nextPos = selection.from + selection.node.nodeSize;
|
|
31
|
-
|
|
32
|
-
return NodeSelection.create(doc, nextPos);
|
|
33
|
-
} else {
|
|
34
|
-
const posAfter = selection.to;
|
|
35
|
-
|
|
36
|
-
return TextSelection.create(doc, posAfter);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
10
|
+
import { moveNodeSelectionForward } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/move-node-selection-forward';
|
|
39
11
|
|
|
40
12
|
export function replaceLocationCommand(
|
|
41
13
|
node: ResolvedPNode,
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { EditorState, NodeSelection } from '@lblod/ember-rdfa-editor';
|
|
2
|
+
import { getTranslationFunction } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/translation';
|
|
3
|
+
import { getRankedPNodes } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/get-ranked-pnodes';
|
|
4
|
+
import { ContextualActionGroup } from '@lblod/ember-rdfa-editor/plugins/contextual-actions';
|
|
5
|
+
import { getPersonFromPNode } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/variable-plugin/variables/person';
|
|
6
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
7
|
+
import { replacePersonCommand } from '../utils/replace-person';
|
|
8
|
+
import { ResolvedPNode } from '@lblod/ember-rdfa-editor/utils/_private/types';
|
|
9
|
+
import { type ContextualAction } from '@lblod/ember-rdfa-editor/plugins/contextual-actions/index';
|
|
10
|
+
import { LmbPluginConfig, openLmbModalCommand } from '../../lmb-plugin';
|
|
11
|
+
import { fetchElectees } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/lmb-plugin/utils/fetchElectees';
|
|
12
|
+
import { BESTUURSPERIODES } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/constants';
|
|
13
|
+
|
|
14
|
+
const PERSON_SUGGESTIONS_GROUP_ID =
|
|
15
|
+
'person-suggestions-9cc92bb6-de78-41cf-824c-ed391b206764';
|
|
16
|
+
|
|
17
|
+
const OTHER_ELEMENTS_GROUP_ID =
|
|
18
|
+
'person-other-elements-5c66b28f-22ff-4f0a-bd24-4f90cdc5a64a';
|
|
19
|
+
|
|
20
|
+
const ASYNC_SEARCH_GROUP_ID =
|
|
21
|
+
'person-async-search-5545e1fa-aa23-4a77-8c5d-b97481d58fc4';
|
|
22
|
+
|
|
23
|
+
const SUGGESTION_AMOUNT = 15;
|
|
24
|
+
const SEARCH_PAGE_SIZE = 20;
|
|
25
|
+
|
|
26
|
+
function getOtherElementsActions(state: EditorState) {
|
|
27
|
+
const translate = getTranslationFunction(state);
|
|
28
|
+
return [
|
|
29
|
+
{
|
|
30
|
+
label: translate(
|
|
31
|
+
'variable-plugin.person.advanced-search',
|
|
32
|
+
'Geavanceerd zoeken',
|
|
33
|
+
),
|
|
34
|
+
id: uuidv4(),
|
|
35
|
+
group: OTHER_ELEMENTS_GROUP_ID,
|
|
36
|
+
command: openLmbModalCommand(),
|
|
37
|
+
icon: 'search',
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function getSuggestionsActions(state: EditorState) {
|
|
43
|
+
const selectedNode = getSelectedPersonNode(state);
|
|
44
|
+
if (!selectedNode) return [];
|
|
45
|
+
return getRankedPNodes(state, 'person_variable', (node) => node.attrs.subject)
|
|
46
|
+
.map((rankedNode) => rankedNode.node)
|
|
47
|
+
.filter(
|
|
48
|
+
(node) => selectedNode.value.attrs.subject !== node.value.attrs.subject,
|
|
49
|
+
)
|
|
50
|
+
.slice(0, SUGGESTION_AMOUNT)
|
|
51
|
+
.flatMap((node) => {
|
|
52
|
+
const person = getPersonFromPNode(node.value);
|
|
53
|
+
if (!person) return [];
|
|
54
|
+
return [
|
|
55
|
+
{
|
|
56
|
+
label: person.fullName,
|
|
57
|
+
id: uuidv4(),
|
|
58
|
+
group: PERSON_SUGGESTIONS_GROUP_ID,
|
|
59
|
+
command: replacePersonCommand(selectedNode, person),
|
|
60
|
+
},
|
|
61
|
+
];
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function getAsyncSearchActionsGetter(args: LmbPluginConfig) {
|
|
66
|
+
return async function getAsyncSearchActions(
|
|
67
|
+
state: EditorState,
|
|
68
|
+
searchQuery?: string,
|
|
69
|
+
) {
|
|
70
|
+
const selectedNode = getSelectedPersonNode(state);
|
|
71
|
+
if (!searchQuery || !selectedNode) return [];
|
|
72
|
+
|
|
73
|
+
const persons = await fetchElectees({
|
|
74
|
+
endpoint: args.endpoint,
|
|
75
|
+
page: 0,
|
|
76
|
+
pageSize: SEARCH_PAGE_SIZE,
|
|
77
|
+
searchString: searchQuery,
|
|
78
|
+
adminUnitSearch: args.defaultAdminUnit ?? '',
|
|
79
|
+
sort: false,
|
|
80
|
+
period:
|
|
81
|
+
args.defaultPeriod ?? Object.values(BESTUURSPERIODES).at(-1) ?? '',
|
|
82
|
+
});
|
|
83
|
+
return persons.electees.map((person) => ({
|
|
84
|
+
label: person.fullName,
|
|
85
|
+
id: uuidv4(),
|
|
86
|
+
group: ASYNC_SEARCH_GROUP_ID,
|
|
87
|
+
command: replacePersonCommand(selectedNode, person),
|
|
88
|
+
}));
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function makeSearchable(
|
|
93
|
+
actionGetter: (state: EditorState) => ContextualAction[],
|
|
94
|
+
) {
|
|
95
|
+
return function (state: EditorState, searchQuery?: string) {
|
|
96
|
+
return actionGetter(state).filter(
|
|
97
|
+
(option) =>
|
|
98
|
+
!searchQuery ||
|
|
99
|
+
option.label.toLocaleLowerCase().includes(searchQuery.toLowerCase()),
|
|
100
|
+
);
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function getSelectedPersonNode(state: EditorState): ResolvedPNode | null {
|
|
105
|
+
const { selection } = state;
|
|
106
|
+
return selection instanceof NodeSelection &&
|
|
107
|
+
selection.node.type === selection.node.type.schema.nodes['person_variable']
|
|
108
|
+
? { value: selection.node, pos: selection.from }
|
|
109
|
+
: null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function getPersonActionGroups(args: LmbPluginConfig) {
|
|
113
|
+
return function (state: EditorState): ContextualActionGroup[] {
|
|
114
|
+
const selectedNode = getSelectedPersonNode(state);
|
|
115
|
+
if (!selectedNode) return [];
|
|
116
|
+
const t = getTranslationFunction(state);
|
|
117
|
+
return [
|
|
118
|
+
{
|
|
119
|
+
id: PERSON_SUGGESTIONS_GROUP_ID,
|
|
120
|
+
label: t('variable-plugin.person.suggestions', 'Suggesties'),
|
|
121
|
+
getActions: makeSearchable(getSuggestionsActions),
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
id: OTHER_ELEMENTS_GROUP_ID,
|
|
125
|
+
getActions: getOtherElementsActions,
|
|
126
|
+
sticky: 'bottom',
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
id: ASYNC_SEARCH_GROUP_ID,
|
|
130
|
+
priority: 10,
|
|
131
|
+
getActions: getAsyncSearchActionsGetter(args),
|
|
132
|
+
searchDebounceMs: 300,
|
|
133
|
+
loadingMessage: t(
|
|
134
|
+
'variable-plugin.person.searching',
|
|
135
|
+
'Aan het zoeken…',
|
|
136
|
+
),
|
|
137
|
+
},
|
|
138
|
+
];
|
|
139
|
+
};
|
|
140
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { ResolvedPNode } from '@lblod/ember-rdfa-editor/utils/_private/types';
|
|
2
|
+
import { EditorState, Transaction, Command } from '@lblod/ember-rdfa-editor';
|
|
3
|
+
import { transactionCombinator } from '@lblod/ember-rdfa-editor/utils/transaction-utils';
|
|
4
|
+
import {
|
|
5
|
+
addPropertyToNode,
|
|
6
|
+
updateSubject,
|
|
7
|
+
} from '@lblod/ember-rdfa-editor/plugins/rdfa-info/utils';
|
|
8
|
+
import { FOAF } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/constants';
|
|
9
|
+
import { sayDataFactory } from '@lblod/ember-rdfa-editor/core/say-data-factory';
|
|
10
|
+
import { moveNodeSelectionForward } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/move-node-selection-forward';
|
|
11
|
+
import { Person } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/variable-plugin/variables/person';
|
|
12
|
+
|
|
13
|
+
export function getReplacePersonTransaction(
|
|
14
|
+
state: EditorState,
|
|
15
|
+
personNode: ResolvedPNode,
|
|
16
|
+
newPerson: Person,
|
|
17
|
+
) {
|
|
18
|
+
return transactionCombinator(state)([
|
|
19
|
+
updateSubject({
|
|
20
|
+
pos: personNode.pos,
|
|
21
|
+
targetSubject: newPerson.uri,
|
|
22
|
+
keepBacklinks: true,
|
|
23
|
+
keepProperties: false,
|
|
24
|
+
keepExternalTriples: true,
|
|
25
|
+
}),
|
|
26
|
+
addPropertyToNode({
|
|
27
|
+
resource: newPerson.uri,
|
|
28
|
+
property: {
|
|
29
|
+
predicate: FOAF('givenName').full,
|
|
30
|
+
object: sayDataFactory.literal(newPerson.firstName),
|
|
31
|
+
},
|
|
32
|
+
}),
|
|
33
|
+
addPropertyToNode({
|
|
34
|
+
resource: newPerson.uri,
|
|
35
|
+
property: {
|
|
36
|
+
predicate: FOAF('familyName').full,
|
|
37
|
+
object: sayDataFactory.literal(newPerson.lastName),
|
|
38
|
+
},
|
|
39
|
+
}),
|
|
40
|
+
]);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function replacePersonCommand(
|
|
44
|
+
node: ResolvedPNode,
|
|
45
|
+
newPerson: Person,
|
|
46
|
+
): Command {
|
|
47
|
+
return function (state: EditorState, dispatch?: (tr: Transaction) => void) {
|
|
48
|
+
const { transaction, result } = getReplacePersonTransaction(
|
|
49
|
+
state,
|
|
50
|
+
node,
|
|
51
|
+
newPerson,
|
|
52
|
+
);
|
|
53
|
+
if (dispatch) {
|
|
54
|
+
const newSelection = moveNodeSelectionForward(
|
|
55
|
+
state.selection.map(transaction.doc, transaction.mapping),
|
|
56
|
+
transaction.doc,
|
|
57
|
+
);
|
|
58
|
+
transaction.setSelection(newSelection);
|
|
59
|
+
dispatch(transaction);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return result.every((res) => res);
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -24,7 +24,10 @@ import {
|
|
|
24
24
|
getOutgoingTriple,
|
|
25
25
|
hasOutgoingNamedNodeTriple,
|
|
26
26
|
} from '@lblod/ember-rdfa-editor-lblod-plugins/utils/namespace';
|
|
27
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
isRdfaAttrs,
|
|
29
|
+
renderRdfaAware,
|
|
30
|
+
} from '@lblod/ember-rdfa-editor/core/schema';
|
|
28
31
|
import { getTranslationFunction } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/translation';
|
|
29
32
|
import { createPersonVariableAttrs } from '../actions/create-person-variable';
|
|
30
33
|
|
|
@@ -156,6 +159,32 @@ const serialize = (node: PNode, state: EditorState): DOMOutputSpec => {
|
|
|
156
159
|
});
|
|
157
160
|
};
|
|
158
161
|
|
|
162
|
+
export function getPersonFromPNode(
|
|
163
|
+
node: PNode,
|
|
164
|
+
): (Person & { fullName: string }) | null {
|
|
165
|
+
if (
|
|
166
|
+
node.type !== node.type.schema.nodes['person_variable'] ||
|
|
167
|
+
!isRdfaAttrs(node.attrs) ||
|
|
168
|
+
node.attrs.rdfaNodeType !== 'resource'
|
|
169
|
+
)
|
|
170
|
+
return null;
|
|
171
|
+
|
|
172
|
+
const { subject, properties } = node.attrs;
|
|
173
|
+
const firstName = properties.find((property) =>
|
|
174
|
+
FOAF('givenName').matches(property.predicate),
|
|
175
|
+
)?.object.value;
|
|
176
|
+
const lastName = properties.find((property) =>
|
|
177
|
+
FOAF('familyName').matches(property.predicate),
|
|
178
|
+
)?.object.value;
|
|
179
|
+
const fullName = firstName || lastName ? [firstName, lastName].join(' ') : '';
|
|
180
|
+
return {
|
|
181
|
+
uri: subject,
|
|
182
|
+
firstName: firstName ?? '',
|
|
183
|
+
lastName: lastName ?? '',
|
|
184
|
+
fullName,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
159
188
|
const emberNodeConfig: EmberNodeConfig = {
|
|
160
189
|
name: 'person-variable',
|
|
161
190
|
component: PersonNodeViewComponent as unknown as ComponentLike,
|
package/addon/{plugins/location-plugin/utils/get-document-locations.ts → utils/get-ranked-pnodes.ts}
RENAMED
|
@@ -1,18 +1,11 @@
|
|
|
1
|
-
import { EditorState } from '@lblod/ember-rdfa-editor';
|
|
2
|
-
import {
|
|
3
|
-
import { Address } from './address-helpers';
|
|
4
|
-
import { getLocationUri } from '../_private/utils/location-helpers';
|
|
1
|
+
import { EditorState, type PNode } from '@lblod/ember-rdfa-editor';
|
|
2
|
+
import { ResolvedPNode } from '@lblod/ember-rdfa-editor/utils/_private/types';
|
|
5
3
|
|
|
6
|
-
type
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
type LocationMetadataType = {
|
|
12
|
-
[locationUri: string]: {
|
|
4
|
+
type NodeMetadataType = {
|
|
5
|
+
[uri: string]: {
|
|
6
|
+
node: ResolvedPNode;
|
|
13
7
|
occurrences: number;
|
|
14
8
|
distance: number;
|
|
15
|
-
location: Address | Place | Area;
|
|
16
9
|
};
|
|
17
10
|
};
|
|
18
11
|
|
|
@@ -50,60 +43,67 @@ function getSuggestionScore(
|
|
|
50
43
|
return score;
|
|
51
44
|
}
|
|
52
45
|
|
|
53
|
-
export
|
|
46
|
+
export function getRankedPNodes(
|
|
47
|
+
state: EditorState,
|
|
48
|
+
nodeType: string,
|
|
49
|
+
getUri: (node: PNode) => string,
|
|
50
|
+
): {
|
|
51
|
+
node: ResolvedPNode;
|
|
52
|
+
score: number;
|
|
53
|
+
}[] {
|
|
54
54
|
const doc = state.doc;
|
|
55
|
-
const
|
|
55
|
+
const nodesWithDistance: { node: ResolvedPNode; distance: number }[] = [];
|
|
56
56
|
const selection = state.selection;
|
|
57
57
|
doc.descendants((node, pos) => {
|
|
58
|
-
if (node.type.name ===
|
|
58
|
+
if (node.type.name === nodeType) {
|
|
59
59
|
const distance = Math.abs(pos - selection.from);
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
nodesWithDistance.push({
|
|
61
|
+
node: { value: node, pos },
|
|
62
62
|
distance: distance,
|
|
63
63
|
});
|
|
64
64
|
return false;
|
|
65
65
|
}
|
|
66
66
|
return true;
|
|
67
67
|
});
|
|
68
|
-
const
|
|
69
|
-
for (const
|
|
70
|
-
const {
|
|
71
|
-
|
|
68
|
+
const nodeMetadata: NodeMetadataType = {};
|
|
69
|
+
for (const nodeWithDistance of nodesWithDistance) {
|
|
70
|
+
const { node, distance } = nodeWithDistance;
|
|
71
|
+
const uri = getUri(node.value);
|
|
72
|
+
if (!uri) {
|
|
72
73
|
continue;
|
|
73
74
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
location,
|
|
75
|
+
if (!nodeMetadata[uri]) {
|
|
76
|
+
nodeMetadata[uri] = {
|
|
77
|
+
node,
|
|
78
78
|
occurrences: 1,
|
|
79
79
|
distance,
|
|
80
80
|
};
|
|
81
81
|
} else {
|
|
82
|
-
|
|
83
|
-
if (distance <
|
|
84
|
-
|
|
82
|
+
nodeMetadata[uri].occurrences++;
|
|
83
|
+
if (distance < nodeMetadata[uri].distance) {
|
|
84
|
+
nodeMetadata[uri].distance = distance;
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
const maxOccurence = Object.values(
|
|
89
|
+
const maxOccurence = Object.values(nodeMetadata).reduce(
|
|
90
90
|
(acc, { occurrences: ocurrences }) =>
|
|
91
91
|
acc >= ocurrences ? acc : ocurrences,
|
|
92
92
|
1,
|
|
93
93
|
);
|
|
94
94
|
|
|
95
|
-
const
|
|
96
|
-
({
|
|
97
|
-
|
|
95
|
+
const scoredNodes = Object.values(nodeMetadata).map(
|
|
96
|
+
({ node, occurrences, distance }) => ({
|
|
97
|
+
node,
|
|
98
98
|
score: getSuggestionScore(occurrences, maxOccurence, distance),
|
|
99
99
|
occurrences,
|
|
100
100
|
distance,
|
|
101
101
|
}),
|
|
102
102
|
);
|
|
103
103
|
|
|
104
|
-
|
|
104
|
+
scoredNodes.sort(({ score: scoreA }, { score: scoreB }) => {
|
|
105
105
|
return scoreB - scoreA;
|
|
106
106
|
});
|
|
107
107
|
|
|
108
|
-
return
|
|
108
|
+
return scoredNodes;
|
|
109
109
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Selection,
|
|
3
|
+
type PNode,
|
|
4
|
+
NodeSelection,
|
|
5
|
+
TextSelection,
|
|
6
|
+
} from '@lblod/ember-rdfa-editor';
|
|
7
|
+
|
|
8
|
+
export function moveNodeSelectionForward(selection: Selection, doc: PNode) {
|
|
9
|
+
if (!(selection instanceof NodeSelection)) {
|
|
10
|
+
return selection;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const $from = selection.$from;
|
|
14
|
+
|
|
15
|
+
const index = $from.index();
|
|
16
|
+
const parent = $from.parent;
|
|
17
|
+
|
|
18
|
+
if (index + 1 < parent.childCount) {
|
|
19
|
+
const nextPos = selection.from + selection.node.nodeSize;
|
|
20
|
+
|
|
21
|
+
return NodeSelection.create(doc, nextPos);
|
|
22
|
+
} else {
|
|
23
|
+
const posAfter = selection.to;
|
|
24
|
+
|
|
25
|
+
return TextSelection.create(doc, posAfter);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -172,3 +172,13 @@
|
|
|
172
172
|
background-color: var(--au-orange-300);
|
|
173
173
|
font-style: italic;
|
|
174
174
|
}
|
|
175
|
+
|
|
176
|
+
#say-date-edit-info-modal-button {
|
|
177
|
+
border: 0.1rem solid var(--au-gray-300);
|
|
178
|
+
border-top-left-radius: 0;
|
|
179
|
+
border-bottom-left-radius: 0;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
#say-date-edit-scrollable-part {
|
|
183
|
+
overflow-y: auto;
|
|
184
|
+
}
|
|
@@ -11,7 +11,7 @@ interface Args {
|
|
|
11
11
|
export default class LmbPluginInsertComponent extends Component<Args> {
|
|
12
12
|
intl: IntlService;
|
|
13
13
|
AddIcon: import("@ember/component/template-only").TOC<import("@appuniversum/ember-appuniversum/components/icons/add").AddIconSignature>;
|
|
14
|
-
showModal: boolean;
|
|
14
|
+
get showModal(): boolean | undefined;
|
|
15
15
|
get controller(): SayController;
|
|
16
16
|
openModal(): void;
|
|
17
17
|
closeModal(): void;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import Intl from 'ember-intl/services/intl';
|
|
3
|
+
type Sig = {
|
|
4
|
+
Args: {
|
|
5
|
+
value?: Date | null;
|
|
6
|
+
onChange: (date: Date) => void;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
export default class DatePickerComponent extends Component<Sig> {
|
|
10
|
+
intl: Intl;
|
|
11
|
+
date?: Date;
|
|
12
|
+
get datePickerLocalization(): {
|
|
13
|
+
buttonLabel: string;
|
|
14
|
+
selectedDateMessage: string;
|
|
15
|
+
prevMonthLabel: string;
|
|
16
|
+
nextMonthLabel: string;
|
|
17
|
+
monthSelectLabel: string;
|
|
18
|
+
yearSelectLabel: string;
|
|
19
|
+
closeLabel: string;
|
|
20
|
+
calendarHeading: string;
|
|
21
|
+
dayNames: DayNames;
|
|
22
|
+
monthNames: MonthNames;
|
|
23
|
+
monthNamesShort: MonthNames;
|
|
24
|
+
placeholder: string;
|
|
25
|
+
locale: string;
|
|
26
|
+
};
|
|
27
|
+
onChangeDate(_isoDate: unknown | null, date: Date | null): void;
|
|
28
|
+
}
|
|
29
|
+
type MonthNames = [
|
|
30
|
+
string,
|
|
31
|
+
string,
|
|
32
|
+
string,
|
|
33
|
+
string,
|
|
34
|
+
string,
|
|
35
|
+
string,
|
|
36
|
+
string,
|
|
37
|
+
string,
|
|
38
|
+
string,
|
|
39
|
+
string,
|
|
40
|
+
string,
|
|
41
|
+
string
|
|
42
|
+
];
|
|
43
|
+
type DayNames = [string, string, string, string, string, string, string];
|
|
44
|
+
export {};
|