profile-pane 3.1.2-8a70896f → 3.1.2-c5f42c7e

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.
@@ -2,5 +2,6 @@ import { DataBrowserContext } from 'pane-registry';
2
2
  import { AddressBooksData, ContactData } from './contactsTypes';
3
3
  import ContactsModuleRdfLib from '@solid-data-modules/contacts-rdflib';
4
4
  export declare const createAddressBookUriSelectorDialog: (context: DataBrowserContext, contactsModule: ContactsModuleRdfLib, contactData: ContactData, addressBooksData: AddressBooksData) => HTMLDialogElement;
5
+ export declare const handleContactExistsByName: (context: DataBrowserContext, addressBooksData: AddressBooksData, contactData: ContactData, contactExistsByNameUri: string, fromRegisteredAddressBook: boolean) => Boolean;
5
6
  export declare function getButtonContainer(context: DataBrowserContext): HTMLDivElement;
6
7
  //# sourceMappingURL=ContactsCard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ContactsCard.d.ts","sourceRoot":"","sources":["../src/ContactsCard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAElD,OAAO,EAAsB,gBAAgB,EAAE,WAAW,EAAa,MAAM,iBAAiB,CAAA;AAC9F,OAAO,oBAAoB,MAAM,qCAAqC,CAAA;AAQtE,eAAO,MAAM,kCAAkC,GAAI,SAAS,kBAAkB,EAC5E,gBAAgB,oBAAoB,EACpC,aAAa,WAAW,EACxB,kBAAkB,gBAAgB,KACjC,iBAuCF,CAAA;AAw0BD,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,kBAAkB,GAC1B,cAAc,CAIhB"}
1
+ {"version":3,"file":"ContactsCard.d.ts","sourceRoot":"","sources":["../src/ContactsCard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAElD,OAAO,EAAsB,gBAAgB,EAAE,WAAW,EAAa,MAAM,iBAAiB,CAAA;AAC9F,OAAO,oBAAoB,MAAM,qCAAqC,CAAA;AAUtE,eAAO,MAAM,kCAAkC,GAAI,SAAS,kBAAkB,EAC5E,gBAAgB,oBAAoB,EACpC,aAAa,WAAW,EACxB,kBAAkB,gBAAgB,KACjC,iBAuCF,CAAA;AAgvBD,eAAO,MAAM,yBAAyB,GACpC,SAAS,kBAAkB,EAC3B,kBAAkB,gBAAgB,EAClC,aAAa,WAAW,EACxB,wBAAwB,MAAM,EAC9B,2BAA2B,OAAO,KACjC,OAkEF,CAAA;AAqDD,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,kBAAkB,GAC1B,cAAc,CAIhB"}
@@ -5,10 +5,13 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.createAddressBookUriSelectorDialog = void 0;
7
7
  exports.getButtonContainer = getButtonContainer;
8
+ exports.handleContactExistsByName = void 0;
8
9
  var _contactsHelpers = require("./contactsHelpers");
10
+ var _contactsPane = require("contacts-pane");
9
11
  var _buttonsHelper = require("./buttonsHelper");
10
12
  var _texts = require("./texts");
11
13
  var _contactsErrors = require("./contactsErrors");
14
+ var _rdflib = require("rdflib");
12
15
  const CONTACTS_POPUP_OVERLAY_ID = 'contacts-popup-overlay';
13
16
  const CONTACTS_OVERLAY_ACTIVE_CLASS = 'contactsOverlayActive';
14
17
  const createAddressBookUriSelectorDialog = (context, contactsModule, contactData, addressBooksData) => {
@@ -269,8 +272,8 @@ const createNewContactCreationButton = (context, contactsModule, addressBooksDat
269
272
  const setButtonOnClickHandler = async event => {
270
273
  event.preventDefault();
271
274
  const contactExistsByWebID = (0, _contactsHelpers.checkIfContactExistsByWebID)(addressBooksData, contactData.webID);
272
- const contactExistsByName = (0, _contactsHelpers.checkIfContactExistsByName)(addressBooksData, contactData.name);
273
- const contactExistsHandled = handleContactExists(context, contactsModule, addressBooksData, contactData, contactExistsByWebID, contactExistsByName);
275
+ const contactExistsByNameUri = (0, _contactsHelpers.checkIfContactExistsByName)(addressBooksData, contactData.name);
276
+ const contactExistsHandled = handleContactExistsFromNonRegisteredAddressBook(context, addressBooksData, contactData, contactExistsByWebID, contactExistsByNameUri);
274
277
  if (contactExistsHandled) return;
275
278
  let selectedAddressBookUri = null;
276
279
  let selectedGroupUris = [];
@@ -288,7 +291,7 @@ const createNewContactCreationButton = (context, contactsModule, addressBooksDat
288
291
  groupUris: selectedGroupUris
289
292
  };
290
293
  try {
291
- const contactUri = await (0, _contactsHelpers.createContactInAddressBook)(context, contactsModule, addressBooksData, contactData, selectedAddressBookUris);
294
+ const contactUri = await (0, _contactsHelpers.createContactInAddressBook)(context, contactsModule, contactData, selectedAddressBookUris);
292
295
  finalizeContactEntry(context, addressBooksData, contactData, contactUri);
293
296
  } catch (error) {
294
297
  (0, _contactsErrors.addErrorToErrorDisplay)(context, `${_texts.errorContactCreation}\n${error}`);
@@ -368,31 +371,35 @@ const createNewAddressBookForm = (context, addressBooksData, contactsModule, con
368
371
  const newAddressBookEventListener = async event => {
369
372
  event.preventDefault();
370
373
  let enteredAddressBookUri = null;
371
- let newGroupUri = null;
374
+ let newGroupNode = null;
372
375
  const addressNameField = context.dom.querySelector('#addressBookNameInput');
373
376
 
374
377
  // @ts-ignore
375
- const enteredAddressName = addressNameField.value;
378
+ const enteredAddressName = sanitizeInput(addressNameField.value);
379
+ // @ts-ignore
380
+ addressNameField.value = enteredAddressName;
376
381
  const addressContainerField = context.dom.querySelector('#addressBookContainerInput');
377
382
 
378
383
  // @ts-ignore
379
- const enteredAddressContainer = addressContainerField.value;
384
+ const enteredAddressContainer = sanitizeInput(addressContainerField.value);
385
+ // @ts-ignore
386
+ addressContainerField.value = enteredAddressContainer;
380
387
  const groupNameField = context.dom.querySelector('#groupNameInput');
381
388
  // @ts-ignore
382
- const enteredGroupName = groupNameField.value;
389
+ const enteredGroupName = sanitizeInput(groupNameField.value);
390
+ // @ts-ignore
391
+ groupNameField.value = enteredGroupName;
383
392
  if (enteredAddressName) {
384
393
  // add addressbook first
385
394
  try {
386
395
  enteredAddressBookUri = await (0, _contactsHelpers.handleAddressBookCreation)(context, enteredAddressContainer, enteredAddressName);
387
396
  const books = await (0, _contactsHelpers.addANewAddressBookUriToAddressBooks)(context, contactsModule, addressBooksData, enteredAddressBookUri);
388
397
  if (enteredGroupName) {
389
- newGroupUri = await contactsModule.createNewGroup({
390
- addressBookUri: enteredAddressBookUri,
391
- groupName: enteredGroupName
392
- });
398
+ const selectedAddressBookNode = new _rdflib.NamedNode(enteredAddressBookUri);
399
+ newGroupNode = await (0, _contactsPane.saveNewGroup)(selectedAddressBookNode, enteredGroupName);
393
400
  const groupAdded = await (0, _contactsHelpers.addGroupToAddressBookData)(addressBooksData, enteredAddressBookUri, {
394
401
  name: enteredGroupName,
395
- uri: newGroupUri
402
+ uri: newGroupNode.value
396
403
  });
397
404
  if (!groupAdded) {
398
405
  (0, _contactsErrors.addErrorToErrorDisplay)(context, _texts.errorGroupCreation);
@@ -416,7 +423,7 @@ const createNewAddressBookForm = (context, addressBooksData, contactsModule, con
416
423
  const groupCreationButton = context.dom.getElementById('contacts-create-group-button');
417
424
  groupCreationButton.remove();
418
425
  groupListDiv.appendChild(createGroupButton(context, {
419
- uri: newGroupUri,
426
+ uri: newGroupNode.value,
420
427
  name: enteredGroupName
421
428
  }));
422
429
  groupListDiv.appendChild(groupCreationButton);
@@ -465,6 +472,10 @@ const createNewAddressBookForm = (context, addressBooksData, contactsModule, con
465
472
  groupNameInputBox.placeholder = 'New group name';
466
473
  groupNameInputBox.classList.add('input', 'contactsGroupInput');
467
474
  groupNameInputBox.required = true;
475
+ const validationMessage = createValidationMessage(context);
476
+ attachSanitizingValidation(addressBookNameInputBox, validationMessage);
477
+ attachSanitizingValidation(addressBookContainerInputBox, validationMessage);
478
+ attachSanitizingValidation(groupNameInputBox, validationMessage);
468
479
  const submitButton = context.dom.createElement('button');
469
480
  submitButton.setAttribute('id', 'submit-addressbook');
470
481
  submitButton.setAttribute('role', 'button');
@@ -482,11 +493,13 @@ const createNewAddressBookForm = (context, addressBooksData, contactsModule, con
482
493
  newAddressBookForm.appendChild(addressBookContainerInputBox);
483
494
  newAddressBookForm.appendChild(groupNameLabel);
484
495
  newAddressBookForm.appendChild(groupNameInputBox);
496
+ newAddressBookForm.appendChild(validationMessage);
485
497
  newAddressBookForm.appendChild(submitButton);
486
498
  newAddressBookForm.addEventListener('submit', newAddressBookEventListener);
487
499
  return newAddressBookForm;
488
500
  };
489
501
  const createCloseButton = (context, element, specialClass) => {
502
+ const buttonID = `${element.id}-close-button`;
490
503
  const setButtonOnClickHandler = event => {
491
504
  event.preventDefault();
492
505
  if (element) {
@@ -499,7 +512,7 @@ const createCloseButton = (context, element, specialClass) => {
499
512
  }
500
513
  };
501
514
  const closeButton = context.dom.createElement('button');
502
- closeButton.setAttribute('id', 'close-addressbook');
515
+ closeButton.setAttribute('id', buttonID);
503
516
  closeButton.setAttribute('role', 'button');
504
517
  closeButton.setAttribute('type', 'button');
505
518
  const ariaLabel = specialClass === 'contactsCloseButton' ? 'Close contacts dialog' : 'Close dialog';
@@ -520,7 +533,9 @@ const createGroupNameForm = (context, contactsModule, addressBooksData, contactD
520
533
  });
521
534
  const groupNameField = context.dom.querySelector('#groupNameInput');
522
535
  // @ts-ignore
523
- const enteredGroupName = groupNameField.value;
536
+ const enteredGroupName = sanitizeInput(groupNameField.value);
537
+ // @ts-ignore
538
+ groupNameField.value = enteredGroupName;
524
539
  if (!selectedAddressBookUri) {
525
540
  (0, _contactsErrors.addErrorToErrorDisplay)(context, _texts.errorNotExistsAddressBookUri);
526
541
  return;
@@ -528,13 +543,11 @@ const createGroupNameForm = (context, contactsModule, addressBooksData, contactD
528
543
  if (enteredGroupName) {
529
544
  // add group first
530
545
  try {
531
- const newGroupUri = await contactsModule.createNewGroup({
532
- addressBookUri: selectedAddressBookUri,
533
- groupName: enteredGroupName
534
- });
546
+ const selectedAddressBookNode = new _rdflib.NamedNode(selectedAddressBookUri);
547
+ const newGroupNode = await (0, _contactsPane.saveNewGroup)(selectedAddressBookNode, enteredGroupName);
535
548
  const newGroup = {
536
549
  name: enteredGroupName,
537
- uri: newGroupUri
550
+ uri: newGroupNode.value
538
551
  };
539
552
  const wasUpdated = (0, _contactsHelpers.addGroupToAddressBookData)(addressBooksData, selectedAddressBookUri, newGroup);
540
553
  if (!wasUpdated) {
@@ -569,10 +582,13 @@ const createGroupNameForm = (context, contactsModule, addressBooksData, contactD
569
582
  groupNameInputBox.id = 'groupNameInput';
570
583
  groupNameInputBox.placeholder = 'New group name';
571
584
  groupNameInputBox.classList.add('input', 'contactsGroupInput');
585
+ const validationMessage = createValidationMessage(context);
586
+ attachSanitizingValidation(groupNameInputBox, validationMessage);
572
587
  const submitButton = createAddGroupButton(context, newGroupForm);
573
588
  const closeButton = createCloseButton(context, newGroupForm, 'contactsGroupCreationCloseButton');
574
589
  newGroupForm.appendChild(groupNameLabel);
575
590
  newGroupForm.appendChild(groupNameInputBox);
591
+ newGroupForm.appendChild(validationMessage);
576
592
  newGroupForm.appendChild(submitButton);
577
593
  newGroupForm.appendChild(closeButton);
578
594
  return newGroupForm;
@@ -593,75 +609,85 @@ const createAddGroupButton = (context, form) => {
593
609
  button.addEventListener('click', setButtonOnClickHandler);
594
610
  return button;
595
611
  };
596
- const handleContactExists = (context, contactsModule, addressBooksData, contactData, contactExistsByWebID, contactExistsByName) => {
612
+ const handleContactExistsFromNonRegisteredAddressBook = (context, addressBooksData, contactData, contactExistsByWebID, contactExistsByNameUri) => {
597
613
  if (contactExistsByWebID) {
598
614
  (0, _contactsErrors.addErrorToErrorDisplay)(context, _texts.contactExistsMessage);
599
615
  return true;
600
- } else if (contactExistsByName) {
601
- // need to disable and possibly grey out the dialog
602
- const selectorDialog = context.dom.getElementById('contacts-selector-dialog');
603
- const contactExistsDiv = context.dom.createElement('div');
604
- contactExistsDiv.setAttribute('role', 'alert');
605
- contactExistsDiv.setAttribute('aria-live', 'assertive');
606
- contactExistsDiv.setAttribute('tabindex', '0');
607
- contactExistsDiv.setAttribute('aria-label', 'Alert message indicating that the contact already exists');
608
- contactExistsDiv.setAttribute('id', 'contacts-contact-exists');
609
- contactExistsDiv.classList.add('contactsContactExistsAlert');
610
- contactExistsDiv.innerHTML = `${contactData.name} already exists. \n Do you want to add their WebID?`;
611
- const confirmButton = context.dom.createElement('button');
612
- confirmButton.setAttribute('id', 'contacts-confirm-add-webid-button');
613
- confirmButton.setAttribute('role', 'button');
614
- confirmButton.setAttribute('type', 'button');
615
- confirmButton.setAttribute('aria-label', 'Confirm adding the contact webID to the existing contact');
616
- confirmButton.setAttribute('tabindex', '0');
617
- confirmButton.classList.add('contactsConfirmButton');
618
- confirmButton.innerHTML = 'Yes';
619
- confirmButton.addEventListener('click', async event => {
620
- event.preventDefault();
621
- await (0, _contactsHelpers.addWebIDToExistingContact)(context, contactsModule, addressBooksData, contactData.webID, contactExistsByName);
622
- finalizeContactEntry(context, addressBooksData, contactData, addressBooksData.contactWebIDs.get(contactData.webID));
623
- (0, _contactsHelpers.refreshButton)(context, addressBooksData, contactData);
624
- });
625
- const cancelButton = context.dom.createElement('button');
626
- cancelButton.setAttribute('id', 'contacts-cancel-add-webid-button');
627
- cancelButton.setAttribute('role', 'button');
628
- cancelButton.setAttribute('type', 'button');
629
- cancelButton.setAttribute('aria-label', 'Cancel adding the contact webID to the existing contact');
630
- cancelButton.setAttribute('tabindex', '0');
631
- cancelButton.classList.add('contactsCancelButton');
632
- cancelButton.innerHTML = 'No';
633
- cancelButton.addEventListener('click', event => {
634
- event.preventDefault();
635
- selectorDialog.remove();
636
- (0, _buttonsHelper.complain)(getButtonContainer(context), context, 'Contact was not added');
637
- setTimeout(() => {
638
- (0, _buttonsHelper.clearPreviousMessage)(getButtonContainer(context));
639
- }, 2000);
640
- (0, _contactsHelpers.refreshButton)(context, addressBooksData, contactData);
641
- });
642
- const actionsDiv = context.dom.createElement('div');
643
- actionsDiv.setAttribute('id', 'contacts-contact-exists-actions');
644
- actionsDiv.setAttribute('role', 'group');
645
- actionsDiv.setAttribute('aria-label', 'Actions for existing contact alert');
646
- actionsDiv.setAttribute('tabindex', '0');
647
- actionsDiv.classList.add('contactsContactExistsActions');
648
- actionsDiv.appendChild(confirmButton);
649
- actionsDiv.appendChild(cancelButton);
650
- contactExistsDiv.appendChild(actionsDiv);
651
- showPopupOverlay(context);
652
- selectorDialog.appendChild(contactExistsDiv);
653
- return true;
616
+ } else if (contactExistsByNameUri) {
617
+ const fromRegisteredAddressBook = false;
618
+ const handled = handleContactExistsByName(context, addressBooksData, contactData, contactExistsByNameUri, fromRegisteredAddressBook);
619
+ return handled;
654
620
  }
655
621
  return false;
656
622
  };
623
+ const handleContactExistsByName = (context, addressBooksData, contactData, contactExistsByNameUri, fromRegisteredAddressBook) => {
624
+ const selectorDialog = context.dom.getElementById('contacts-selector-dialog');
625
+ const buttonContainer = getButtonContainer(context);
626
+ const contactExistsDiv = context.dom.createElement('div');
627
+ contactExistsDiv.setAttribute('role', 'alert');
628
+ contactExistsDiv.setAttribute('aria-live', 'assertive');
629
+ contactExistsDiv.setAttribute('tabindex', '0');
630
+ contactExistsDiv.setAttribute('aria-label', 'Alert message indicating that the contact already exists');
631
+ contactExistsDiv.setAttribute('id', 'contacts-contact-exists');
632
+ contactExistsDiv.classList.add('contactsContactExistsAlert');
633
+ contactExistsDiv.innerHTML = `${contactData.name} already exists. \n Do you want to add their WebID?`;
634
+ const confirmButton = context.dom.createElement('button');
635
+ confirmButton.setAttribute('id', 'contacts-confirm-add-webid-button');
636
+ confirmButton.setAttribute('role', 'button');
637
+ confirmButton.setAttribute('type', 'button');
638
+ confirmButton.setAttribute('aria-label', 'Confirm adding the contact webID to the existing contact');
639
+ confirmButton.setAttribute('tabindex', '0');
640
+ confirmButton.classList.add('contactsConfirmButton');
641
+ confirmButton.innerHTML = 'Yes';
642
+ confirmButton.addEventListener('click', async event => {
643
+ event.preventDefault();
644
+ await (0, _contactsHelpers.addWebIDToExistingContact)(context, contactData, contactExistsByNameUri);
645
+ contactExistsDiv.remove();
646
+ finalizeContactEntry(context, addressBooksData, contactData, addressBooksData.contactWebIDs.get(contactData.webID));
647
+ (0, _contactsHelpers.refreshButton)(context, addressBooksData, contactData);
648
+ });
649
+ const cancelButton = context.dom.createElement('button');
650
+ cancelButton.setAttribute('id', 'contacts-cancel-add-webid-button');
651
+ cancelButton.setAttribute('role', 'button');
652
+ cancelButton.setAttribute('type', 'button');
653
+ cancelButton.setAttribute('aria-label', 'Cancel adding the contact webID to the existing contact');
654
+ cancelButton.setAttribute('tabindex', '0');
655
+ cancelButton.classList.add('contactsCancelButton');
656
+ cancelButton.innerHTML = 'No';
657
+ cancelButton.addEventListener('click', event => {
658
+ event.preventDefault();
659
+ if (!fromRegisteredAddressBook) selectorDialog.remove();
660
+ contactExistsDiv.remove();
661
+ (0, _buttonsHelper.complain)(getButtonContainer(context), context, 'Contact was not added');
662
+ setTimeout(() => {
663
+ (0, _buttonsHelper.clearPreviousMessage)(getButtonContainer(context));
664
+ }, 2000);
665
+ (0, _contactsHelpers.refreshButton)(context, addressBooksData, contactData);
666
+ });
667
+ const actionsDiv = context.dom.createElement('div');
668
+ actionsDiv.setAttribute('id', 'contacts-contact-exists-actions');
669
+ actionsDiv.setAttribute('role', 'group');
670
+ actionsDiv.setAttribute('aria-label', 'Actions for existing contact alert');
671
+ actionsDiv.setAttribute('tabindex', '0');
672
+ actionsDiv.classList.add('contactsContactExistsActions');
673
+ actionsDiv.appendChild(confirmButton);
674
+ actionsDiv.appendChild(cancelButton);
675
+ contactExistsDiv.appendChild(actionsDiv);
676
+ showPopupOverlay(context);
677
+ if (fromRegisteredAddressBook) {
678
+ buttonContainer.appendChild(contactExistsDiv);
679
+ } else {
680
+ selectorDialog.appendChild(contactExistsDiv);
681
+ }
682
+ return true;
683
+ };
684
+ exports.handleContactExistsByName = handleContactExistsByName;
657
685
  const finalizeContactEntry = (context, addressBooksData, contactData, contactUri) => {
658
686
  addressBooksData.contactWebIDs.set(contactData.webID, contactUri);
659
687
  const selectorDialog = context.dom.getElementById('contacts-selector-dialog');
660
- selectorDialog.remove();
688
+ if (selectorDialog) selectorDialog.remove();
661
689
  const buttonContainer = getButtonContainer(context);
662
690
  (0, _buttonsHelper.mention)(buttonContainer, _texts.contactWasAddedSuccesMessage);
663
- const button = context.dom.getElementById('add-to-contacts-button');
664
- button.removeAttribute('disabled');
665
691
  setTimeout(() => {
666
692
  (0, _buttonsHelper.clearPreviousMessage)(buttonContainer);
667
693
  }, 2000);
@@ -718,4 +744,29 @@ const removePopupOverlayIfNoPopup = context => {
718
744
  const overlay = selectorDialog.querySelector(`#${CONTACTS_POPUP_OVERLAY_ID}`);
719
745
  if (overlay) overlay.remove();
720
746
  selectorDialog.classList.remove(CONTACTS_OVERLAY_ACTIVE_CLASS);
721
- };
747
+ };
748
+ /* Sanitization and validation */
749
+ function sanitizeInput(input) {
750
+ return (input || '').replace(/[^a-zA-Z0-9 ]+/g, '').replace(/\s+/g, ' ').trim();
751
+ }
752
+ function attachSanitizingValidation(input, feedbackElement) {
753
+ input.addEventListener('input', () => {
754
+ const rawValue = input.value;
755
+ const sanitizedValue = sanitizeInput(rawValue);
756
+ if (rawValue !== sanitizedValue) {
757
+ input.value = sanitizedValue;
758
+ input.setAttribute('aria-invalid', 'true');
759
+ feedbackElement.textContent = 'Only letters, numbers, and spaces are allowed.';
760
+ return;
761
+ }
762
+ input.removeAttribute('aria-invalid');
763
+ feedbackElement.textContent = '';
764
+ });
765
+ }
766
+ function createValidationMessage(context) {
767
+ const validationMessage = context.dom.createElement('p');
768
+ validationMessage.setAttribute('role', 'status');
769
+ validationMessage.setAttribute('aria-live', 'polite');
770
+ validationMessage.classList.add('contactsInputValidationMessage');
771
+ return validationMessage;
772
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"addMeToYourContacts.d.ts","sourceRoot":"","sources":["../src/addMeToYourContacts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,cAAc,EAAE,MAAM,UAAU,CAAA;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAElD,OAAO,EAAa,SAAS,EAAE,MAAM,QAAQ,CAAA;AAM7C,OAAO,EAAE,gBAAgB,EAAe,MAAM,iBAAiB,CAAA;AAI/D,OAAO,0BAA0B,CAAA;AACjC,OAAO,oBAAoB,MAAM,qCAAqC,CAAA;AAKtE,QAAA,MAAM,sBAAsB,GAC1B,SAAS,SAAS,EAClB,SAAS,kBAAkB,KAC1B,OAAO,CAAC,cAAc,CAmBxB,CAAA;AAED,QAAA,MAAM,+BAA+B,GACnC,SAAS,SAAS,EAClB,SAAS,kBAAkB,KAC1B,OAAO,CAAC,iBAAiB,CA2D3B,CAAA;AAED,iBAAe,cAAc,CAC3B,OAAO,EAAE,SAAS,EAClB,OAAO,EAAE,kBAAkB,EAC3B,cAAc,EAAE,oBAAoB,EACpC,gBAAgB,EAAE,gBAAgB,GACjC,OAAO,CAAC,IAAI,CAAC,CA0Bf;AAED,OAAO,EACL,sBAAsB,EACtB,+BAA+B,EAC/B,cAAc,EACf,CAAA"}
1
+ {"version":3,"file":"addMeToYourContacts.d.ts","sourceRoot":"","sources":["../src/addMeToYourContacts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,cAAc,EAAE,MAAM,UAAU,CAAA;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAElD,OAAO,EAAa,SAAS,EAAE,MAAM,QAAQ,CAAA;AAM7C,OAAO,EAAE,gBAAgB,EAAe,MAAM,iBAAiB,CAAA;AAK/D,OAAO,0BAA0B,CAAA;AACjC,OAAO,oBAAoB,MAAM,qCAAqC,CAAA;AAMtE,QAAA,MAAM,sBAAsB,GAC1B,SAAS,SAAS,EAClB,SAAS,kBAAkB,KAC1B,OAAO,CAAC,cAAc,CAmBxB,CAAA;AAED,QAAA,MAAM,+BAA+B,GACnC,SAAS,SAAS,EAClB,SAAS,kBAAkB,KAC1B,OAAO,CAAC,iBAAiB,CA2D3B,CAAA;AAED,iBAAe,cAAc,CAC3B,OAAO,EAAE,SAAS,EAClB,OAAO,EAAE,kBAAkB,EAC3B,cAAc,EAAE,oBAAoB,EACpC,gBAAgB,EAAE,gBAAgB,GACjC,OAAO,CAAC,IAAI,CAAC,CA4Bf;AAED,OAAO,EACL,sBAAsB,EACtB,+BAA+B,EAC/B,cAAc,EACf,CAAA"}
@@ -14,6 +14,7 @@ var _texts = require("./texts");
14
14
  require("./styles/ProfileCard.css");
15
15
  var _contactsRdflib = _interopRequireDefault(require("@solid-data-modules/contacts-rdflib"));
16
16
  var _contactsErrors = require("./contactsErrors");
17
+ var _ContactsCard = require("./ContactsCard");
17
18
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
18
19
  let buttonContainer = document.createElement('section');
19
20
  const addMeToYourContactsDiv = async (subject, context) => {
@@ -104,7 +105,9 @@ async function saveNewContact(subject, context, contactsModule, addressBooksData
104
105
  const contactData = await (0, _contactsHelpers.getContactData)(store, subject);
105
106
  const contactExistsByNameUri = (0, _contactsHelpers.checkIfContactExistsByName)(addressBooksData, contactData.name);
106
107
  if (contactExistsByNameUri) {
107
- await (0, _contactsHelpers.addWebIDToExistingContact)(context, contactsModule, addressBooksData, contactData.webID, contactExistsByNameUri);
108
+ const fromRegisteredAddressBook = true;
109
+ const handled = (0, _ContactsCard.handleContactExistsByName)(context, addressBooksData, contactData, contactExistsByNameUri, fromRegisteredAddressBook);
110
+ if (!handled) (0, _contactsErrors.addErrorToErrorDisplay)(context, _texts.errorAddingContactWebIDToAddressBook);
108
111
  } else {
109
112
  await (0, _contactsHelpers.addContactToAddressBook)(context, contactsModule, contactData, addressBooksData, buttonContainer);
110
113
  }
@@ -10,13 +10,13 @@ declare function addANewAddressBookUriToAddressBooks(context: DataBrowserContext
10
10
  addressBooksData: AddressBooksData;
11
11
  addressBook: AddressBookDetails;
12
12
  }>;
13
- declare function createContactInAddressBook(context: DataBrowserContext, contactsModule: ContactsModuleRdfLib, addressBooksData: AddressBooksData, contactData: ContactData, selectedAddressBookUris: SelectedAddressBookUris): Promise<string>;
13
+ declare function createContactInAddressBook(context: DataBrowserContext, contactsModule: ContactsModuleRdfLib, contactData: ContactData, selectedAddressBookUris: SelectedAddressBookUris): Promise<string>;
14
14
  declare function addAddressToTypeIndex(context: DataBrowserContext, typeOfIndex: string, addressBookUri: string): Promise<boolean>;
15
15
  declare function updateAddressBookName(context: DataBrowserContext, addressBookUri: string, newName: string): Promise<void>;
16
16
  declare function refreshButton(context: DataBrowserContext, addressBooksData: AddressBooksData, contactData: ContactData): void;
17
17
  declare function checkIfContactExistsByWebID(addressBooksData: AddressBooksData, subjectUri: string): boolean;
18
18
  declare function checkIfContactExistsByName(addressBooksData: AddressBooksData, name: string): string | null;
19
- declare function addWebIDToExistingContact(context: DataBrowserContext, contactsModule: ContactsModuleRdfLib, addressBooksData: AddressBooksData, webID: string, contactUri: string): Promise<void>;
19
+ declare function addWebIDToExistingContact(context: DataBrowserContext, contactData: ContactData, contactUri: string): Promise<void>;
20
20
  declare function addGroupToAddressBookData(addressBooksData: AddressBooksData, addressBookUri: string, group: GroupData): boolean;
21
21
  declare function handleAddressBookCreation(dataBrowserContext: DataBrowserContext, containerName: string, enteredAddressName: string): Promise<string>;
22
22
  export { getAddressBooksData, getContactData, addContactToAddressBook, createContactInAddressBook, addAddressToTypeIndex, refreshButton, checkIfContactExistsByWebID, checkIfContactExistsByName, addWebIDToExistingContact, addANewAddressBookUriToAddressBooks, addGroupToAddressBookData, updateAddressBookName, handleAddressBookCreation };
@@ -1 +1 @@
1
- {"version":3,"file":"contactsHelpers.d.ts","sourceRoot":"","sources":["../src/contactsHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAoB,MAAM,QAAQ,CAAA;AAE/D,OAAO,oBAAoB,MAAM,qCAAqC,CAAA;AAEtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAElD,OAAO,2BAA2B,CAAA;AAElC,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,WAAW,EAAgB,SAAS,EAAgB,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AAMnJ,iBAAe,uBAAuB,CACpC,OAAO,EAAE,kBAAkB,EAC3B,cAAc,EAAE,oBAAoB,EACpC,WAAW,EAAE,WAAW,EACxB,gBAAgB,EAAE,gBAAgB,EAClC,SAAS,EAAE,cAAc,iBAM1B;AAgHD,iBAAe,mBAAmB,CAChC,OAAO,EAAE,kBAAkB,EAC3B,aAAa,EAAE,oBAAoB,GAClC,OAAO,CAAC,gBAAgB,CAAC,CAY3B;AAkBD,iBAAe,cAAc,CAC3B,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,SAAS,GACjB,OAAO,CAAC,WAAW,CAAC,CA8BtB;AAED,iBAAe,mCAAmC,CAChD,OAAO,EAAC,kBAAkB,EAC1B,cAAc,EAAE,oBAAoB,EACpC,gBAAgB,EAAE,gBAAgB,EAClC,qBAAqB,EAAE,MAAM,GAC5B,OAAO,CAAC;IAAE,gBAAgB,EAAE,gBAAgB,CAAC;IAAC,WAAW,EAAE,kBAAkB,CAAA;CAAE,CAAC,CA2BlF;AAED,iBAAe,0BAA0B,CACvC,OAAO,EAAE,kBAAkB,EAC3B,cAAc,EAAE,oBAAoB,EACpC,gBAAgB,EAAE,gBAAgB,EAClC,WAAW,EAAE,WAAW,EACxB,uBAAuB,EAAE,uBAAuB,GAC/C,OAAO,CAAC,MAAM,CAAC,CAwBjB;AAqFD,iBAAe,qBAAqB,CAClC,OAAO,EAAE,kBAAkB,EAC3B,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,OAAO,CAAC,CAuBlB;AAED,iBAAe,qBAAqB,CAClC,OAAO,EAAE,kBAAkB,EAC3B,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,MAAM,iBA0BhB;AAED,iBAAS,aAAa,CACpB,OAAO,EAAE,kBAAkB,EAC3B,gBAAgB,EAAE,gBAAgB,EAClC,WAAW,EAAE,WAAW,QAuBvB;AAEH,iBAAS,2BAA2B,CAClC,gBAAgB,EAAE,gBAAgB,EAClC,UAAU,EAAE,MAAM,GACjB,OAAO,CAGT;AAED,iBAAS,0BAA0B,CACjC,gBAAgB,EAAE,gBAAgB,EAClC,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,IAAI,CAYf;AAED,iBAAe,yBAAyB,CACtC,OAAO,EAAE,kBAAkB,EAC3B,cAAc,EAAE,oBAAoB,EACpC,gBAAgB,EAAE,gBAAgB,EAClC,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,iBASnB;AA6CD,iBAAS,yBAAyB,CAChC,gBAAgB,EAAE,gBAAgB,EAClC,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,SAAS,GACf,OAAO,CA0BT;AAED,iBAAe,yBAAyB,CACtC,kBAAkB,EAAE,kBAAkB,EACtC,aAAa,EAAE,MAAM,EACrB,kBAAkB,EAAE,MAAM,GACzB,OAAO,CAAC,MAAM,CAAC,CAsCjB;AAED,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,EACrB,aAAa,EACb,2BAA2B,EAC3B,0BAA0B,EAC1B,yBAAyB,EACzB,mCAAmC,EACnC,yBAAyB,EACzB,qBAAqB,EACrB,yBAAyB,EAC1B,CAAA"}
1
+ {"version":3,"file":"contactsHelpers.d.ts","sourceRoot":"","sources":["../src/contactsHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAoB,MAAM,QAAQ,CAAA;AAE/D,OAAO,oBAAoB,MAAM,qCAAqC,CAAA;AAEtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAElD,OAAO,2BAA2B,CAAA;AAElC,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,WAAW,EAAgB,SAAS,EAAgB,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AAMnJ,iBAAe,uBAAuB,CACpC,OAAO,EAAE,kBAAkB,EAC3B,cAAc,EAAE,oBAAoB,EACpC,WAAW,EAAE,WAAW,EACxB,gBAAgB,EAAE,gBAAgB,EAClC,SAAS,EAAE,cAAc,iBAM1B;AAgGD,iBAAe,mBAAmB,CAChC,OAAO,EAAE,kBAAkB,EAC3B,aAAa,EAAE,oBAAoB,GAClC,OAAO,CAAC,gBAAgB,CAAC,CAY3B;AAkBD,iBAAe,cAAc,CAC3B,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,SAAS,GACjB,OAAO,CAAC,WAAW,CAAC,CA8BtB;AAED,iBAAe,mCAAmC,CAChD,OAAO,EAAC,kBAAkB,EAC1B,cAAc,EAAE,oBAAoB,EACpC,gBAAgB,EAAE,gBAAgB,EAClC,qBAAqB,EAAE,MAAM,GAC5B,OAAO,CAAC;IAAE,gBAAgB,EAAE,gBAAgB,CAAC;IAAC,WAAW,EAAE,kBAAkB,CAAA;CAAE,CAAC,CA2BlF;AAED,iBAAe,0BAA0B,CACvC,OAAO,EAAE,kBAAkB,EAC3B,cAAc,EAAE,oBAAoB,EACpC,WAAW,EAAE,WAAW,EACxB,uBAAuB,EAAE,uBAAuB,GAC/C,OAAO,CAAC,MAAM,CAAC,CA0BjB;AA0CD,iBAAe,qBAAqB,CAClC,OAAO,EAAE,kBAAkB,EAC3B,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,OAAO,CAAC,CAuBlB;AAED,iBAAe,qBAAqB,CAClC,OAAO,EAAE,kBAAkB,EAC3B,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,MAAM,iBA0BhB;AAED,iBAAS,aAAa,CACpB,OAAO,EAAE,kBAAkB,EAC3B,gBAAgB,EAAE,gBAAgB,EAClC,WAAW,EAAE,WAAW,QAwBvB;AAEH,iBAAS,2BAA2B,CAClC,gBAAgB,EAAE,gBAAgB,EAClC,UAAU,EAAE,MAAM,GACjB,OAAO,CAGT;AAED,iBAAS,0BAA0B,CACjC,gBAAgB,EAAE,gBAAgB,EAClC,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,IAAI,CAYf;AAED,iBAAe,yBAAyB,CACtC,OAAO,EAAE,kBAAkB,EAC3B,WAAW,EAAE,WAAW,EACxB,UAAU,EAAE,MAAM,iBAUnB;AAED,iBAAS,yBAAyB,CAChC,gBAAgB,EAAE,gBAAgB,EAClC,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,SAAS,GACf,OAAO,CA0BT;AASD,iBAAe,yBAAyB,CACtC,kBAAkB,EAAE,kBAAkB,EACtC,aAAa,EAAE,MAAM,EACrB,kBAAkB,EAAE,MAAM,GACzB,OAAO,CAAC,MAAM,CAAC,CA8CjB;AAED,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,EACrB,aAAa,EACb,2BAA2B,EAC3B,0BAA0B,EAC1B,yBAAyB,EACzB,mCAAmC,EACnC,yBAAyB,EACzB,qBAAqB,EACrB,yBAAyB,EAC1B,CAAA"}
@@ -24,8 +24,8 @@ var _solidLogic = require("solid-logic");
24
24
  var _texts = require("./texts");
25
25
  var _buttonsHelper = require("./buttonsHelper");
26
26
  var _contactsErrors = require("./contactsErrors");
27
- var _contactsPane = _interopRequireDefault(require("contacts-pane"));
28
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
27
+ var _contactsPane = _interopRequireWildcard(require("contacts-pane"));
28
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
29
29
  async function addContactToAddressBook(context, contactsModule, contactData, addressBooksData, container) {
30
30
  const addressBookUriSelectorDialog = (0, _ContactsCard.createAddressBookUriSelectorDialog)(context, contactsModule, contactData, addressBooksData);
31
31
  container.appendChild(addressBookUriSelectorDialog);
@@ -63,15 +63,6 @@ async function getWebID(context, contact) {
63
63
  async function getAddressBooks(context, contactsModule) {
64
64
  const allContacts = [];
65
65
  const me = _solidLogic.authn.currentUser();
66
- const dom = context.dom;
67
- const div = dom.getElementById('add-to-contacts-button-container');
68
- const contextForFindAppInstances = {
69
- target: me,
70
- me,
71
- noun: 'address book',
72
- div,
73
- dom
74
- };
75
66
  let addressBooksData = {
76
67
  public: new Map(),
77
68
  private: new Map(),
@@ -80,14 +71,7 @@ async function getAddressBooks(context, contactsModule) {
80
71
  };
81
72
  try {
82
73
  await context.session.store.fetcher.load(me);
83
- const addressBookContext = await _solidUi.login.findAppInstances(contextForFindAppInstances, _solidUi.ns.vcard('AddressBook'));
84
- const addressBookNodes = addressBookContext.instances;
85
- let addressBookUris = {
86
- publicUris: (addressBookNodes || []).map(node => node.value),
87
- privateUris: []
88
- };
89
- // let addressBookUris = await contactsModule.listAddressBooks(me.value)
90
-
74
+ let addressBookUris = await contactsModule.listAddressBooks(me.value);
91
75
  const publicAddressBookPromises = addressBookUris.publicUris.map(addressBook => getAddressData(context, contactsModule, addressBook));
92
76
  const publicAddressBooksData = await Promise.all(publicAddressBookPromises);
93
77
  publicAddressBooksData.map(addressBook => {
@@ -204,8 +188,9 @@ async function addANewAddressBookUriToAddressBooks(context, contactsModule, addr
204
188
  addressBook: contactsAddressBook
205
189
  };
206
190
  }
207
- async function createContactInAddressBook(context, contactsModule, addressBooksData, contactData, selectedAddressBookUris) {
191
+ async function createContactInAddressBook(context, contactsModule, contactData, selectedAddressBookUris) {
208
192
  let contactUri = null;
193
+ const store = context.session.store;
209
194
  const newContact = {
210
195
  name: contactData.name
211
196
  };
@@ -222,7 +207,8 @@ async function createContactInAddressBook(context, contactsModule, addressBooksD
222
207
  return;
223
208
  }
224
209
  await context.session.store.fetcher.load(contactUri);
225
- await addWebIDToContact(context, groupUris, contactUri, contactData.webID);
210
+ const contactNode = new _rdflib.NamedNode(contactUri);
211
+ await (0, _contactsPane.addWebIDToContacts)(contactNode, contactData.webID, _solidUi.ns.vcard('WebID'), store);
226
212
  if (contactData.emails.length || contactData.phoneNumbers.length) {
227
213
  await addContactDetails(context, contactUri, contactData);
228
214
  }
@@ -261,29 +247,6 @@ async function addContactDetails(context, contactUri, contactData) {
261
247
  (0, _contactsErrors.addErrorToErrorDisplay)(context, error);
262
248
  }
263
249
  }
264
- async function addWebIDToContact(context, groupUris, contactUri, webID) {
265
- const store = context.session.store;
266
- const contactNode = new _rdflib.NamedNode(contactUri);
267
- const webIDNode = (0, _rdflib.sym)(webID);
268
- const vcardURLNode = store.bnode();
269
- let groupUriNode = null;
270
- try {
271
- if (groupUris?.length) {
272
- for (const groupUri of groupUris) {
273
- await context.session.store.fetcher.load(groupUri);
274
- groupUriNode = new _rdflib.NamedNode(groupUri);
275
- const groupDoc = groupUriNode.doc();
276
- const deletions = context.session.store.statementsMatching(groupUriNode, _solidUi.ns.vcard('hasMember'), contactNode, groupDoc);
277
- const insertions = [(0, _rdflib.st)(groupUriNode, _solidUi.ns.vcard('hasMember'), webIDNode, groupDoc), (0, _rdflib.st)(webIDNode, _solidUi.ns.owl('sameAs'), contactNode, groupDoc)];
278
- await store.updater.update(deletions, insertions);
279
- }
280
- }
281
- const personInsertions = [(0, _rdflib.st)(contactNode, _solidUi.ns.vcard('url'), vcardURLNode, contactNode.doc()), (0, _rdflib.st)(vcardURLNode, _solidUi.ns.rdf('type'), _solidUi.ns.vcard('WebID'), contactNode.doc()), (0, _rdflib.st)(vcardURLNode, _solidUi.ns.vcard('value'), (0, _rdflib.literal)(webID), contactNode.doc())];
282
- await store.updater.update([], personInsertions);
283
- } catch (error) {
284
- (0, _contactsErrors.addErrorToErrorDisplay)(context, error);
285
- }
286
- }
287
250
  async function addAddressToTypeIndex(context, typeOfIndex, addressBookUri) {
288
251
  const store = context.session.store;
289
252
  const me = _solidLogic.authn.currentUser();
@@ -332,6 +295,7 @@ function refreshButton(context, addressBooksData, contactData) {
332
295
  //logged in and friend exists or friend was just added
333
296
  button.innerHTML = _texts.contactExistsAlreadyButtonText.toUpperCase();
334
297
  button.onclick = null;
298
+ button.setAttribute('disabled', '');
335
299
  } else if (contactExistsByName) {
336
300
  button.innerHTML = _texts.contactExistsAlreadyByNameButtonText.toUpperCase();
337
301
  button.removeAttribute('disabled');
@@ -358,52 +322,16 @@ function checkIfContactExistsByName(addressBooksData, name) {
358
322
  });
359
323
  return contactUri;
360
324
  }
361
- async function addWebIDToExistingContact(context, contactsModule, addressBooksData, webID, contactUri) {
325
+ async function addWebIDToExistingContact(context, contactData, contactUri) {
326
+ const store = context.session.store;
362
327
  try {
363
- const groupUris = await getGroupUrisForContact(contactsModule, addressBooksData, contactUri);
364
- await addWebIDToContact(context, groupUris, contactUri, webID);
328
+ await context.session.store.fetcher.load(contactUri);
329
+ const contactNode = new _rdflib.NamedNode(contactUri);
330
+ await (0, _contactsPane.addWebIDToContacts)(contactNode, contactData.webID, _solidUi.ns.vcard('WebID'), store);
365
331
  } catch (error) {
366
332
  (0, _contactsErrors.addErrorToErrorDisplay)(context, error);
367
333
  }
368
334
  }
369
- async function getGroupUrisForContact(contactsModule, addressBooksData, contactUri) {
370
- let groupUrisForContact = [];
371
- let addressBookForContact = null;
372
- let allGroupUrisForAddressBook = [];
373
- addressBooksData.public.forEach((book, uri) => {
374
- book.contacts.map(contact => {
375
- if (contact.uri === contactUri) {
376
- addressBookForContact = book;
377
- }
378
- });
379
- });
380
- addressBooksData.private.forEach((book, uri) => {
381
- book.contacts.map(contact => {
382
- if (contact.uri === contactUri) {
383
- addressBookForContact = book;
384
- }
385
- });
386
- });
387
- allGroupUrisForAddressBook = addressBookForContact.groups;
388
- const groupPromises = allGroupUrisForAddressBook.map(async group => {
389
- group = await contactsModule.readGroup(group.uri);
390
- return {
391
- groupUri: group.uri,
392
- group
393
- };
394
- });
395
- const groups = await Promise.all(groupPromises);
396
- groups.map(groupInfo => {
397
- groupInfo.group.members.map(contact => {
398
- if (contact.uri === contactUri) {
399
- if (!groupUrisForContact.includes(groupInfo.groupUri)) {
400
- groupUrisForContact.push(groupInfo.groupUri);
401
- }
402
- }
403
- });
404
- });
405
- return groupUrisForContact;
406
- }
407
335
  function addGroupToAddressBookData(addressBooksData, addressBookUri, group) {
408
336
  const publicAddressBook = addressBooksData.public.get(addressBookUri);
409
337
  if (publicAddressBook) {
@@ -429,6 +357,9 @@ function addGroupToAddressBookData(addressBooksData, addressBookUri, group) {
429
357
  }
430
358
  return false;
431
359
  }
360
+ function sanitizeAlphaNumericSpaces(input) {
361
+ return (input || '').replace(/[^a-zA-Z0-9 ]+/g, '').replace(/\s+/g, ' ').trim();
362
+ }
432
363
  async function handleAddressBookCreation(dataBrowserContext, containerName, enteredAddressName) {
433
364
  const me = _solidLogic.authn.currentUser();
434
365
  const newAddressContainer = me?.site()?.value;
@@ -438,8 +369,13 @@ async function handleAddressBookCreation(dataBrowserContext, containerName, ente
438
369
  if (!me || !newAddressContainer) {
439
370
  throw new Error(_texts.errorUnableToDetermineUserWorkspace);
440
371
  }
372
+ const sanitizedAddressName = sanitizeAlphaNumericSpaces(enteredAddressName);
373
+ if (!sanitizedAddressName) {
374
+ throw new Error('Address book name can only contain letters, numbers, and spaces');
375
+ }
376
+ const sanitizedContainerName = sanitizeAlphaNumericSpaces(containerName);
441
377
  const normalizedContainer = newAddressContainer.endsWith('/') ? newAddressContainer : `${newAddressContainer}/`;
442
- const addressBookSlug = (containerName || 'address-book').trim().toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') || 'address-book';
378
+ const addressBookSlug = (sanitizedContainerName || 'address-book').trim().toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]+/g, '-').replace(/^-+|-+$/g, '') || 'address-book';
443
379
  const newBase = `${normalizedContainer}${addressBookSlug}/`;
444
380
  const mintResult = await _contactsPane.default.mintNew(dataBrowserContext, {
445
381
  me,
@@ -447,10 +383,10 @@ async function handleAddressBookCreation(dataBrowserContext, containerName, ente
447
383
  div,
448
384
  newBase,
449
385
  instanceClass: _solidUi.ns.vcard('AddressBook'),
450
- instanceName: enteredAddressName
386
+ instanceName: sanitizedAddressName
451
387
  });
452
388
  addressBookUri = mintResult?.newInstance?.uri || `${newBase}index.ttl#this`;
453
- await updateAddressBookName(dataBrowserContext, addressBookUri, enteredAddressName);
389
+ await updateAddressBookName(dataBrowserContext, addressBookUri, sanitizedAddressName);
454
390
  } catch (error) {
455
391
  (0, _contactsErrors.addErrorToErrorDisplay)(dataBrowserContext, _texts.errorAddressBookCreation + '\n' + error);
456
392
  }