Skip to content

Commit

Permalink
persons v4 add--so far just copied of v3
Browse files Browse the repository at this point in the history
  • Loading branch information
chlohilt committed Oct 9, 2023
1 parent 38da897 commit e57d0eb
Show file tree
Hide file tree
Showing 10 changed files with 2,972 additions and 1,731 deletions.
117 changes: 117 additions & 0 deletions components/byu-personsv4-datasource.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* Copyright 2018 Brigham Young University
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import * as personsv4Source from '../lib/personsv4SearchDataSource'
import { LitElement, html } from '@polymer/lit-element'

const { CustomEvent } = window

const executePersonsv4Request = async (search, target, pageLink) => {
try {
const { next, prev, people } = await personsv4Source.search(search, pageLink)
target.dispatchEvent(new CustomEvent('byu-lookup-datasource-result', {
bubbles: true,
detail: people
}))
return { next, prev }
} catch (err) {
console.error(err)
target.dispatchEvent(new CustomEvent('byu-lookup-datasource-error', {
bubbles: true,
detail: err
}))
return { next: null, prev: null }
}
}

const setPendingSearch = (target) => {
const evtType = 'byu-lookup-datasource-searching'
const evt = new CustomEvent(evtType, { bubbles: true })
target.dispatchEvent(evt)
}

class ByuPersonsv4Datasource extends LitElement {
connectedCallback () {
super.connectedCallback()
personsv4Source.connect()
const evt = new CustomEvent('byu-lookup-datasource-register', { bubbles: true })
this.dispatchEvent(evt)
}

disconnectedCallback () {
super.disconnectedCallback()
personsv4Source.disconnect()
}

static get properties () {
return {
search: { type: String },
next: { type: String },
prev: { type: String }
}
}

render () {
if (!this.search) {
this.search = ''
}
const { label } = personsv4Source.resolveSearchType(this.search)
return html`${label}`
}

async performSearch (search) {
if (this.timeout) {
clearTimeout(this.timeout)
}
this.timeout = setTimeout(async () => {
setPendingSearch(this)
const { next, prev } = await executePersonsv4Request(search, this)
this.next = next
this.prev = prev
}, 100)
}

async nextPage () {
if (this.timeout) {
clearTimeout(this.timeout)
}
this.timeout = setTimeout(async () => {
if (this.next) {
setPendingSearch(this)
const { next, prev } = await executePersonsv4Request(this.search, this, this.next)
this.next = next
this.prev = prev
}
}, 100)
}

async prevPage () {
if (this.timeout) {
clearTimeout(this.timeout)
}
this.timeout = setTimeout(async () => {
if (this.prev) {
setPendingSearch(this)
const { next, prev } = await executePersonsv4Request(this.search, this, this.prev)
this.next = next
this.prev = prev
}
}, 100)
}
}

console.log('registering personsv4 datasource')
window.customElements.define('byu-personsv4-datasource', ByuPersonsv4Datasource)
5 changes: 5 additions & 0 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ <h1 slot="site-title">Demo: BYU Person Lookup Component</h1>

<div id="content">

<!-- <h2>PersonsV4 Lookup (not in production until March)</h2>-->
<!-- <byu-person-lookup id="lookup-3" context="directory">-->
<!-- <byu-personsv4-datasource></byu-personsv4-datasource>-->
<!-- </byu-person-lookup>-->

<h2>PersonsV3 Lookup</h2>
<byu-person-lookup id="lookup-3" context="directory">
<byu-personsv3-datasource></byu-personsv3-datasource>
Expand Down
82 changes: 41 additions & 41 deletions dist/byu-person-lookup-nomodule.min.js

Large diffs are not rendered by default.

32 changes: 16 additions & 16 deletions dist/byu-person-lookup-results-nomodule.min.js

Large diffs are not rendered by default.

46 changes: 23 additions & 23 deletions dist/byu-personsv2-datasource-nomodule.min.js

Large diffs are not rendered by default.

44 changes: 22 additions & 22 deletions dist/byu-personsv3-datasource-nomodule.min.js

Large diffs are not rendered by default.

165 changes: 165 additions & 0 deletions lib/parsePersonV4.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/*
* Copyright 2018 Brigham Young University
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import get from 'lodash.get'

const pickFirst = (acc, curr) => acc || curr

function parseLinks (links) {
const next = get(links, 'persons__next.href')
const prev = get(links, 'persons__prev.href')
return { next, prev }
}

function parseAddresses (addresses) {
if (addresses.metadata.validation_response.code !== 200) {
return null
}
return addresses.values
.filter(address => address.metadata.validation_response.code === 200)
.reduce((all, c) => {
const data = [
get(c, 'address_line_1.value', ''),
get(c, 'address_line_2.value', ''),
get(c, 'address_line_3.value', ''),
get(c, 'address_line_4.value', '')
].filter(l => l.trim().length > 0)
const key = {
'MAL': 'mailing',
'RES': 'residential',
'WRK': 'work',
'PRM': 'permanent'
}[c.address_type.value] || c.address_type.value
return Object.assign({}, all, { [key]: data })
}, {})
}

function parseBasic (basic) {
const name = get(basic, 'name_lnf.value', '')
const byuId = get(basic, 'byu_id.value', '')
const netId = get(basic, 'net_id.value', '')
const personId = get(basic, 'person_id.value', '')
return {
name,
byuId,
netId,
personId
}
}

function parseEmailAddresses (emailAddresses) {
if (emailAddresses.metadata.validation_response.code !== 200) {
return null
}
return emailAddresses.values.map(e => get(e, 'email_address.value', ''))
.filter(e => !!e)
.reduce(pickFirst, '')
}

function parsePhones (phones) {
if (phones.metadata.validation_response.code !== 200) {
return null
}
return phones.values.map(p => get(p, 'phone_number.value', ''))
.filter(p => !!p)
.reduce(pickFirst, '')
}

function parseEmployeeSummaries (employeeSummaries) {
if (employeeSummaries.metadata.validation_response.code !== 200) {
return null
}
return {
employeeStatus: get(employeeSummaries, 'employee_role.value'),
department: get(employeeSummaries, 'department.value'),
jobTitle: get(employeeSummaries, 'job_title.description')
}
}

function parseStudentSummaries (studentSummaries) {
if (studentSummaries.metadata.validation_response.code !== 200) {
return null
}
const studentStatus = get(studentSummaries, 'student_status.value')
return { studentStatus }
}

function pickAddress (addrs) {
if (!addrs) return []
if (addrs.mailing) return addrs.mailing
if (addrs.residential) return addrs.mailing
if (addrs.permanent) return addrs.permanent
return []
}

function isEmployee (results) {
if (results.employeeStatus) {
return /ACT|LEV/.test(results.employeeStatus)
}
return results.department && results.jobTitle
}

function buildAdditionalInfo (results) {
const workAddress = results.addresses.work ? results.addresses.work : []
return [
results.department,
results.jobTitle,
...workAddress
]
}

function parsePerson (data) {
const results = Object.assign(
{
addresses: parseAddresses(data.addresses),
email: parseEmailAddresses(data.email_addresses),
phone: parsePhones(data.phones)
},
parseBasic(data.basic),
parseEmployeeSummaries(data.employee_summary),
parseStudentSummaries(data.student_summary)
)
const address = pickAddress(results.addresses)
const {
email,
phone,
name,
byuId,
netId,
employeeStatus,
studentStatus
} = results
const showAdditionalInfo = isEmployee(results)
const additionalInfo = showAdditionalInfo ? buildAdditionalInfo(results) : []
return {
address,
email,
phone,
name,
byuId,
netId,
employeeStatus,
studentStatus,
showAdditionalInfo,
additionalInfo
}
}

export default function (data) {
const people = data.values.map(parsePerson)
const { next, prev } = parseLinks(data.links)
return { next, prev, people }
}
98 changes: 98 additions & 0 deletions lib/personsv4LookupDataSource.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* Copyright 2018 Brigham Young University
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import * as authn from '@byuweb/browser-oauth/byu-browser-oauth.mjs'
import parsePersonv4 from './parsePersonv4'

let authHeader = null
let observer = null

export function connect () {
if (!observer) {
observer = new authn.AuthenticationObserver(({ state, token, user, error }) => {
// React to change
authHeader = token ? token.authorizationHeader : null
})
}
}

function nameParams (search) {
let surname = ''
let restOfName = ''
if (/,/.test(search)) {
// Assume 'Last, First'
[surname, restOfName] = search.split(',').map(s => s.trim())
} else {
// Assume 'First Middle Last'
const words = search.split(' ')
surname = words.slice(-1)
restOfName = words.slice(0, -1).join(' ')
}
return `?surname=${surname}&rest_of_name=${restOfName}`
}

export function resolveSearchType (search) {
return search.length < 1
? { q: `?surname=${search}`, label: 'Search' }
: /^\d{3,9}$/.test(search)
? { q: `?byu_ids=${search}`, label: 'BYU ID' }
: /^[a-z][a-z0-9]{2,7}$/.test(search)
? { q: `?net_ids=${search}`, label: 'Net ID' }
: /^[^@]+@.+$/.test(search)
? { q: `?email_addresses.email_address=${search}`, label: 'Email' }
: /^[^ ]+ +[^ ]+[^0-9]*$/.test(search)
? { q: `${nameParams(search)}`, label: 'Name' }
: { q: `?surname=${search}`, label: 'Name' }
}

export async function search (searchText, pageLink) {
if (!authHeader) {
throw new Error('Not authenticated!')
}

const { q } = resolveSearchType(searchText)

const apiBase = 'https://api.byu.edu:443/byuapi/persons/v4/'

const init = {
method: 'GET',
headers: new window.Headers({ 'Authorization': authHeader })
}

const fieldSets = 'basic,addresses,email_addresses,phones,employee_summary,student_summary'

const url = pageLink || `${apiBase}${q}&field_sets=${fieldSets}&page_size=50`

const response = await window.fetch(url, init)

if (response.ok) {
const json = await response.json()
return parsePersonv4(json)
} else if (response.status === 404) {
return {}
}

const message = `Error ${response.status} while querying personsv4`
throw new Error(message)
}

// in disconnectedCallback():
export function disconnect () {
if (observer) {
observer.disconnect()
}
observer = null
}
Loading

0 comments on commit e57d0eb

Please sign in to comment.