Skip to content
This repository has been archived by the owner on Nov 16, 2023. It is now read-only.

Commit

Permalink
Merged PR 317534: MSPeoplePicker
Browse files Browse the repository at this point in the history
Implements `MSPeoplePicker` which is used to select personas by providing a list of `suggestedPersonas` in a `MSPersonaListView` under a badge field consisting of a text field which filters the `suggestedPersonas` and a list of badges which displays the list of `pickedPersonas`.

The text field can filter the `availablePersonas` or the delegate method `getSuggestedPersonasFromText` can be implemented to provide the list of `suggestedPersonas`. Once picked the personas will be displayed as an `MSBadgeView` which can be interacted with and removed.

- Updates to `MSBadgeField` included to make it work better with `MSPeoplePicker`. This includes the delegate not being required since `MSPeoplePicker` when set up with sufficient data will function as intended without most delegate methods implemented, making them optional.
- Small updates to `MSBadgeField` demo and clean up in `MSPersonaListView` demo.

![Screen Shot 2019-09-11 at 5.37.20 PM.png](https://onedrive.visualstudio.com/4dcbf0bc-c3cd-49c8-a7c3-ec1924691d9b/_apis/git/repositories/93ac71ee-b53a-4fc6-a8c4-d46a80d4ca39/pullRequests/317534/attachments/Screen%20Shot%202019-09-11%20at%205.37.20%20PM.png)

Related work items: #663382
  • Loading branch information
philworthington committed Jan 7, 2020
1 parent 5682636 commit 04dc7e7
Show file tree
Hide file tree
Showing 17 changed files with 679 additions and 101 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
B4414792228F6F740040E88E /* MSTableViewCellSampleData.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4414791228F6F740040E88E /* MSTableViewCellSampleData.swift */; };
B4414794228F6FDF0040E88E /* OtherCellsSampleData.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4414793228F6FDF0040E88E /* OtherCellsSampleData.swift */; };
B444D6B82183BA4B0002B4D4 /* MSBadgeViewDemoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B444D6B72183BA4B0002B4D4 /* MSBadgeViewDemoController.swift */; };
B4575C5122FB8B6900EBD0EB /* MSPeoplePickerDemoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4575C5022FB8B6900EBD0EB /* MSPeoplePickerDemoController.swift */; };
B45EB79221A4D047008646A2 /* MSBadgeFieldDemoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B45EB79121A4D047008646A2 /* MSBadgeFieldDemoController.swift */; };
B4946764220A4DF10059045E /* MSCollectionViewCellDemoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4946763220A4DF10059045E /* MSCollectionViewCellDemoController.swift */; };
B498141621E42C140077B48D /* MSTableViewCellDemoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B498141521E42C140077B48D /* MSTableViewCellDemoController.swift */; };
Expand Down Expand Up @@ -87,6 +88,7 @@
B4414791228F6F740040E88E /* MSTableViewCellSampleData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSTableViewCellSampleData.swift; sourceTree = "<group>"; };
B4414793228F6FDF0040E88E /* OtherCellsSampleData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OtherCellsSampleData.swift; sourceTree = "<group>"; };
B444D6B72183BA4B0002B4D4 /* MSBadgeViewDemoController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSBadgeViewDemoController.swift; sourceTree = "<group>"; };
B4575C5022FB8B6900EBD0EB /* MSPeoplePickerDemoController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSPeoplePickerDemoController.swift; sourceTree = "<group>"; };
B45EB79121A4D047008646A2 /* MSBadgeFieldDemoController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSBadgeFieldDemoController.swift; sourceTree = "<group>"; };
B4946763220A4DF10059045E /* MSCollectionViewCellDemoController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSCollectionViewCellDemoController.swift; sourceTree = "<group>"; };
B498141521E42C140077B48D /* MSTableViewCellDemoController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSTableViewCellDemoController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -254,6 +256,7 @@
A5DCA75D211E3A92005F4CB7 /* MSDrawerDemoController.swift */,
B4E8F65121CD9579008A1598 /* MSHUDDemoController.swift */,
A589F855211BA71000471C23 /* MSLabelDemoController.swift */,
B4575C5022FB8B6900EBD0EB /* MSPeoplePickerDemoController.swift */,
FD41C8F322E28EEB0086F899 /* MSNavigationControllerDemoController.swift */,
A5B6617523A4227300E801DD /* MSNotificationViewDemoController.swift */,
B4EF53C4215C45C400573E8F /* MSPersonaListViewDemoController.swift */,
Expand Down Expand Up @@ -458,6 +461,7 @@
FD7254ED21471A3F002F4069 /* MSDateTimePickerDemoController.swift in Sources */,
B4EF665B22974BF0007FEAB0 /* MSCollectionViewHeaderFooterViewDemoController.swift in Sources */,
B4EF66542295F1A8007FEAB0 /* MSTableViewHeaderFooterViewDemoController.swift in Sources */,
B4575C5122FB8B6900EBD0EB /* MSPeoplePickerDemoController.swift in Sources */,
B4946764220A4DF10059045E /* MSCollectionViewCellDemoController.swift in Sources */,
A5CEC21220E436F10016922A /* MasterViewController.swift in Sources */,
B498141621E42C140077B48D /* MSTableViewCellDemoController.swift in Sources */,
Expand Down
7 changes: 7 additions & 0 deletions OfficeUIFabric.Demo/OfficeUIFabric.Demo/DemoController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ class DemoController: UIViewController {
return button
}

func addDescription(text: String) {
let description = MSLabel(style: .subhead, colorStyle: .regular)
description.numberOfLines = 0
description.text = text
container.addArrangedSubview(description)
}

func addTitle(text: String) {
let titleLabel = MSLabel(style: .headline)
titleLabel.text = text
Expand Down
1 change: 1 addition & 0 deletions OfficeUIFabric.Demo/OfficeUIFabric.Demo/Demos.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ let demos: [(title: String, controllerClass: UIViewController.Type)] = [
("MSLabel", MSLabelDemoController.self),
("MSNavigationController", MSNavigationControllerDemoController.self),
("MSNotificationView", MSNotificationViewDemoController.self),
("MSPeoplePicker", MSPeoplePickerDemoController.self),
("MSPersonaListView", MSPersonaListViewDemoController.self),
("MSPopupMenuController", MSPopupMenuDemoController.self),
("MSSegmentedControl", MSSegmentedControlDemoController.self),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,28 +31,19 @@ class MSBadgeFieldDemoController: DemoController {
badgeField1.numberOfLines = 1
let badgeField2 = setupBadgeField(label: "Cc:", dataSources: badgeDataSources2)

let title1 = setupTitle(text: "Badge field with limited number of lines")
let title2 = setupTitle(text: "Badge field with unlimited number of lines")

container.addArrangedSubview(title1)
addDescription(text: "Badge field with limited number of lines")
container.addArrangedSubview(badgeField1)
container.addArrangedSubview(UIView())
container.addArrangedSubview(title2)
addDescription(text: "Badge field with unlimited number of lines")
container.addArrangedSubview(badgeField2)
}

func setupTitle(text: String) -> MSLabel {
let titleLabel = MSLabel(style: .subhead, colorStyle: .regular)
titleLabel.text = text
return titleLabel
}

private func setupBadgeField(label: String, dataSources: [MSBadgeViewDataSource]) -> MSBadgeField {
let badgeField = MSBadgeField()
badgeField.translatesAutoresizingMaskIntoConstraints = false
badgeField.hardBadgingCharacters = ",;"
badgeField.label = label
badgeField.delegate = self
badgeField.badgeFieldDelegate = self
badgeField.addBadges(withDataSources: dataSources)
return badgeField
}
Expand All @@ -66,4 +57,9 @@ extension MSBadgeFieldDemoController: MSBadgeFieldDelegate {
func badgeField(_ badgeField: MSBadgeField, shouldAddBadgeForBadgeDataSource badgeDataSource: MSBadgeViewDataSource) -> Bool {
return !badgeField.badgeDataSources.contains(where: { $0.text == badgeDataSource.text })
}

func badgeField(_ badgeField: MSBadgeField, didTapSelectedBadge badge: MSBadgeView) {
badge.isSelected = false
showMessage("\(badge.dataSource?.text ?? "A selected badge") was tapped")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class MSBadgeViewDemoController: DemoController {
func createBadge(text: String, style: MSBadgeView.Style, size: MSBadgeView.Size, isEnabled: Bool) -> MSBadgeView {
let badge = MSBadgeView(dataSource: MSBadgeViewDataSource(text: text, style: style, size: size))
badge.delegate = self
badge.isEnabled = isEnabled
badge.isActive = isEnabled
return badge
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//

import OfficeUIFabric
import UIKit

// MARK: PeoplePickerSampleData

class PeoplePickerSampleData {
struct Variant {
let description: String
let numberOfLines: Int
let pickedPersonas: [MSPersona]
let allowsPickedPersonasToAppearAsSuggested: Bool
let showsSearchDirectoryButton: Bool

init(description: String, numberOfLines: Int = 0, pickedPersonas: [MSPersona] = [], allowsPickedPersonasToAppearAsSuggested: Bool = true, showsSearchDirectoryButton: Bool = true) {
self.description = description
self.numberOfLines = numberOfLines
self.pickedPersonas = pickedPersonas
self.allowsPickedPersonasToAppearAsSuggested = allowsPickedPersonasToAppearAsSuggested
self.showsSearchDirectoryButton = showsSearchDirectoryButton
}
}

static let variants: [Variant] = [
Variant(description: "Standard implementation with one line of picked personas", numberOfLines: 1, pickedPersonas: [samplePersonas[0], samplePersonas[4], samplePersonas[11], samplePersonas[14]]),
Variant(description: "Doesn't allow picked personas to appear as suggested", pickedPersonas: [samplePersonas[0], samplePersonas[9]], allowsPickedPersonasToAppearAsSuggested: false),
Variant(description: "Hides search directory button", pickedPersonas: [samplePersonas[13]], showsSearchDirectoryButton: false),
Variant(description: "Includes callback when picking a suggested persona")
]
}

// MARK: - MSPeoplePickerDemoController

class MSPeoplePickerDemoController: DemoController {
var peoplePickers: [MSPeoplePicker] = []

override func viewDidLoad() {
super.viewDidLoad()

for (index, variant) in PeoplePickerSampleData.variants.enumerated() {
addDescription(text: variant.description)
addPeoplePicker(for: variant)
if index != PeoplePickerSampleData.variants.count - 1 {
container.addArrangedSubview(MSSeparator())
}
}
}

func addPeoplePicker(for variant: PeoplePickerSampleData.Variant) {
let peoplePicker = MSPeoplePicker()
peoplePicker.label = "Send to:"
peoplePicker.availablePersonas = samplePersonas
peoplePicker.pickedPersonas = variant.pickedPersonas
peoplePicker.showsSearchDirectoryButton = variant.showsSearchDirectoryButton
peoplePicker.numberOfLines = variant.numberOfLines
peoplePicker.allowsPickedPersonasToAppearAsSuggested = variant.allowsPickedPersonasToAppearAsSuggested
peoplePicker.showsSearchDirectoryButton = variant.showsSearchDirectoryButton
peoplePicker.delegate = self
peoplePickers.append(peoplePicker)
container.addArrangedSubview(peoplePicker)
}
}

// MARK: - MSPeoplePickerDemoController: MSPeoplePickerDelegate

extension MSPeoplePickerDemoController: MSPeoplePickerDelegate {
func peoplePicker(_ peoplePicker: MSPeoplePicker, personaFromText text: String) -> MSPersona {
return samplePersonas.first { return $0.name.lowercased() == text.lowercased() } ?? MSPersonaData(name: text)
}

func peoplePicker(_ peoplePicker: MSPeoplePicker, personaIsValid persona: MSPersona) -> Bool {
let availablePersonas = samplePersonas + searchDirectoryPersonas
return availablePersonas.contains { $0.name == persona.name }
}

func peoplePicker(_ peoplePicker: MSPeoplePicker, didPickPersona persona: MSPersona) {
if peoplePicker == peoplePickers.last {
showMessage("\(persona.name) was picked")
}
}

func peoplePicker(_ peoplePicker: MSPeoplePicker, didTapSelectedPersona persona: MSPersona) {
peoplePicker.badge(for: persona)?.isSelected = false
showMessage("\(persona.name) was tapped")
}

func peoplePicker(_ peoplePicker: MSPeoplePicker, searchDirectoryWithCompletion completion: @escaping ([MSPersona], Bool) -> Void) {
// Delay added for 2 seconds to demo activity indicator
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
let text = peoplePicker.textFieldContent.lowercased()
let personas = searchDirectoryPersonas.filter { $0.name.lowercased().contains(text) }
completion(personas, true)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ let samplePersonas: [MSPersonaData] = [
MSPersonaData(name: "Cecil Folk", subtitle: "Program Manager", avatarImage: UIImage(named: "avatar_cecil_folk"))
]

let searchDirectoryPersonas: [MSPersonaData] = [
MSPersonaData(name: "Celeste Burton", email: "[email protected]", subtitle: "Program Manager", avatarImage: UIImage(named: "avatar_celeste_burton")),
MSPersonaData(name: "Erik Nason", email: "[email protected]", subtitle: "Designer"),
MSPersonaData(name: "Miguel Garcia", email: "[email protected]", subtitle: "Software Engineer", avatarImage: UIImage(named: "avatar_miguel_garcia"))
]

class MSPersonaListViewDemoController: DemoController {
override func viewDidLoad() {
super.viewDidLoad()
Expand Down Expand Up @@ -61,12 +67,7 @@ extension MSPersonaListViewDemoController: MSPersonaListViewSearchDirectoryDeleg
func personaListSearchDirectory(_ personaListView: MSPersonaListView, completion: @escaping ((_ success: Bool) -> Void)) {
// Delay added for 2 seconds to demo activity indicator
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
let personas: [MSPersona] = [
MSPersonaData(name: "Celeste Burton", email: "[email protected]", subtitle: "Program Manager", avatarImage: UIImage(named: "avatar_celeste_burton")),
MSPersonaData(name: "Erik Nason", email: "[email protected]", subtitle: "Designer"),
MSPersonaData(name: "Miguel Garcia", email: "[email protected]", subtitle: "Software Engineer", avatarImage: UIImage(named: "avatar_miguel_garcia"))
]
personaListView.personaList = personas
personaListView.personaList = searchDirectoryPersonas
completion(true)
}
}
Expand Down
8 changes: 8 additions & 0 deletions OfficeUIFabric.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,13 @@
B46D3F91215056940029772C /* CharacterSet+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B46D3F90215056940029772C /* CharacterSet+Extension.swift */; };
B46D3F932151D95F0029772C /* MSPersonaCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B46D3F922151D95F0029772C /* MSPersonaCell.swift */; };
B46D3F9D215985AC0029772C /* MSPersonaListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B46D3F9C215985AC0029772C /* MSPersonaListView.swift */; };
B47B58B822F8E5840078DE38 /* MSPeoplePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = B47B58B722F8E5840078DE38 /* MSPeoplePicker.swift */; };
B483323321CC71940022B4CC /* MSHUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B483323221CC71940022B4CC /* MSHUDView.swift */; };
B483323521DEA8D70022B4CC /* MSHUD.swift in Sources */ = {isa = PBXBuildFile; fileRef = B483323421DEA8D70022B4CC /* MSHUD.swift */; };
B483323721DEB5A00022B4CC /* MSTouchForwardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B483323621DEB5A00022B4CC /* MSTouchForwardingView.swift */; };
B498141421E424920077B48D /* MSTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B498141321E424920077B48D /* MSTableViewCell.swift */; };
B4A8BBCD21BF6D6900D5E3ED /* MSBadgeStringExtractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4A8BBCC21BF6D6900D5E3ED /* MSBadgeStringExtractor.swift */; };
B4BA27882319DC0D0001563C /* MSPersonaBadgeViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4BA27872319DC0D0001563C /* MSPersonaBadgeViewDataSource.swift */; };
B4E782C12176AD5E00A7DFCE /* MSActionsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4E782C02176AD5E00A7DFCE /* MSActionsCell.swift */; };
B4E782C321793AB200A7DFCE /* MSActivityIndicatorCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4E782C221793AB200A7DFCE /* MSActivityIndicatorCell.swift */; };
B4E782C521793BB900A7DFCE /* MSActivityIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4E782C421793BB900A7DFCE /* MSActivityIndicatorView.swift */; };
Expand Down Expand Up @@ -337,11 +339,13 @@
B46D3F90215056940029772C /* CharacterSet+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CharacterSet+Extension.swift"; sourceTree = "<group>"; };
B46D3F922151D95F0029772C /* MSPersonaCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSPersonaCell.swift; sourceTree = "<group>"; };
B46D3F9C215985AC0029772C /* MSPersonaListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSPersonaListView.swift; sourceTree = "<group>"; };
B47B58B722F8E5840078DE38 /* MSPeoplePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSPeoplePicker.swift; sourceTree = "<group>"; };
B483323221CC71940022B4CC /* MSHUDView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSHUDView.swift; sourceTree = "<group>"; };
B483323421DEA8D70022B4CC /* MSHUD.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSHUD.swift; sourceTree = "<group>"; };
B483323621DEB5A00022B4CC /* MSTouchForwardingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSTouchForwardingView.swift; sourceTree = "<group>"; };
B498141321E424920077B48D /* MSTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSTableViewCell.swift; sourceTree = "<group>"; };
B4A8BBCC21BF6D6900D5E3ED /* MSBadgeStringExtractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSBadgeStringExtractor.swift; sourceTree = "<group>"; };
B4BA27872319DC0D0001563C /* MSPersonaBadgeViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSPersonaBadgeViewDataSource.swift; sourceTree = "<group>"; };
B4E782C02176AD5E00A7DFCE /* MSActionsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSActionsCell.swift; sourceTree = "<group>"; };
B4E782C221793AB200A7DFCE /* MSActivityIndicatorCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSActivityIndicatorCell.swift; sourceTree = "<group>"; };
B4E782C421793BB900A7DFCE /* MSActivityIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSActivityIndicatorView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -716,6 +720,8 @@
A578C4A12321CFD6002D5C40 /* MSAvatar.swift */,
B42661412148568800E25423 /* MSAvatarView.swift */,
B426613D214731D100E25423 /* MSInitialsView.swift */,
B47B58B722F8E5840078DE38 /* MSPeoplePicker.swift */,
B4BA27872319DC0D0001563C /* MSPersonaBadgeViewDataSource.swift */,
B46D3F922151D95F0029772C /* MSPersonaCell.swift */,
B46D3F9C215985AC0029772C /* MSPersonaListView.swift */,
B4EF53C2215AF1AB00573E8F /* MSPersona.swift */,
Expand Down Expand Up @@ -1283,6 +1289,7 @@
A5B6617323A41E2900E801DD /* MSNotificationView.swift in Sources */,
FD41C88622DD13230086F899 /* MSShyHeaderController.swift in Sources */,
FDFB8AF121361C9D0046850A /* MSCalendarViewDayMonthCell.swift in Sources */,
B47B58B822F8E5840078DE38 /* MSPeoplePicker.swift in Sources */,
FD41C89E22DD13230086F899 /* MSNavigationController.swift in Sources */,
FD4F2A20214AE20400C437D6 /* MSDatePickerController.swift in Sources */,
B4EF53C3215AF1AB00573E8F /* MSPersona.swift in Sources */,
Expand All @@ -1297,6 +1304,7 @@
A5B87B06211E23650038C37C /* UIView+Extensions.swift in Sources */,
FDCF7C7F21BB56740058E9E6 /* MSSegmentedControl.swift in Sources */,
A5961FA7218A2E4500E2A506 /* UIImage+Extensions.swift in Sources */,
B4BA27882319DC0D0001563C /* MSPersonaBadgeViewDataSource.swift in Sources */,
FD7DF06021FA83C900857267 /* MSTooltipPositionController.swift in Sources */,
FD56FD94219128BF0023C7EA /* MSDateTimePickerViewDataSource.swift in Sources */,
FD41C88822DD13230086F899 /* MSShyHeaderView.swift in Sources */,
Expand Down
Loading

0 comments on commit 04dc7e7

Please sign in to comment.