profile-pane 3.2.1 → 3.2.2-test.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/README.md +50 -0
- package/lib/303.profile-pane.js +1362 -0
- package/lib/303.profile-pane.js.map +1 -0
- package/lib/303.profile-pane.min.js +2 -0
- package/lib/303.profile-pane.min.js.map +1 -0
- package/lib/ProfileView.css +1090 -0
- package/lib/ProfileView.d.ts +2 -1
- package/lib/ProfileView.d.ts.map +1 -1
- package/lib/ProfileView.js +64 -36
- package/lib/buttonsHelper.d.ts +1 -1
- package/lib/buttonsHelper.d.ts.map +1 -1
- package/lib/buttonsHelper.js +2 -1
- package/lib/editProfilePane/EditCVCard.js +1 -1
- package/lib/editProfilePane/EditCommunitiesCard.js +1 -1
- package/lib/editProfilePane/EditFriendsCard.js +1 -1
- package/lib/editProfilePane/EditProfileView.d.ts +1 -1
- package/lib/editProfilePane/EditProfileView.d.ts.map +1 -1
- package/lib/editProfilePane/EditProfileView.js +4 -5
- package/lib/editProfilePane/editProfilePresenter.d.ts.map +1 -1
- package/lib/editProfilePane/editProfilePresenter.js +5 -4
- package/lib/icons-svg/profileIcons.d.ts +1 -1
- package/lib/icons-svg/profileIcons.d.ts.map +1 -1
- package/lib/icons-svg/profileIcons.js +9 -17
- package/lib/index.d.ts +1 -8
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +74 -40
- package/lib/ontology/otherPreferencesForm.ttl +32 -0
- package/lib/ontology/resumeForm.ttl +349 -0
- package/lib/ontology/socialMedia.ttl +433 -0
- package/lib/profile-pane.js +32266 -13247
- package/lib/profile-pane.js.map +1 -1
- package/lib/profile-pane.min.js +2315 -935
- package/lib/profile-pane.min.js.map +1 -1
- package/lib/rdfFormsHelper.d.ts +13 -1
- package/lib/rdfFormsHelper.d.ts.map +1 -1
- package/lib/rdfFormsHelper.js +13 -1
- package/lib/sections/bio/BioEditDialog.d.ts.map +1 -1
- package/lib/sections/bio/BioEditDialog.js +7 -7
- package/lib/sections/bio/BioSection.css +300 -0
- package/lib/sections/bio/BioSection.d.ts +3 -2
- package/lib/sections/bio/BioSection.d.ts.map +1 -1
- package/lib/sections/bio/BioSection.js +26 -19
- package/lib/sections/bio/mutations.d.ts.map +1 -1
- package/lib/sections/bio/mutations.js +14 -3
- package/lib/sections/contactInfo/ContactInfoEditDialog.css +354 -0
- package/lib/sections/contactInfo/ContactInfoEditDialog.d.ts +3 -1
- package/lib/sections/contactInfo/ContactInfoEditDialog.d.ts.map +1 -1
- package/lib/sections/contactInfo/ContactInfoEditDialog.js +183 -98
- package/lib/sections/contactInfo/ContactInfoSection.css +125 -0
- package/lib/sections/contactInfo/ContactInfoSection.d.ts +2 -0
- package/lib/sections/contactInfo/ContactInfoSection.d.ts.map +1 -1
- package/lib/sections/contactInfo/ContactInfoSection.js +64 -41
- package/lib/sections/contactInfo/mutations.d.ts.map +1 -1
- package/lib/sections/contactInfo/mutations.js +51 -16
- package/lib/sections/education/EducationEditDialog.d.ts +3 -1
- package/lib/sections/education/EducationEditDialog.d.ts.map +1 -1
- package/lib/sections/education/EducationEditDialog.js +170 -92
- package/lib/sections/education/EducationSection.css +133 -0
- package/lib/sections/education/EducationSection.d.ts +3 -2
- package/lib/sections/education/EducationSection.d.ts.map +1 -1
- package/lib/sections/education/EducationSection.js +32 -25
- package/lib/sections/education/mutations.d.ts.map +1 -1
- package/lib/sections/education/mutations.js +14 -3
- package/lib/sections/heading/HeadingEditDialog.d.ts +4 -1
- package/lib/sections/heading/HeadingEditDialog.d.ts.map +1 -1
- package/lib/sections/heading/HeadingEditDialog.js +287 -162
- package/lib/sections/heading/HeadingSection.css +862 -0
- package/lib/sections/heading/HeadingSection.d.ts +3 -2
- package/lib/sections/heading/HeadingSection.d.ts.map +1 -1
- package/lib/sections/heading/HeadingSection.js +63 -32
- package/lib/sections/heading/imageHelpers.d.ts +1 -0
- package/lib/sections/heading/imageHelpers.d.ts.map +1 -1
- package/lib/sections/heading/imageHelpers.js +40 -1
- package/lib/sections/heading/mutations.d.ts.map +1 -1
- package/lib/sections/heading/mutations.js +86 -23
- package/lib/sections/heading/selectors.d.ts.map +1 -1
- package/lib/sections/heading/selectors.js +14 -3
- package/lib/sections/heading/types.d.ts +1 -2
- package/lib/sections/heading/types.d.ts.map +1 -1
- package/lib/sections/languages/LanguageEditDialog.d.ts +3 -1
- package/lib/sections/languages/LanguageEditDialog.d.ts.map +1 -1
- package/lib/sections/languages/LanguageEditDialog.js +202 -119
- package/lib/sections/languages/LanguageSection.css +53 -0
- package/lib/sections/languages/LanguageSection.d.ts +2 -0
- package/lib/sections/languages/LanguageSection.d.ts.map +1 -1
- package/lib/sections/languages/LanguageSection.js +42 -31
- package/lib/sections/languages/mutations.d.ts.map +1 -1
- package/lib/sections/languages/mutations.js +60 -161
- package/lib/sections/languages/selectors.d.ts.map +1 -1
- package/lib/sections/languages/selectors.js +1 -2
- package/lib/sections/projects/ProjectEditDialog.d.ts +2 -1
- package/lib/sections/projects/ProjectEditDialog.d.ts.map +1 -1
- package/lib/sections/projects/ProjectEditDialog.js +13 -24
- package/lib/sections/projects/ProjectSection.css +368 -0
- package/lib/sections/projects/ProjectSection.d.ts +2 -1
- package/lib/sections/projects/ProjectSection.d.ts.map +1 -1
- package/lib/sections/projects/ProjectSection.js +116 -34
- package/lib/sections/projects/mutations.d.ts.map +1 -1
- package/lib/sections/projects/mutations.js +109 -132
- package/lib/sections/projects/selectors.d.ts.map +1 -1
- package/lib/sections/projects/selectors.js +4 -45
- package/lib/{QRCodeCard.d.ts → sections/qrcode/QRCodeCard.d.ts} +2 -1
- package/lib/sections/qrcode/QRCodeCard.d.ts.map +1 -0
- package/lib/{QRCodeCard.js → sections/qrcode/QRCodeCard.js} +59 -11
- package/lib/sections/qrcode/QRCodeSection.css +108 -0
- package/lib/sections/qrcode/QRCodeSection.d.ts +4 -0
- package/lib/sections/qrcode/QRCodeSection.d.ts.map +1 -0
- package/lib/sections/qrcode/QRCodeSection.js +17 -0
- package/lib/sections/resume/ResumeEditDialog.d.ts +10 -1
- package/lib/sections/resume/ResumeEditDialog.d.ts.map +1 -1
- package/lib/sections/resume/ResumeEditDialog.js +531 -149
- package/lib/sections/resume/ResumeSection.css +350 -0
- package/lib/sections/resume/ResumeSection.d.ts +3 -2
- package/lib/sections/resume/ResumeSection.d.ts.map +1 -1
- package/lib/sections/resume/ResumeSection.js +78 -49
- package/lib/sections/resume/mutations.d.ts.map +1 -1
- package/lib/sections/resume/mutations.js +17 -3
- package/lib/sections/resume/selectors.d.ts.map +1 -1
- package/lib/sections/resume/selectors.js +1 -0
- package/lib/sections/resume/types.d.ts +1 -0
- package/lib/sections/resume/types.d.ts.map +1 -1
- package/lib/sections/shared/collapsibleSection.d.ts.map +1 -1
- package/lib/sections/shared/collapsibleSection.js +1 -0
- package/lib/sections/shared/phoneCountries.d.ts +1 -1
- package/lib/sections/shared/phoneCountries.d.ts.map +1 -1
- package/lib/sections/shared/phoneCountries.js +2 -2
- package/lib/sections/shared/projectCommunityNodes.d.ts +6 -0
- package/lib/sections/shared/projectCommunityNodes.d.ts.map +1 -0
- package/lib/sections/shared/projectCommunityNodes.js +56 -0
- package/lib/sections/shared/rdfMutationHelpers.d.ts +35 -2
- package/lib/sections/shared/rdfMutationHelpers.d.ts.map +1 -1
- package/lib/sections/shared/rdfMutationHelpers.js +290 -14
- package/lib/sections/shared/sectionCardHelpers.d.ts.map +1 -1
- package/lib/sections/shared/sectionCardHelpers.js +80 -11
- package/lib/sections/shared/types.d.ts +24 -0
- package/lib/sections/shared/types.d.ts.map +1 -1
- package/lib/sections/skills/SkillsEditDialog.d.ts +3 -1
- package/lib/sections/skills/SkillsEditDialog.d.ts.map +1 -1
- package/lib/sections/skills/SkillsEditDialog.js +136 -115
- package/lib/sections/skills/SkillsSection.css +173 -0
- package/lib/sections/skills/SkillsSection.d.ts +2 -0
- package/lib/sections/skills/SkillsSection.d.ts.map +1 -1
- package/lib/sections/skills/SkillsSection.js +107 -47
- package/lib/sections/skills/mutations.d.ts.map +1 -1
- package/lib/sections/skills/mutations.js +25 -21
- package/lib/sections/skills/selectors.d.ts.map +1 -1
- package/lib/sections/skills/selectors.js +5 -3
- package/lib/sections/social/SocialEditDialog.d.ts +3 -1
- package/lib/sections/social/SocialEditDialog.d.ts.map +1 -1
- package/lib/sections/social/SocialEditDialog.js +170 -62
- package/lib/sections/social/SocialSection.css +194 -0
- package/lib/sections/social/SocialSection.d.ts +4 -3
- package/lib/sections/social/SocialSection.d.ts.map +1 -1
- package/lib/sections/social/SocialSection.js +59 -43
- package/lib/sections/social/mutations.d.ts.map +1 -1
- package/lib/sections/social/mutations.js +23 -132
- package/lib/specialButtons/AddMeToYourFriends.css +54 -0
- package/lib/specialButtons/addContact/AddMeToYourContacts.css +1118 -0
- package/lib/specialButtons/addContact/ContactCreationDialog.d.ts +10 -0
- package/lib/specialButtons/addContact/ContactCreationDialog.d.ts.map +1 -0
- package/lib/specialButtons/addContact/ContactCreationDialog.js +1123 -0
- package/lib/specialButtons/addContact/addMeToYourContacts.d.ts +16 -0
- package/lib/specialButtons/addContact/addMeToYourContacts.d.ts.map +1 -0
- package/lib/specialButtons/addContact/addMeToYourContacts.js +136 -0
- package/lib/specialButtons/addContact/contactsErrors.d.ts +8 -0
- package/lib/specialButtons/addContact/contactsErrors.d.ts.map +1 -0
- package/lib/specialButtons/addContact/contactsErrors.js +106 -0
- package/lib/specialButtons/addContact/contactsTypes.d.ts +43 -0
- package/lib/specialButtons/addContact/contactsTypes.d.ts.map +1 -0
- package/lib/specialButtons/addContact/contactsTypes.js +5 -0
- package/lib/specialButtons/addContact/helpers.d.ts +7 -0
- package/lib/specialButtons/addContact/helpers.d.ts.map +1 -0
- package/lib/specialButtons/addContact/helpers.js +103 -0
- package/lib/specialButtons/addContact/mutations.d.ts +16 -0
- package/lib/specialButtons/addContact/mutations.d.ts.map +1 -0
- package/lib/specialButtons/addContact/mutations.js +300 -0
- package/lib/specialButtons/addContact/selectors.d.ts +10 -0
- package/lib/specialButtons/addContact/selectors.d.ts.map +1 -0
- package/lib/specialButtons/addContact/selectors.js +163 -0
- package/lib/{addMeToYourFriends.d.ts → specialButtons/addMeToYourFriends.d.ts} +6 -4
- package/lib/specialButtons/addMeToYourFriends.d.ts.map +1 -0
- package/lib/{addMeToYourFriends.js → specialButtons/addMeToYourFriends.js} +46 -11
- package/lib/styles/CollapsibleSection.css +519 -0
- package/lib/styles/EditDialogs.css +506 -686
- package/lib/styles/EditDialogs.responsive.css +989 -0
- package/lib/texts/buttonTexts.d.ts +9 -0
- package/lib/texts/buttonTexts.d.ts.map +1 -0
- package/lib/texts/buttonTexts.js +14 -0
- package/lib/texts/dialogTexts.d.ts +14 -0
- package/lib/texts/dialogTexts.d.ts.map +1 -0
- package/lib/texts/dialogTexts.js +19 -0
- package/lib/texts/messageTexts.d.ts +42 -0
- package/lib/texts/messageTexts.d.ts.map +1 -0
- package/lib/texts/messageTexts.js +47 -0
- package/lib/texts/profileTexts.d.ts +14 -0
- package/lib/texts/profileTexts.d.ts.map +1 -0
- package/lib/texts/profileTexts.js +19 -0
- package/lib/texts/qrCodeTexts.d.ts +2 -0
- package/lib/texts/qrCodeTexts.d.ts.map +1 -0
- package/lib/texts/qrCodeTexts.js +7 -0
- package/lib/texts.d.ts +5 -60
- package/lib/texts.d.ts.map +1 -1
- package/lib/texts.js +55 -70
- package/lib/ui/dialog.css +233 -0
- package/lib/ui/dialog.d.ts +15 -1
- package/lib/ui/dialog.d.ts.map +1 -1
- package/lib/ui/dialog.js +245 -45
- package/lib/ui/dialog.responsive.css +195 -0
- package/lib/ui/errors.d.ts.map +1 -1
- package/lib/ui/errors.js +2 -1
- package/lib/ui/spinner.d.ts +3 -0
- package/lib/ui/spinner.d.ts.map +1 -0
- package/lib/ui/spinner.js +13 -0
- package/lib/utils/debug.d.ts +5 -0
- package/lib/utils/debug.d.ts.map +1 -0
- package/lib/utils/debug.js +23 -0
- package/lib/utils/errorDisplay.d.ts +2 -0
- package/lib/utils/errorDisplay.d.ts.map +1 -0
- package/lib/utils/errorDisplay.js +19 -0
- package/package.json +32 -25
- package/lib/ChatWithMe.d.ts +0 -7
- package/lib/ChatWithMe.d.ts.map +0 -1
- package/lib/ChatWithMe.js +0 -90
- package/lib/QRCodeCard.d.ts.map +0 -1
- package/lib/addMeToYourFriends.d.ts.map +0 -1
- package/lib/sections/heading/camera.d.ts +0 -19
- package/lib/sections/heading/camera.d.ts.map +0 -1
- package/lib/sections/heading/camera.js +0 -199
- package/lib/styles/BioSection.css +0 -77
- package/lib/styles/CVCard.css +0 -142
- package/lib/styles/ChatWithMe.css +0 -6
- package/lib/styles/ContactInfoEditDialog.css +0 -153
- package/lib/styles/EducationCard.css +0 -103
- package/lib/styles/HeadingSection.css +0 -309
- package/lib/styles/ProfileCard.css +0 -66
- package/lib/styles/ProfileView.css +0 -65
- package/lib/styles/ProjectsCard.css +0 -206
- package/lib/styles/QRCodeCard.css +0 -43
- package/lib/styles/SocialCard.css +0 -89
- package/lib/styles/dialog.css +0 -209
- package/lib/styles/utilities.css +0 -740
|
@@ -4,19 +4,327 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.createResumeEditDialog = createResumeEditDialog;
|
|
7
|
+
exports.fetchWikidataOrganizationSuggestions = fetchWikidataOrganizationSuggestions;
|
|
7
8
|
var _dialog = require("../../ui/dialog");
|
|
8
9
|
var _litHtml = require("lit-html");
|
|
10
|
+
require("solid-ui/components/actions/button");
|
|
11
|
+
require("solid-ui/components/forms/combobox");
|
|
12
|
+
require("solid-ui/components/forms/select");
|
|
9
13
|
require("../../styles/EditDialogs.css");
|
|
10
|
-
require("
|
|
14
|
+
require("../contactInfo/ContactInfoEditDialog.css");
|
|
11
15
|
var _rdflib = require("rdflib");
|
|
12
16
|
var _mutations = require("./mutations");
|
|
13
17
|
var _rowState = require("../shared/rowState");
|
|
14
18
|
var _textUtils = require("../../textUtils");
|
|
15
19
|
var _profileIcons = require("../../icons-svg/profileIcons");
|
|
16
20
|
var _texts = require("../../texts");
|
|
21
|
+
const RESUME_ORGANIZATION_TYPE_OPTIONS = [{
|
|
22
|
+
label: 'Corporation',
|
|
23
|
+
value: 'Corporation'
|
|
24
|
+
}, {
|
|
25
|
+
label: 'Educational Organization',
|
|
26
|
+
value: 'EducationalOrganization'
|
|
27
|
+
}, {
|
|
28
|
+
label: 'Research Organization',
|
|
29
|
+
value: 'ResearchOrganization'
|
|
30
|
+
}, {
|
|
31
|
+
label: 'Government Organization',
|
|
32
|
+
value: 'GovernmentOrganization'
|
|
33
|
+
}, {
|
|
34
|
+
label: 'NGO',
|
|
35
|
+
value: 'NGO'
|
|
36
|
+
}, {
|
|
37
|
+
label: 'Performing Group',
|
|
38
|
+
value: 'PerformingGroup'
|
|
39
|
+
}, {
|
|
40
|
+
label: 'Project',
|
|
41
|
+
value: 'Project'
|
|
42
|
+
}, {
|
|
43
|
+
label: 'Sports Organization',
|
|
44
|
+
value: 'SportsOrganization'
|
|
45
|
+
}, {
|
|
46
|
+
label: 'Other',
|
|
47
|
+
value: 'Other'
|
|
48
|
+
}];
|
|
49
|
+
const RESUME_MONTH_OPTIONS = [{
|
|
50
|
+
value: '01',
|
|
51
|
+
label: 'January'
|
|
52
|
+
}, {
|
|
53
|
+
value: '02',
|
|
54
|
+
label: 'February'
|
|
55
|
+
}, {
|
|
56
|
+
value: '03',
|
|
57
|
+
label: 'March'
|
|
58
|
+
}, {
|
|
59
|
+
value: '04',
|
|
60
|
+
label: 'April'
|
|
61
|
+
}, {
|
|
62
|
+
value: '05',
|
|
63
|
+
label: 'May'
|
|
64
|
+
}, {
|
|
65
|
+
value: '06',
|
|
66
|
+
label: 'June'
|
|
67
|
+
}, {
|
|
68
|
+
value: '07',
|
|
69
|
+
label: 'July'
|
|
70
|
+
}, {
|
|
71
|
+
value: '08',
|
|
72
|
+
label: 'August'
|
|
73
|
+
}, {
|
|
74
|
+
value: '09',
|
|
75
|
+
label: 'September'
|
|
76
|
+
}, {
|
|
77
|
+
value: '10',
|
|
78
|
+
label: 'October'
|
|
79
|
+
}, {
|
|
80
|
+
value: '11',
|
|
81
|
+
label: 'November'
|
|
82
|
+
}, {
|
|
83
|
+
value: '12',
|
|
84
|
+
label: 'December'
|
|
85
|
+
}];
|
|
86
|
+
const WIKIDATA_ORGANIZATION_SEARCH_URI = 'https://www.wikidata.org/w/api.php?action=wbsearchentities&language=$(language)&type=item&limit=$(limit)&format=json&origin=*&search=$(name)';
|
|
87
|
+
const WIKIDATA_ENTITY_LOOKUP_URI = 'https://www.wikidata.org/w/api.php?action=wbgetentities&format=json&origin=*&props=claims&ids=$(ids)';
|
|
88
|
+
const WIKIDATA_ORGANIZATION_SEARCH_LANGUAGE = 'en';
|
|
89
|
+
const WIKIDATA_ORGANIZATION_SEARCH_LIMIT = 8;
|
|
90
|
+
const WIKIDATA_ORGANIZATION_SEARCH_CANDIDATE_LIMIT = 24;
|
|
91
|
+
const RESUME_ORGANIZATION_TYPE_WIKIDATA_CLASS_URIS = {
|
|
92
|
+
Corporation: ['http://www.wikidata.org/entity/Q6881511', 'http://www.wikidata.org/entity/Q4830453'],
|
|
93
|
+
EducationalOrganization: ['http://www.wikidata.org/entity/Q178706', 'http://www.wikidata.org/entity/Q2385804', 'http://www.wikidata.org/entity/Q1664720'],
|
|
94
|
+
ResearchOrganization: ['http://www.wikidata.org/entity/Q31855'],
|
|
95
|
+
GovernmentOrganization: ['http://www.wikidata.org/entity/Q327333'],
|
|
96
|
+
NGO: ['http://www.wikidata.org/entity/Q163740', 'http://www.wikidata.org/entity/Q79913', 'http://www.wikidata.org/entity/Q708676'],
|
|
97
|
+
PerformingGroup: ['http://www.wikidata.org/entity/Q32178211'],
|
|
98
|
+
Project: ['http://www.wikidata.org/entity/Q170584'],
|
|
99
|
+
SportsOrganization: ['http://www.wikidata.org/entity/Q4438121'],
|
|
100
|
+
Other: ['http://www.wikidata.org/entity/Q43229']
|
|
101
|
+
};
|
|
102
|
+
const RESUME_ORGANIZATION_SEARCH_CLASS_URIS = Array.from(new Set(RESUME_ORGANIZATION_TYPE_OPTIONS.flatMap(option => RESUME_ORGANIZATION_TYPE_WIKIDATA_CLASS_URIS[option.value] || [])));
|
|
103
|
+
const RESUME_PRESENT_MONTH_VALUE = '__present__';
|
|
17
104
|
function sanitizeResumeFieldValue(value) {
|
|
18
105
|
return (0, _textUtils.sanitizeTextValue)(value);
|
|
19
106
|
}
|
|
107
|
+
function normalizeResumeOrganizationPublicId(value) {
|
|
108
|
+
return sanitizeResumeFieldValue(value);
|
|
109
|
+
}
|
|
110
|
+
function buildWikidataOrganizationSearchUrl(name) {
|
|
111
|
+
return WIKIDATA_ORGANIZATION_SEARCH_URI.replace('$(language)', encodeURIComponent(WIKIDATA_ORGANIZATION_SEARCH_LANGUAGE)).replace('$(limit)', encodeURIComponent(String(WIKIDATA_ORGANIZATION_SEARCH_CANDIDATE_LIMIT))).replace('$(name)', encodeURIComponent(name));
|
|
112
|
+
}
|
|
113
|
+
function buildWikidataEntityLookupUrl(ids) {
|
|
114
|
+
return WIKIDATA_ENTITY_LOOKUP_URI.replace('$(ids)', encodeURIComponent(ids.join('|')));
|
|
115
|
+
}
|
|
116
|
+
function getWikidataIdFromUri(value) {
|
|
117
|
+
const trimmed = sanitizeResumeFieldValue(value);
|
|
118
|
+
const match = trimmed.match(/Q\d+/);
|
|
119
|
+
return match ? match[0] : '';
|
|
120
|
+
}
|
|
121
|
+
function getWikidataClaimIds(entity, property) {
|
|
122
|
+
const claims = entity?.claims?.[property] || [];
|
|
123
|
+
return claims.map(claim => claim?.mainsnak).filter(snak => snak?.snaktype === 'value').map(snak => snak?.datavalue?.value?.id).filter(id => typeof id === 'string' && id.length > 0);
|
|
124
|
+
}
|
|
125
|
+
function getAllowedOrganizationTypeIds(selectedType) {
|
|
126
|
+
const normalizedType = normalizeResumeOrganizationTypeValue(selectedType);
|
|
127
|
+
const typeUris = RESUME_ORGANIZATION_TYPE_WIKIDATA_CLASS_URIS[normalizedType];
|
|
128
|
+
if (!typeUris?.length) {
|
|
129
|
+
return RESUME_ORGANIZATION_SEARCH_CLASS_URIS.map(uri => getWikidataIdFromUri(uri)).filter(Boolean);
|
|
130
|
+
}
|
|
131
|
+
return typeUris.map(uri => getWikidataIdFromUri(uri)).filter(Boolean);
|
|
132
|
+
}
|
|
133
|
+
const allowedOrganizationTypeIdSetCache = new Map();
|
|
134
|
+
function getAllowedOrganizationTypeIdSet(selectedType) {
|
|
135
|
+
const normalizedType = normalizeResumeOrganizationTypeValue(selectedType);
|
|
136
|
+
const cachedIds = allowedOrganizationTypeIdSetCache.get(normalizedType);
|
|
137
|
+
if (cachedIds) {
|
|
138
|
+
return cachedIds;
|
|
139
|
+
}
|
|
140
|
+
const allowedIds = new Set(getAllowedOrganizationTypeIds(normalizedType));
|
|
141
|
+
allowedOrganizationTypeIdSetCache.set(normalizedType, allowedIds);
|
|
142
|
+
return allowedIds;
|
|
143
|
+
}
|
|
144
|
+
async function fetchWikidataEntities(ids) {
|
|
145
|
+
const uniqueIds = Array.from(new Set(ids.filter(Boolean)));
|
|
146
|
+
if (!uniqueIds.length || typeof fetch !== 'function') return {};
|
|
147
|
+
const response = await fetch(buildWikidataEntityLookupUrl(uniqueIds));
|
|
148
|
+
if (!response.ok) return {};
|
|
149
|
+
const payload = await response.json();
|
|
150
|
+
return payload?.entities || {};
|
|
151
|
+
}
|
|
152
|
+
function entityMatchesAllowedOrganizationTypes(entityId, entityMap, selectedType) {
|
|
153
|
+
const allowedIds = getAllowedOrganizationTypeIdSet(selectedType);
|
|
154
|
+
const visited = new Set();
|
|
155
|
+
const agenda = [entityId];
|
|
156
|
+
while (agenda.length) {
|
|
157
|
+
const currentId = agenda.shift();
|
|
158
|
+
if (!currentId || visited.has(currentId)) continue;
|
|
159
|
+
visited.add(currentId);
|
|
160
|
+
if (allowedIds.has(currentId)) {
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
const entity = entityMap[currentId];
|
|
164
|
+
agenda.push(...getWikidataClaimIds(entity, 'P31'));
|
|
165
|
+
agenda.push(...getWikidataClaimIds(entity, 'P279'));
|
|
166
|
+
}
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
function toResumeOrganizationLabel(result) {
|
|
170
|
+
return result?.label || result?.match?.text || result?.id || '';
|
|
171
|
+
}
|
|
172
|
+
function toResumeOrganizationSuggestion(result) {
|
|
173
|
+
const label = sanitizeResumeFieldValue(toResumeOrganizationLabel(result));
|
|
174
|
+
const publicId = normalizeResumeOrganizationPublicId(typeof result?.concepturi === 'string' ? result.concepturi : typeof result?.url === 'string' ? result.url : '');
|
|
175
|
+
return {
|
|
176
|
+
label,
|
|
177
|
+
publicId
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
function dedupeResumeOrganizationSuggestions(suggestions) {
|
|
181
|
+
const seen = new Set();
|
|
182
|
+
return suggestions.filter(suggestion => {
|
|
183
|
+
if (!suggestion.label || !suggestion.publicId) return false;
|
|
184
|
+
const key = suggestion.label.toLowerCase();
|
|
185
|
+
if (seen.has(key)) return false;
|
|
186
|
+
seen.add(key);
|
|
187
|
+
return true;
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
async function fetchWikidataOrganizationSuggestions(name, selectedType) {
|
|
191
|
+
const query = sanitizeResumeFieldValue(name);
|
|
192
|
+
if (query.length < 2 || typeof fetch !== 'function') return [];
|
|
193
|
+
try {
|
|
194
|
+
const response = await fetch(buildWikidataOrganizationSearchUrl(query));
|
|
195
|
+
if (!response.ok) return [];
|
|
196
|
+
const payload = await response.json();
|
|
197
|
+
const results = Array.isArray(payload?.search) ? payload.search : [];
|
|
198
|
+
const suggestions = dedupeResumeOrganizationSuggestions(results.map(result => toResumeOrganizationSuggestion(result)));
|
|
199
|
+
const resultIds = suggestions.map(suggestion => getWikidataIdFromUri(suggestion.publicId)).filter(Boolean);
|
|
200
|
+
if (!resultIds.length) {
|
|
201
|
+
return suggestions.slice(0, WIKIDATA_ORGANIZATION_SEARCH_LIMIT);
|
|
202
|
+
}
|
|
203
|
+
const resultEntities = await fetchWikidataEntities(resultIds);
|
|
204
|
+
const relatedIds = Array.from(new Set(Object.values(resultEntities).flatMap(entity => [...getWikidataClaimIds(entity, 'P31'), ...getWikidataClaimIds(entity, 'P279')])));
|
|
205
|
+
const relatedEntities = await fetchWikidataEntities(relatedIds);
|
|
206
|
+
const entityMap = {
|
|
207
|
+
...resultEntities,
|
|
208
|
+
...relatedEntities
|
|
209
|
+
};
|
|
210
|
+
if (Object.keys(entityMap).length === 0) {
|
|
211
|
+
return suggestions.slice(0, WIKIDATA_ORGANIZATION_SEARCH_LIMIT);
|
|
212
|
+
}
|
|
213
|
+
const filteredSuggestions = suggestions.filter(suggestion => {
|
|
214
|
+
const entityId = getWikidataIdFromUri(suggestion.publicId);
|
|
215
|
+
return entityMatchesAllowedOrganizationTypes(entityId, entityMap, selectedType);
|
|
216
|
+
});
|
|
217
|
+
return filteredSuggestions.slice(0, WIKIDATA_ORGANIZATION_SEARCH_LIMIT);
|
|
218
|
+
} catch {
|
|
219
|
+
return [];
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
function toResumeOrganizationComboboxOption(suggestion) {
|
|
223
|
+
return {
|
|
224
|
+
label: suggestion.label,
|
|
225
|
+
value: suggestion.publicId,
|
|
226
|
+
publicId: suggestion.publicId
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
function readResumeOrganizationComboboxInputValue(event) {
|
|
230
|
+
const customEvent = event;
|
|
231
|
+
if (typeof customEvent.detail?.value === 'string') {
|
|
232
|
+
return customEvent.detail.value;
|
|
233
|
+
}
|
|
234
|
+
const target = event.target;
|
|
235
|
+
return typeof target?.value === 'string' ? target.value : '';
|
|
236
|
+
}
|
|
237
|
+
function readResumeOrganizationComboboxChange(event) {
|
|
238
|
+
const customEvent = event;
|
|
239
|
+
if (customEvent.detail?.option) {
|
|
240
|
+
return customEvent.detail.option;
|
|
241
|
+
}
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
function createResumeOrganizationSuggestionProvider(getSelectedType) {
|
|
245
|
+
return async query => {
|
|
246
|
+
const suggestions = await fetchWikidataOrganizationSuggestions(query, getSelectedType());
|
|
247
|
+
return suggestions.map(toResumeOrganizationComboboxOption);
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
function normalizeResumeOrganizationTypeValue(value) {
|
|
251
|
+
return RESUME_ORGANIZATION_TYPE_OPTIONS.some(option => option.value === value) ? value : RESUME_ORGANIZATION_TYPE_OPTIONS[0]?.value || '';
|
|
252
|
+
}
|
|
253
|
+
function readResumeOrganizationTypeChange(event) {
|
|
254
|
+
const customEvent = event;
|
|
255
|
+
if (typeof customEvent.detail?.value === 'string') {
|
|
256
|
+
return customEvent.detail.value;
|
|
257
|
+
}
|
|
258
|
+
const target = event.target;
|
|
259
|
+
return typeof target?.value === 'string' ? target.value : '';
|
|
260
|
+
}
|
|
261
|
+
function readResumeSelectChange(event) {
|
|
262
|
+
return readResumeOrganizationTypeChange(event);
|
|
263
|
+
}
|
|
264
|
+
function getResumeYearOptions(selectedYears) {
|
|
265
|
+
const currentYear = new Date().getFullYear();
|
|
266
|
+
const baseYearOptions = Array.from({
|
|
267
|
+
length: 120
|
|
268
|
+
}, (_, i) => String(currentYear - i));
|
|
269
|
+
const yearOptions = Array.from(new Set([...baseYearOptions, ...selectedYears].filter(Boolean))).sort((a, b) => Number(b) - Number(a));
|
|
270
|
+
return yearOptions.map(year => ({
|
|
271
|
+
label: year,
|
|
272
|
+
value: year
|
|
273
|
+
}));
|
|
274
|
+
}
|
|
275
|
+
function getResumeDateSelectOptions(kind, selectedYears, isCurrentRole) {
|
|
276
|
+
if (kind === 'start-month') {
|
|
277
|
+
return RESUME_MONTH_OPTIONS;
|
|
278
|
+
}
|
|
279
|
+
if (kind === 'start-year') {
|
|
280
|
+
return getResumeYearOptions(selectedYears);
|
|
281
|
+
}
|
|
282
|
+
if (kind === 'end-month') {
|
|
283
|
+
if (isCurrentRole) {
|
|
284
|
+
return [{
|
|
285
|
+
value: RESUME_PRESENT_MONTH_VALUE,
|
|
286
|
+
label: 'Present'
|
|
287
|
+
}];
|
|
288
|
+
}
|
|
289
|
+
return RESUME_MONTH_OPTIONS;
|
|
290
|
+
}
|
|
291
|
+
if (kind === 'end-year' && isCurrentRole) {
|
|
292
|
+
return [{
|
|
293
|
+
value: '',
|
|
294
|
+
label: ''
|
|
295
|
+
}];
|
|
296
|
+
}
|
|
297
|
+
return getResumeYearOptions(selectedYears);
|
|
298
|
+
}
|
|
299
|
+
function getResumeDateSelectLabel(kind, row) {
|
|
300
|
+
switch (kind) {
|
|
301
|
+
case 'start-month':
|
|
302
|
+
case 'end-month':
|
|
303
|
+
return row?.isCurrentRole && kind === 'end-month' ? 'Present' : 'Select Month';
|
|
304
|
+
case 'start-year':
|
|
305
|
+
return 'Select Year';
|
|
306
|
+
case 'end-year':
|
|
307
|
+
return row?.isCurrentRole ? '' : 'Select Year';
|
|
308
|
+
default:
|
|
309
|
+
return '';
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
function getResumeDateSelectValue(kind, row) {
|
|
313
|
+
const startDateParts = parseYearMonthFromDateText((0, _textUtils.toText)(row?.startDate));
|
|
314
|
+
const endDateParts = parseYearMonthFromDateText((0, _textUtils.toText)(row?.endDate));
|
|
315
|
+
switch (kind) {
|
|
316
|
+
case 'start-month':
|
|
317
|
+
return startDateParts.month;
|
|
318
|
+
case 'start-year':
|
|
319
|
+
return startDateParts.year;
|
|
320
|
+
case 'end-month':
|
|
321
|
+
return row?.isCurrentRole ? RESUME_PRESENT_MONTH_VALUE : endDateParts.month;
|
|
322
|
+
case 'end-year':
|
|
323
|
+
return row?.isCurrentRole ? '' : endDateParts.year;
|
|
324
|
+
default:
|
|
325
|
+
return '';
|
|
326
|
+
}
|
|
327
|
+
}
|
|
20
328
|
function parseYearMonthFromDateText(dateText) {
|
|
21
329
|
const normalized = (dateText || '').trim();
|
|
22
330
|
if (!normalized) return {
|
|
@@ -47,7 +355,8 @@ function toFormState(resumeData) {
|
|
|
47
355
|
endDate: role.endDate,
|
|
48
356
|
isCurrentRole: role.isCurrentRole ?? !role.endDate,
|
|
49
357
|
orgName: sanitizeResumeFieldValue((0, _textUtils.toText)(role.orgName)),
|
|
50
|
-
|
|
358
|
+
orgPublicId: normalizeResumeOrganizationPublicId(sanitizeResumeFieldValue((0, _textUtils.toText)(role.orgPublicId))),
|
|
359
|
+
orgType: normalizeResumeOrganizationTypeValue(sanitizeResumeFieldValue((0, _textUtils.toText)(role.orgType))),
|
|
51
360
|
orgLocation: sanitizeResumeFieldValue((0, _textUtils.toText)(role.orgLocation)),
|
|
52
361
|
orgHomePage: sanitizeResumeFieldValue((0, _textUtils.toText)(role.orgHomePage)),
|
|
53
362
|
description: sanitizeResumeFieldValue((0, _textUtils.toText)(role.description)),
|
|
@@ -62,7 +371,8 @@ function toFormState(resumeData) {
|
|
|
62
371
|
endDate: undefined,
|
|
63
372
|
isCurrentRole: false,
|
|
64
373
|
orgName: '',
|
|
65
|
-
|
|
374
|
+
orgPublicId: '',
|
|
375
|
+
orgType: RESUME_ORGANIZATION_TYPE_OPTIONS[0].value,
|
|
66
376
|
orgLocation: '',
|
|
67
377
|
orgHomePage: '',
|
|
68
378
|
description: '',
|
|
@@ -88,6 +398,66 @@ function validateResumeBeforeSave(rows) {
|
|
|
88
398
|
ok: true
|
|
89
399
|
};
|
|
90
400
|
}
|
|
401
|
+
function initializeResumeOrganizationTypeSelects(form, resumeData) {
|
|
402
|
+
const selectElements = form.querySelectorAll('solid-ui-select[data-resume-organization-type-index]');
|
|
403
|
+
selectElements.forEach(selectElement => {
|
|
404
|
+
const rowIndex = Number(selectElement.dataset.resumeOrganizationTypeIndex);
|
|
405
|
+
if (Number.isNaN(rowIndex)) return;
|
|
406
|
+
const resumeRow = resumeData[rowIndex];
|
|
407
|
+
if (!resumeRow) return;
|
|
408
|
+
selectElement.options = RESUME_ORGANIZATION_TYPE_OPTIONS;
|
|
409
|
+
selectElement.value = normalizeResumeOrganizationTypeValue(resumeRow.orgType || '');
|
|
410
|
+
selectElement.label = '';
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
function initializeResumeOrganizationComboboxes(form, resumeData) {
|
|
414
|
+
const comboboxElements = form.querySelectorAll('solid-ui-combobox[data-resume-organization-index]');
|
|
415
|
+
comboboxElements.forEach(comboboxElement => {
|
|
416
|
+
const rowIndex = Number(comboboxElement.dataset.resumeOrganizationIndex);
|
|
417
|
+
if (Number.isNaN(rowIndex)) return;
|
|
418
|
+
const resumeRow = resumeData[rowIndex];
|
|
419
|
+
if (!resumeRow) return;
|
|
420
|
+
const options = resumeRow.orgPublicId && resumeRow.orgName ? [{
|
|
421
|
+
label: resumeRow.orgName,
|
|
422
|
+
value: resumeRow.orgPublicId,
|
|
423
|
+
publicId: resumeRow.orgPublicId
|
|
424
|
+
}] : [];
|
|
425
|
+
comboboxElement.suggestionProvider = createResumeOrganizationSuggestionProvider(() => normalizeResumeOrganizationTypeValue(resumeRow.orgType || ''));
|
|
426
|
+
comboboxElement.options = options;
|
|
427
|
+
comboboxElement.value = resumeRow.orgPublicId || '';
|
|
428
|
+
comboboxElement.inputValue = resumeRow.orgName || '';
|
|
429
|
+
comboboxElement.label = '';
|
|
430
|
+
comboboxElement.placeholder = 'Company or Organization';
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
function syncResumeOrganizationRowsFromComboboxes(form, resumeData) {
|
|
434
|
+
const comboboxElements = form.querySelectorAll('solid-ui-combobox[data-resume-organization-index]');
|
|
435
|
+
comboboxElements.forEach(comboboxElement => {
|
|
436
|
+
const rowIndex = Number(comboboxElement.dataset.resumeOrganizationIndex);
|
|
437
|
+
if (Number.isNaN(rowIndex) || !resumeData[rowIndex]) return;
|
|
438
|
+
const comboboxInput = comboboxElement.shadowRoot?.querySelector('input');
|
|
439
|
+
const nextName = sanitizeResumeFieldValue(comboboxInput?.value || comboboxElement.inputValue || '');
|
|
440
|
+
const nextPublicId = normalizeResumeOrganizationPublicId(comboboxElement.value || '');
|
|
441
|
+
(0, _rowState.applyRowFieldChange)(resumeData[rowIndex], 'orgName', nextName, rowHasContent);
|
|
442
|
+
resumeData[rowIndex].orgPublicId = nextPublicId;
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
function initializeResumeDateSelects(form, resumeData) {
|
|
446
|
+
const selectElements = form.querySelectorAll('solid-ui-select[data-resume-date-kind]');
|
|
447
|
+
selectElements.forEach(selectElement => {
|
|
448
|
+
const kind = selectElement.dataset.resumeDateKind;
|
|
449
|
+
const rowIndex = Number(selectElement.dataset.resumeRowIndex);
|
|
450
|
+
if (!kind || Number.isNaN(rowIndex)) return;
|
|
451
|
+
const resumeRow = resumeData[rowIndex];
|
|
452
|
+
if (!resumeRow) return;
|
|
453
|
+
const startDateParts = parseYearMonthFromDateText((0, _textUtils.toText)(resumeRow.startDate));
|
|
454
|
+
const endDateParts = parseYearMonthFromDateText((0, _textUtils.toText)(resumeRow.endDate));
|
|
455
|
+
const selectedYears = [startDateParts.year, endDateParts.year];
|
|
456
|
+
selectElement.options = getResumeDateSelectOptions(kind, selectedYears, Boolean(resumeRow.isCurrentRole));
|
|
457
|
+
selectElement.value = getResumeDateSelectValue(kind, resumeRow);
|
|
458
|
+
selectElement.label = getResumeDateSelectLabel(kind, resumeRow);
|
|
459
|
+
});
|
|
460
|
+
}
|
|
91
461
|
function renderResumeInputRow({
|
|
92
462
|
resumeData,
|
|
93
463
|
index,
|
|
@@ -130,59 +500,7 @@ function renderResumeInputRow({
|
|
|
130
500
|
const endYearParsedText = endDateParts.year;
|
|
131
501
|
const isCurrentRoleId = `resume-current-role-${index}`;
|
|
132
502
|
const currentYear = new Date().getFullYear();
|
|
133
|
-
const
|
|
134
|
-
length: 120
|
|
135
|
-
}, (_, i) => String(currentYear - i));
|
|
136
|
-
const yearOptions = Array.from(new Set([...baseYearOptions, startYearText, endYearParsedText].filter(Boolean))).sort((a, b) => Number(b) - Number(a));
|
|
137
|
-
const monthOptions = [{
|
|
138
|
-
value: '01',
|
|
139
|
-
label: 'January'
|
|
140
|
-
}, {
|
|
141
|
-
value: '02',
|
|
142
|
-
label: 'February'
|
|
143
|
-
}, {
|
|
144
|
-
value: '03',
|
|
145
|
-
label: 'March'
|
|
146
|
-
}, {
|
|
147
|
-
value: '04',
|
|
148
|
-
label: 'April'
|
|
149
|
-
}, {
|
|
150
|
-
value: '05',
|
|
151
|
-
label: 'May'
|
|
152
|
-
}, {
|
|
153
|
-
value: '06',
|
|
154
|
-
label: 'June'
|
|
155
|
-
}, {
|
|
156
|
-
value: '07',
|
|
157
|
-
label: 'July'
|
|
158
|
-
}, {
|
|
159
|
-
value: '08',
|
|
160
|
-
label: 'August'
|
|
161
|
-
}, {
|
|
162
|
-
value: '09',
|
|
163
|
-
label: 'September'
|
|
164
|
-
}, {
|
|
165
|
-
value: '10',
|
|
166
|
-
label: 'October'
|
|
167
|
-
}, {
|
|
168
|
-
value: '11',
|
|
169
|
-
label: 'November'
|
|
170
|
-
}, {
|
|
171
|
-
value: '12',
|
|
172
|
-
label: 'December'
|
|
173
|
-
}];
|
|
174
|
-
const renderMonthOptions = (selectedMonth, emptyLabel = 'Select Month') => (0, _litHtml.html)`
|
|
175
|
-
<option value="" ?selected=${!selectedMonth}>${emptyLabel}</option>
|
|
176
|
-
${monthOptions.map(month => (0, _litHtml.html)`
|
|
177
|
-
<option value=${month.value} ?selected=${month.value === selectedMonth}>${month.label}</option>
|
|
178
|
-
`)}
|
|
179
|
-
`;
|
|
180
|
-
const renderYearOptions = (selectedYear, emptyLabel = 'Select Year') => (0, _litHtml.html)`
|
|
181
|
-
<option value="" ?selected=${!selectedYear}>${emptyLabel}</option>
|
|
182
|
-
${yearOptions.map(year => (0, _litHtml.html)`
|
|
183
|
-
<option value=${year} ?selected=${year === selectedYear}>${year}</option>
|
|
184
|
-
`)}
|
|
185
|
-
`;
|
|
503
|
+
const selectedYears = [startYearText, endYearParsedText];
|
|
186
504
|
const handleResumeInput = field => e => {
|
|
187
505
|
const target = e.target;
|
|
188
506
|
const nextValue = sanitizeResumeFieldValue(target.value);
|
|
@@ -203,8 +521,7 @@ function renderResumeInputRow({
|
|
|
203
521
|
/* The following function was generated by AI Model: GPT-5.3-Codex */
|
|
204
522
|
/* Prompt: can you make this a month drop down for the start year */
|
|
205
523
|
const handleStartMonthChange = event => {
|
|
206
|
-
const
|
|
207
|
-
const month = target.value;
|
|
524
|
+
const month = readResumeSelectChange(event);
|
|
208
525
|
const year = parseYearMonthFromDateText((0, _textUtils.toText)(resumeData[index]?.startDate)).year || String(currentYear);
|
|
209
526
|
const nextStartDate = buildDateLiteral(month, year);
|
|
210
527
|
if (resumeData[index]) {
|
|
@@ -213,8 +530,7 @@ function renderResumeInputRow({
|
|
|
213
530
|
}
|
|
214
531
|
};
|
|
215
532
|
const handleStartYearChange = event => {
|
|
216
|
-
const
|
|
217
|
-
const year = target.value;
|
|
533
|
+
const year = readResumeSelectChange(event);
|
|
218
534
|
const month = parseYearMonthFromDateText((0, _textUtils.toText)(resumeData[index]?.startDate)).month || '01';
|
|
219
535
|
const nextStartDate = buildDateLiteral(month, year);
|
|
220
536
|
if (resumeData[index]) {
|
|
@@ -223,8 +539,8 @@ function renderResumeInputRow({
|
|
|
223
539
|
}
|
|
224
540
|
};
|
|
225
541
|
const handleEndMonthChange = event => {
|
|
226
|
-
|
|
227
|
-
const month =
|
|
542
|
+
if (resumeData[index]?.isCurrentRole) return;
|
|
543
|
+
const month = readResumeSelectChange(event);
|
|
228
544
|
const year = parseYearMonthFromDateText((0, _textUtils.toText)(resumeData[index]?.endDate)).year || String(currentYear);
|
|
229
545
|
const nextEndDate = buildDateLiteral(month, year);
|
|
230
546
|
if (resumeData[index]) {
|
|
@@ -233,8 +549,8 @@ function renderResumeInputRow({
|
|
|
233
549
|
}
|
|
234
550
|
};
|
|
235
551
|
const handleEndYearChange = event => {
|
|
236
|
-
|
|
237
|
-
const year =
|
|
552
|
+
if (resumeData[index]?.isCurrentRole) return;
|
|
553
|
+
const year = readResumeSelectChange(event);
|
|
238
554
|
const month = parseYearMonthFromDateText((0, _textUtils.toText)(resumeData[index]?.endDate)).month || '01';
|
|
239
555
|
const nextEndDate = buildDateLiteral(month, year);
|
|
240
556
|
if (resumeData[index]) {
|
|
@@ -257,48 +573,45 @@ function renderResumeInputRow({
|
|
|
257
573
|
if (target.checked) {
|
|
258
574
|
(0, _rowState.applyRowFieldChange)(resumeData[index], 'endDate', undefined, rowHasContent);
|
|
259
575
|
}
|
|
260
|
-
|
|
261
|
-
const endMonthSelect = formRoot?.querySelector(`#${endMonthSelectId}`);
|
|
262
|
-
const endYearSelect = formRoot?.querySelector(`#${endYearSelectId}`);
|
|
263
|
-
if (endMonthSelect) {
|
|
264
|
-
endMonthSelect.disabled = target.checked;
|
|
265
|
-
endMonthSelect.value = '';
|
|
266
|
-
const emptyOption = endMonthSelect.options[0];
|
|
267
|
-
if (emptyOption) {
|
|
268
|
-
emptyOption.text = target.checked ? 'Present' : 'Select Month';
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
if (endYearSelect) {
|
|
272
|
-
endYearSelect.disabled = target.checked;
|
|
273
|
-
endYearSelect.value = '';
|
|
274
|
-
const emptyOption = endYearSelect.options[0];
|
|
275
|
-
if (emptyOption) {
|
|
276
|
-
emptyOption.text = target.checked ? '' : 'Select Year';
|
|
277
|
-
}
|
|
278
|
-
}
|
|
576
|
+
onChange();
|
|
279
577
|
}
|
|
280
578
|
};
|
|
281
579
|
const handleOrganizationTypeInput = e => {
|
|
282
|
-
const
|
|
283
|
-
const nextType = target.value;
|
|
580
|
+
const nextType = normalizeResumeOrganizationTypeValue(readResumeOrganizationTypeChange(e));
|
|
284
581
|
if (resumeRow) {
|
|
285
582
|
(0, _rowState.applyRowSelectChange)(resumeRow, 'orgType', nextType);
|
|
583
|
+
resumeRow.orgPublicId = '';
|
|
286
584
|
onChange();
|
|
287
585
|
}
|
|
288
586
|
};
|
|
587
|
+
const handleOrganizationNameInput = e => {
|
|
588
|
+
const nextValue = sanitizeResumeFieldValue(readResumeOrganizationComboboxInputValue(e));
|
|
589
|
+
if (resumeRow) {
|
|
590
|
+
(0, _rowState.applyRowFieldChange)(resumeRow, 'orgName', nextValue, rowHasContent);
|
|
591
|
+
resumeRow.orgPublicId = '';
|
|
592
|
+
}
|
|
593
|
+
};
|
|
594
|
+
const handleOrganizationNameChange = e => {
|
|
595
|
+
const selectedOption = readResumeOrganizationComboboxChange(e);
|
|
596
|
+
if (!resumeRow || !selectedOption?.publicId) return;
|
|
597
|
+
(0, _rowState.applyRowFieldChange)(resumeRow, 'orgName', sanitizeResumeFieldValue(selectedOption.label), rowHasContent);
|
|
598
|
+
resumeRow.orgPublicId = selectedOption.publicId;
|
|
599
|
+
};
|
|
289
600
|
return (0, _litHtml.html)`
|
|
290
601
|
<div class="profile-edit-dialog__row profile-edit-dialog__row--resume-entry-header" role="group" aria-labelledby=${experienceHeadingId}>
|
|
291
602
|
<h3 id=${experienceHeadingId} class="profile-edit-dialog__entry-heading">${label}</h3>
|
|
292
603
|
<div class="profile-edit-dialog__actions profile-edit-dialog__actions--edge">
|
|
293
|
-
<button
|
|
604
|
+
<solid-ui-button
|
|
294
605
|
type="button"
|
|
606
|
+
variant="icon"
|
|
607
|
+
size="md"
|
|
295
608
|
class="profile-edit-dialog__delete-button"
|
|
296
609
|
aria-label=${`Delete resume ${displayIndex + 1}`}
|
|
297
610
|
title=${_texts.deleteEntryButtonTitleText}
|
|
298
611
|
@click=${handleDelete}
|
|
299
612
|
>
|
|
300
|
-
<span class="profile-edit-dialog__delete-icon" aria-hidden="true">${_profileIcons.trashIcon}</span>
|
|
301
|
-
</button>
|
|
613
|
+
<span slot="icon" class="profile-edit-dialog__delete-icon" aria-hidden="true">${_profileIcons.trashIcon}</span>
|
|
614
|
+
</solid-ui-button>
|
|
302
615
|
</div>
|
|
303
616
|
</div>
|
|
304
617
|
<label aria-label=${`${label} Title`} class="label profile-edit-dialog__field">
|
|
@@ -318,36 +631,28 @@ function renderResumeInputRow({
|
|
|
318
631
|
/>
|
|
319
632
|
</label>
|
|
320
633
|
<div class="profile-edit-dialog__row">
|
|
634
|
+
<label aria-label=${`${label} Organization Type`} class="label profile-edit-dialog__field">
|
|
635
|
+
Organization Type
|
|
636
|
+
<solid-ui-select
|
|
637
|
+
class="profile-edit-dialog__resume-organization-type-select"
|
|
638
|
+
name=${organizationTypeName}
|
|
639
|
+
id=${organizationTypeSelectId}
|
|
640
|
+
data-resume-organization-type-index=${String(index)}
|
|
641
|
+
.options=${RESUME_ORGANIZATION_TYPE_OPTIONS}
|
|
642
|
+
.value=${normalizeResumeOrganizationTypeValue(resumeRow?.orgType || '')}
|
|
643
|
+
.label=${''}
|
|
644
|
+
@change=${handleOrganizationTypeInput}
|
|
645
|
+
></solid-ui-select>
|
|
646
|
+
</label>
|
|
321
647
|
<label aria-label=${`${label} Organization Name`} class="label profile-edit-dialog__field">
|
|
322
648
|
Company or Organization
|
|
323
|
-
<
|
|
324
|
-
class="input"
|
|
325
|
-
type="text"
|
|
649
|
+
<solid-ui-combobox
|
|
326
650
|
name=${organizationName}
|
|
327
|
-
|
|
651
|
+
data-resume-organization-index=${String(index)}
|
|
328
652
|
required
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
placeholder="Company or Organization"
|
|
333
|
-
autocomplete="organization"
|
|
334
|
-
inputmode="text"
|
|
335
|
-
@change=${handleResumeInput('orgName')}
|
|
336
|
-
/>
|
|
337
|
-
</label>
|
|
338
|
-
<label aria-label=${`${label} Organization Type`} class="label profile-edit-dialog__field">
|
|
339
|
-
Organization Type
|
|
340
|
-
<select name=${organizationTypeName} id=${organizationTypeSelectId} @change=${handleOrganizationTypeInput} .value=${resumeRow?.orgType || ''}>
|
|
341
|
-
<option value="Corporation">Corporation</option>
|
|
342
|
-
<option value="EducationalOrganization">Educational Organization</option>
|
|
343
|
-
<option value="ResearchOrganization">Research Organization</option>
|
|
344
|
-
<option value="GovernmentOrganization">Government Organization</option>
|
|
345
|
-
<option value="NGO">NGO</option>
|
|
346
|
-
<option value="PerformingGroup">Performing Group</option>
|
|
347
|
-
<option value="Project">Project</option>
|
|
348
|
-
<option value="SportsOrganization">Sports Organization</option>
|
|
349
|
-
<option value="Other">Other</option>
|
|
350
|
-
</select>
|
|
653
|
+
@input=${handleOrganizationNameInput}
|
|
654
|
+
@change=${handleOrganizationNameChange}
|
|
655
|
+
></solid-ui-combobox>
|
|
351
656
|
</label>
|
|
352
657
|
</div>
|
|
353
658
|
<div class="profile-edit-dialog__row">
|
|
@@ -388,35 +693,63 @@ function renderResumeInputRow({
|
|
|
388
693
|
<label aria-label=${`Start Date ${displayIndex + 1}`} class="label profile-edit-dialog__field profile-edit-dialog__field--date-group">
|
|
389
694
|
<span>Start Date</span>
|
|
390
695
|
<div class="profile-edit-dialog__date-pair">
|
|
391
|
-
<select
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
696
|
+
<solid-ui-select
|
|
697
|
+
class="profile-edit-dialog__resume-date-select"
|
|
698
|
+
name=${startMonthInputName}
|
|
699
|
+
id=${startMonthSelectId}
|
|
700
|
+
aria-label=${startMonthLabel}
|
|
701
|
+
data-resume-date-kind="start-month"
|
|
702
|
+
data-resume-row-index=${String(index)}
|
|
703
|
+
.options=${getResumeDateSelectOptions('start-month', selectedYears, Boolean(resumeRow?.isCurrentRole))}
|
|
704
|
+
.value=${startMonthValue}
|
|
705
|
+
.label=${getResumeDateSelectLabel('start-month', resumeRow)}
|
|
706
|
+
@change=${handleStartMonthChange}
|
|
707
|
+
></solid-ui-select>
|
|
708
|
+
<solid-ui-select
|
|
709
|
+
class="profile-edit-dialog__resume-date-select"
|
|
710
|
+
name=${startYearInputName}
|
|
711
|
+
id=${startYearSelectId}
|
|
712
|
+
aria-label=${startYearLabel}
|
|
713
|
+
data-resume-date-kind="start-year"
|
|
714
|
+
data-resume-row-index=${String(index)}
|
|
715
|
+
.options=${getResumeDateSelectOptions('start-year', selectedYears, Boolean(resumeRow?.isCurrentRole))}
|
|
716
|
+
.value=${startYearText}
|
|
717
|
+
.label=${getResumeDateSelectLabel('start-year', resumeRow)}
|
|
718
|
+
@change=${handleStartYearChange}
|
|
719
|
+
></solid-ui-select>
|
|
397
720
|
</div>
|
|
398
721
|
</label>
|
|
399
722
|
<label aria-label=${`End Date ${displayIndex + 1}`} class="label profile-edit-dialog__field profile-edit-dialog__field--date-group">
|
|
400
723
|
<span>End Date</span>
|
|
401
724
|
<div class="profile-edit-dialog__date-pair">
|
|
402
|
-
<select
|
|
725
|
+
<solid-ui-select
|
|
726
|
+
class=${`profile-edit-dialog__resume-date-select${resumeRow?.isCurrentRole ? ' profile-edit-dialog__resume-date-select--disabled' : ''}`}
|
|
403
727
|
name=${endMonthInputName}
|
|
404
728
|
id=${endMonthSelectId}
|
|
405
729
|
aria-label=${endMonthLabel}
|
|
730
|
+
aria-disabled=${String(Boolean(resumeRow?.isCurrentRole))}
|
|
731
|
+
tabindex=${resumeRow?.isCurrentRole ? '-1' : '0'}
|
|
732
|
+
data-resume-date-kind="end-month"
|
|
733
|
+
data-resume-row-index=${String(index)}
|
|
734
|
+
.options=${getResumeDateSelectOptions('end-month', selectedYears, Boolean(resumeRow?.isCurrentRole))}
|
|
735
|
+
.value=${resumeRow?.isCurrentRole ? RESUME_PRESENT_MONTH_VALUE : endMonthValue}
|
|
736
|
+
.label=${getResumeDateSelectLabel('end-month', resumeRow)}
|
|
406
737
|
@change=${handleEndMonthChange}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
${
|
|
410
|
-
</select>
|
|
411
|
-
<select
|
|
738
|
+
></solid-ui-select>
|
|
739
|
+
<solid-ui-select
|
|
740
|
+
class=${`profile-edit-dialog__resume-date-select${resumeRow?.isCurrentRole ? ' profile-edit-dialog__resume-date-select--disabled' : ''}`}
|
|
412
741
|
name=${endYearInputName}
|
|
413
742
|
id=${endYearSelectId}
|
|
414
743
|
aria-label=${endYearLabel}
|
|
744
|
+
aria-disabled=${String(Boolean(resumeRow?.isCurrentRole))}
|
|
745
|
+
tabindex=${resumeRow?.isCurrentRole ? '-1' : '0'}
|
|
746
|
+
data-resume-date-kind="end-year"
|
|
747
|
+
data-resume-row-index=${String(index)}
|
|
748
|
+
.options=${getResumeDateSelectOptions('end-year', selectedYears, Boolean(resumeRow?.isCurrentRole))}
|
|
749
|
+
.value=${resumeRow?.isCurrentRole ? '' : endYearParsedText}
|
|
750
|
+
.label=${getResumeDateSelectLabel('end-year', resumeRow)}
|
|
415
751
|
@change=${handleEndYearChange}
|
|
416
|
-
|
|
417
|
-
>
|
|
418
|
-
${renderYearOptions(endYearParsedText, resumeRow?.isCurrentRole ? '' : 'Select Year')}
|
|
419
|
-
</select>
|
|
752
|
+
></solid-ui-select>
|
|
420
753
|
</div>
|
|
421
754
|
</label>
|
|
422
755
|
</div>
|
|
@@ -486,16 +819,24 @@ function renderResumeEditTemplate(form, formState, rerender, viewerMode) {
|
|
|
486
819
|
${renderResumeSection(formState.resumeData, rerender)}
|
|
487
820
|
${viewerMode !== 'owner' ? (0, _litHtml.html)`<p class="profile-edit-dialog__login-message">${_texts.ownerLoginRequiredDialogMessageText}</p>` : null}
|
|
488
821
|
`, form);
|
|
822
|
+
initializeResumeOrganizationTypeSelects(form, formState.resumeData);
|
|
823
|
+
initializeResumeOrganizationComboboxes(form, formState.resumeData);
|
|
824
|
+
initializeResumeDateSelects(form, formState.resumeData);
|
|
489
825
|
}
|
|
490
826
|
function captureResumeDialogRenderState(form) {
|
|
491
827
|
const dialog = form.closest('dialog');
|
|
492
828
|
const description = dialog?.querySelector('#modal-desc');
|
|
493
829
|
const activeElement = form.ownerDocument.activeElement;
|
|
830
|
+
const activeTextField = activeElement instanceof HTMLInputElement || activeElement instanceof HTMLTextAreaElement ? activeElement : null;
|
|
494
831
|
return {
|
|
495
832
|
dialogScrollTop: dialog?.scrollTop || 0,
|
|
496
833
|
descriptionScrollTop: description?.scrollTop || 0,
|
|
497
834
|
activeId: activeElement?.id || '',
|
|
498
|
-
activeName: activeElement?.getAttribute('name') || ''
|
|
835
|
+
activeName: activeElement?.getAttribute('name') || '',
|
|
836
|
+
selectionStart: activeTextField?.selectionStart ?? null,
|
|
837
|
+
selectionEnd: activeTextField?.selectionEnd ?? null,
|
|
838
|
+
fieldScrollLeft: activeTextField?.scrollLeft || 0,
|
|
839
|
+
fieldScrollTop: activeTextField?.scrollTop || 0
|
|
499
840
|
};
|
|
500
841
|
}
|
|
501
842
|
function restoreResumeDialogRenderState(form, state) {
|
|
@@ -512,22 +853,61 @@ function restoreResumeDialogRenderState(form, state) {
|
|
|
512
853
|
if (!nextActive && escapedName) {
|
|
513
854
|
nextActive = form.querySelector(`[name="${escapedName}"]`);
|
|
514
855
|
}
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
856
|
+
focusResumeFieldElement(nextActive, {
|
|
857
|
+
selectionStart: state.selectionStart,
|
|
858
|
+
selectionEnd: state.selectionEnd,
|
|
859
|
+
scrollLeft: state.fieldScrollLeft,
|
|
860
|
+
scrollTop: state.fieldScrollTop
|
|
861
|
+
});
|
|
862
|
+
}
|
|
863
|
+
function getResumeFocusableTarget(element) {
|
|
864
|
+
if (!element) return null;
|
|
865
|
+
if (element.tagName === 'SOLID-UI-COMBOBOX') {
|
|
866
|
+
const comboboxInput = element.shadowRoot?.querySelector('input');
|
|
867
|
+
if (comboboxInput) return comboboxInput;
|
|
519
868
|
}
|
|
869
|
+
return element;
|
|
520
870
|
}
|
|
521
|
-
function
|
|
522
|
-
const
|
|
523
|
-
if (!
|
|
524
|
-
|
|
871
|
+
function focusResumeFieldElement(element, options = {}) {
|
|
872
|
+
const focusTarget = getResumeFocusableTarget(element);
|
|
873
|
+
if (!focusTarget || typeof focusTarget.focus !== 'function') return;
|
|
874
|
+
const view = focusTarget.ownerDocument.defaultView;
|
|
875
|
+
const shouldAvoidFocus = Boolean(view?.matchMedia && (view.matchMedia('(pointer: coarse)').matches || view.matchMedia('(max-width: 640px)').matches));
|
|
876
|
+
if (shouldAvoidFocus) {
|
|
877
|
+
focusTarget.scrollIntoView({
|
|
878
|
+
block: 'nearest',
|
|
879
|
+
behavior: 'auto'
|
|
880
|
+
});
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
focusTarget.focus({
|
|
525
884
|
preventScroll: true
|
|
526
885
|
});
|
|
527
|
-
if (
|
|
528
|
-
|
|
886
|
+
if (focusTarget instanceof HTMLInputElement || focusTarget instanceof HTMLTextAreaElement) {
|
|
887
|
+
const selectionStart = options.selectionStart ?? focusTarget.value.length;
|
|
888
|
+
const selectionEnd = options.selectionEnd ?? selectionStart;
|
|
889
|
+
focusTarget.setSelectionRange(selectionStart, selectionEnd);
|
|
890
|
+
focusTarget.scrollLeft = options.scrollLeft ?? focusTarget.scrollLeft;
|
|
891
|
+
focusTarget.scrollTop = options.scrollTop ?? focusTarget.scrollTop;
|
|
892
|
+
requestAnimationFrame(() => {
|
|
893
|
+
focusTarget.scrollLeft = options.scrollLeft ?? focusTarget.scrollLeft;
|
|
894
|
+
focusTarget.scrollTop = options.scrollTop ?? focusTarget.scrollTop;
|
|
895
|
+
});
|
|
896
|
+
}
|
|
897
|
+
if (element?.tagName === 'SOLID-UI-COMBOBOX') {
|
|
898
|
+
const comboboxHost = element;
|
|
899
|
+
if (comboboxHost._closePopup) {
|
|
900
|
+
requestAnimationFrame(() => {
|
|
901
|
+
comboboxHost._closePopup?.();
|
|
902
|
+
});
|
|
903
|
+
}
|
|
529
904
|
}
|
|
530
905
|
}
|
|
906
|
+
function focusResumeField(form, selector) {
|
|
907
|
+
const nextField = form.querySelector(selector);
|
|
908
|
+
if (!nextField) return;
|
|
909
|
+
focusResumeFieldElement(nextField);
|
|
910
|
+
}
|
|
531
911
|
function createResumeEditForm(resumeData, viewerMode) {
|
|
532
912
|
const form = document.createElement('form');
|
|
533
913
|
form.classList.add('profile__edit-form');
|
|
@@ -556,7 +936,8 @@ function createResumeEditForm(resumeData, viewerMode) {
|
|
|
556
936
|
endDate: undefined,
|
|
557
937
|
isCurrentRole: false,
|
|
558
938
|
orgName: '',
|
|
559
|
-
|
|
939
|
+
orgPublicId: '',
|
|
940
|
+
orgType: RESUME_ORGANIZATION_TYPE_OPTIONS[0].value,
|
|
560
941
|
orgLocation: '',
|
|
561
942
|
orgHomePage: '',
|
|
562
943
|
description: '',
|
|
@@ -587,6 +968,11 @@ async function createResumeEditDialog(event, store, subject, resumeData, viewerM
|
|
|
587
968
|
title: _texts.editResumeDialogTitleText,
|
|
588
969
|
dom,
|
|
589
970
|
form,
|
|
971
|
+
shouldCloseWithoutSave: () => {
|
|
972
|
+
syncResumeOrganizationRowsFromComboboxes(form, formState.resumeData);
|
|
973
|
+
const plan = (0, _rowState.summarizeRowOps)(formState.resumeData, rowHasContent);
|
|
974
|
+
return plan.create.length === 0 && plan.update.length === 0 && plan.remove.length === 0;
|
|
975
|
+
},
|
|
590
976
|
headerAction: {
|
|
591
977
|
type: 'button',
|
|
592
978
|
label: '+ Add More',
|
|
@@ -596,14 +982,10 @@ async function createResumeEditDialog(event, store, subject, resumeData, viewerM
|
|
|
596
982
|
submitLabel: _texts.dialogSubmitLabelText,
|
|
597
983
|
cancelLabel: _texts.dialogCancelLabelText,
|
|
598
984
|
validate: async () => {
|
|
985
|
+
syncResumeOrganizationRowsFromComboboxes(form, formState.resumeData);
|
|
599
986
|
if (viewerMode !== 'owner') {
|
|
600
987
|
return _texts.ownerLoginRequiredDialogMessageText;
|
|
601
988
|
}
|
|
602
|
-
const plan = (0, _rowState.summarizeRowOps)(formState.resumeData, rowHasContent);
|
|
603
|
-
const hasChanges = plan.create.length > 0 || plan.update.length > 0 || plan.remove.length > 0;
|
|
604
|
-
if (!hasChanges) {
|
|
605
|
-
return 'No resume changes detected.';
|
|
606
|
-
}
|
|
607
989
|
const validation = validateResumeBeforeSave(formState.resumeData);
|
|
608
990
|
if (!validation.ok) {
|
|
609
991
|
return validation.message || 'Please complete the required resume fields.';
|
|
@@ -611,13 +993,13 @@ async function createResumeEditDialog(event, store, subject, resumeData, viewerM
|
|
|
611
993
|
return null;
|
|
612
994
|
},
|
|
613
995
|
onSave: async () => {
|
|
996
|
+
syncResumeOrganizationRowsFromComboboxes(form, formState.resumeData);
|
|
614
997
|
const plan = (0, _rowState.summarizeRowOps)(formState.resumeData, rowHasContent);
|
|
615
998
|
await (0, _mutations.processResumeMutations)(store, subject, plan);
|
|
616
999
|
rerender();
|
|
617
1000
|
},
|
|
618
1001
|
formatSaveError: error => {
|
|
619
|
-
|
|
620
|
-
return `${_texts.saveResumeUpdatesFailedPrefixText} ${message}`;
|
|
1002
|
+
return error instanceof Error ? error.message : _texts.saveResumeUpdatesFailedMessageText;
|
|
621
1003
|
}
|
|
622
1004
|
});
|
|
623
1005
|
if (!result) return;
|