Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
247e4e6
Initial bcp work
f-osorio Jun 9, 2026
fb28e84
Fix date duplicating when present
f-osorio Jun 9, 2026
4d1714c
Input with multiple fields, works
f-osorio Jun 10, 2026
9ab6916
Add duplicate
f-osorio Jun 10, 2026
1e025a7
cleanup, start MARC updates
f-osorio Jun 10, 2026
46cc02c
fix issues related to deleting text
f-osorio Jun 10, 2026
c05da95
Update XML format when adding new stuff
f-osorio Jun 11, 2026
9cbc7e6
Deletable 4xx, start comparison
f-osorio Jun 12, 2026
4311b66
Fix not deleting things
f-osorio Jun 12, 2026
adeb215
More diffing
f-osorio Jun 15, 2026
144e9d3
More diffing
f-osorio Jun 16, 2026
ff1ed31
Format, deleting
f-osorio Jun 16, 2026
1046527
seperate $7s
f-osorio Jun 16, 2026
eba3f7d
Split $7s
f-osorio Jun 17, 2026
d2c8378
Add date from 1XX
f-osorio Jun 17, 2026
3b97a32
Add unit tests
f-osorio Jun 17, 2026
0483c4f
Add validation
f-osorio Jun 17, 2026
30a8e39
Gather 667, don't show `$d` button when it's false
f-osorio Jun 17, 2026
54b489f
Capture `667` incase something needs to happen with it.
f-osorio Jun 18, 2026
a0533ad
Fix date from 1xx, address existing $7
f-osorio Jun 23, 2026
05b203a
Update layout
f-osorio Jun 23, 2026
e5b5983
Add toggle for preferred
f-osorio Jun 23, 2026
a10509f
Redo how bcpcodes are added
f-osorio Jun 23, 2026
c0806c6
Updates to logic & tests
f-osorio Jun 24, 2026
01a97e6
Adding row and duplicating work
f-osorio Jun 24, 2026
adabf8e
Records with BCP information loaded better
f-osorio Jun 24, 2026
a48f5c8
Remove 667 "script not evaluated" not when refeval=true
f-osorio Jun 24, 2026
a28ebad
Button showing is stricter
f-osorio Jun 24, 2026
dbef65e
Add local validation
f-osorio Jun 24, 2026
f7088fb
Marc prevew working
f-osorio Jun 25, 2026
1655f93
Update associatedLang and styling
f-osorio Jun 25, 2026
6b8b80d
Fix some issues related to canceling a preview and then preview
f-osorio Jun 26, 2026
e3d308d
Adjust XML that gets sent for ingest
f-osorio Jun 26, 2026
ebc5109
Merge branch 'main' into edit-4XX-NAR
f-osorio Jun 26, 2026
07a8fec
Delete after making updates
f-osorio Jun 29, 2026
095b024
Reset and `doSearch()` on submit of Auth
f-osorio Jun 29, 2026
cb8d328
Don't assume assocuatedLanguage is present
f-osorio Jun 29, 2026
88b5ad9
Expand 667 note match
f-osorio Jun 29, 2026
31a4a66
Add button to open in FLIO
f-osorio Jun 30, 2026
879ead5
backup for marc preview
f-osorio Jun 30, 2026
cb65e54
Fix broken endpoint
f-osorio Jun 30, 2026
3be424a
Populate `bcpSelection` if record has preferred variants
f-osorio Jun 30, 2026
f6809dc
change 040 to `DLC`
f-osorio Jun 30, 2026
97be78e
Pressing `tab` will move to next 4XX in BCP view
f-osorio Jun 30, 2026
76b6122
Remove tabbing. Add `@focus`
f-osorio Jun 30, 2026
3e6872c
Fix issue when removing a row
f-osorio Jul 1, 2026
6b62598
Set 008/29 & expand 667 deletions
f-osorio Jul 1, 2026
26d3931
Start on new 667 note
f-osorio Jul 8, 2026
23df548
Building and adding new 667
f-osorio Jul 8, 2026
3cb0888
667 notes
f-osorio Jul 13, 2026
627be21
Adjust NAR creation
f-osorio Jul 13, 2026
dbc70eb
Fix for failing test
f-osorio Jul 13, 2026
955e673
Fix display of mixed rtl & lrt text
f-osorio Jul 13, 2026
e01fb1e
Scope the CSS
f-osorio Jul 13, 2026
a76eea5
Adjust FOLIO url
f-osorio Jul 14, 2026
42216fe
TODO
f-osorio Jul 14, 2026
9f1dd85
Fix cursor jump, adjust variants
f-osorio Jul 15, 2026
7f42b99
Hide `addDate` Button when there is a date
f-osorio Jul 15, 2026
e92e553
Works with Authorities 130 & nameTitle, adjust 667
f-osorio Jul 15, 2026
790ba71
Fix repeating 040$d
f-osorio Jul 15, 2026
46b04cd
use preprod
f-osorio Jul 16, 2026
1349d6b
Add BCP creation for new NARs
f-osorio Jul 22, 2026
7451a2c
Add selection
f-osorio Jul 22, 2026
42b6ec5
Don't show buttons if there are no languages for the BCP
f-osorio Jul 22, 2026
3ef0c6e
Tie in API
f-osorio Jul 22, 2026
a1743f4
Avoid multiple preferred for same language
f-osorio Jul 23, 2026
15f8a12
Add validation for dupe preferred BCPs
f-osorio Jul 23, 2026
2b772bc
Add 667 note
f-osorio Jul 23, 2026
829912e
Check if arabic comma should be used
f-osorio Jul 24, 2026
cb646f2
Always insert $d after $a,
f-osorio Jul 24, 2026
1df8301
Support adding 670s for new variants
f-osorio Jul 27, 2026
12a7024
670 input appears when duping
f-osorio Jul 27, 2026
0f27fa2
Adjust where "some non-latin..." note is added
f-osorio Jul 28, 2026
e55d878
Send cataloger id to backend with NAR
f-osorio Jul 28, 2026
a13e878
Fix extra variant field after "cancel"
f-osorio Jul 28, 2026
6f49b10
Merge branch 'main' into edit-4XX-NAR
f-osorio Jul 28, 2026
827bb6d
Update nar creation
f-osorio Jul 29, 2026
13c04a3
Remove `\u200E` from the marcXML
f-osorio Jul 29, 2026
0a651e6
Start adjusting note order
f-osorio Jul 29, 2026
9b44e42
Simplify appending stuff
f-osorio Jul 29, 2026
f62b745
Fix "Set BCP" starting with "Expand"
f-osorio Jul 30, 2026
09e4ed3
Add feedback link
f-osorio Jul 31, 2026
45d959c
Update
f-osorio Jul 31, 2026
c0eb5d5
Adjust for task group LCCN list
f-osorio Aug 3, 2026
14d21d0
Check 4xx has value before expanding
f-osorio Aug 4, 2026
63bc9ab
Fix leader and 008/29
f-osorio Aug 4, 2026
041ad41
Sort record after adjusting it
f-osorio Aug 4, 2026
e02e1c9
error message
f-osorio Aug 5, 2026
9da8641
Update 667 text
f-osorio Aug 5, 2026
7e76c48
Move pieces out of profile.js
f-osorio Aug 5, 2026
7e37dee
cleanup
f-osorio Aug 5, 2026
0296b1b
Adjust for failing tests
f-osorio Aug 5, 2026
833cd5b
Fix typing an an input field jumping ahead
f-osorio Aug 5, 2026
d698164
Work with TG lccn list
f-osorio Aug 5, 2026
7bb9f8a
Merge branch 'main' into edit-4XX-NAR
f-osorio Aug 6, 2026
e52b5f6
Prep for production
f-osorio Aug 6, 2026
31f31c2
collapse tg list
f-osorio Aug 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
290 changes: 290 additions & 0 deletions public/twain.xml

Large diffs are not rendered by default.

1,218 changes: 1,116 additions & 102 deletions src/components/panels/edit/modals/ComplexLookupModal.vue

Large diffs are not rendered by default.

288 changes: 234 additions & 54 deletions src/components/panels/edit/modals/NacoStubCreateModal.vue

Large diffs are not rendered by default.

82 changes: 41 additions & 41 deletions src/components/panels/edit/modals/NonLatinBulkModal.vue

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions src/components/panels/edit/modals/SubjectEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -1862,6 +1862,9 @@ export default {
this.contextData.type = types.includes("Hub") ? "bf:Hub" : types.includes("Work") ? "bf:Work" : "madsrdf:" + types[0]
this.contextData.typeFull = this.contextData.type.replace('madsrdf:', 'http://www.loc.gov/mads/rdf/v1#')

if (!Object.keys(this.pickLookup[this.pickPostion].extra).includes('collections')){
this.pickLookup[this.pickPostion].extra['collections'] = []
}
//Check if it's a Jurisdiction, and overwrite
if (this.pickLookup[this.pickPostion].extra['collections'] && this.pickLookup[this.pickPostion].extra['collections'].includes("http://id.loc.gov/authorities/names/collection_Jurisdictions")) {
this.contextData.type = "bf:Jursidiction"
Expand Down
1 change: 1 addition & 0 deletions src/lib/TG_LCCN_LIST.json

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions src/lib/iso_lang.json

Large diffs are not rendered by default.

323 changes: 282 additions & 41 deletions src/lib/utils_export.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import utilsRDF from './utils_rdf';
import utilsMisc from './utils_misc';
import utilsNetwork from './utils_network';
import utilsProfile from './utils_profile';
import utilsParse from './utils_parse';

import { parse, parse as parseEDTF } from 'edtf'

Expand Down Expand Up @@ -2250,27 +2251,25 @@ const utilsExport = {

let pos29 = "n"
// did they make a 4xx
if (fourXXParts && fourXXParts.a && add667){
pos29 = 'b'
}else if (fourXXParts && fourXXParts.a && !add667){
if (fourXXParts && fourXXParts.a && !add667){
pos29 = 'a'
}

let has667 = add667
// if there is a 667 in the extraMarcStatements then set it
for (let x of extraMarcStatements){
if (x.tag == '667' || x.fieldTag == '667'){
pos29 = 'b'
has667 = true
}
if (/5[0-9]{2}/.test(x.fieldTag) && pos29 == "n"){ // treat 5XX like 4XX
if (add667){
pos29 = 'b'
} else if (!add667){
pos29 = 'a'
}
}
}
// // if there is a 667 in the extraMarcStatements then set it
// for (let x of extraMarcStatements){
// if (x.tag == '667' || x.fieldTag == '667'){
// pos29 = 'b'
// has667 = true
// }
// if (/5[0-9]{2}/.test(x.fieldTag) && pos29 == "n"){ // treat 5XX like 4XX
// if (add667){
// pos29 = 'b'
// } else if (!add667){
// pos29 = 'a'
// }
// }
// }

// check again if they made a 4XX in the extraMarcStatements and there is no 667 then set it to a
for (let x of extraMarcStatements){
Expand Down Expand Up @@ -2504,13 +2503,13 @@ const utilsExport = {
for (let v of useValues){
let subfield = document.createElementNS(marcNamespace,"marcxml:subfield");
subfield.setAttribute( 'code', key)
subfield.innerHTML = v.replace(/[\r\n]+/g, ' ').trim()
subfield.innerHTML = v.replace(/[\r\n]+/g, ' ').replace('\u200E', '').trim()
fieldName4xx.appendChild(subfield)
fourXXSubfieldsValues.push(`$${key} ${v.replace(/[\r\n]+/g, ' ').trim()}`)
}
}
}

for (let key of Object.keys(fourXXParts)){
// only add the subfields
if (key.length == 1 && !isAlpha(key)){
Expand All @@ -2519,7 +2518,7 @@ const utilsExport = {
for (let v of useValues){
let subfield = document.createElementNS(marcNamespace,"marcxml:subfield");
subfield.setAttribute( 'code', key)
subfield.innerHTML = v.replace(/[\r\n]+/g, ' ').trim()
subfield.innerHTML = v.replace(/[\r\n]+/g, ' ').replace('\u200E', '').trim()
fieldName4xx.appendChild(subfield)
fourXXSubfieldsValues.push(`$${key} ${v.replace(/[\r\n]+/g, ' ').trim()}`)
}
Expand All @@ -2541,25 +2540,6 @@ const utilsExport = {
}



if (pos29 === 'b' && !useAdvancedMode){

let field667 = document.createElementNS(marcNamespace,"marcxml:datafield");
field667.setAttribute( 'tag', '667')
field667.setAttribute( 'ind1', ' ')
field667.setAttribute( 'ind2', ' ')
let field667a = document.createElementNS(marcNamespace,"marcxml:subfield");
field667a.setAttribute( 'code', 'a')
field667a.innerHTML = "Non-Latin script references not evaluated."
field667.appendChild(field667a)

rootEl.appendChild(field667)
marcTextArray.push({txt: this.buildMarcTxtLine('667', ' ', ' ', ['$a Non-Latin script references not evaluated.']), field: '667', fieldInt: 667})


}


let field670SubfieldsValues = []

let field670 = document.createElementNS(marcNamespace,"marcxml:datafield");
Expand Down Expand Up @@ -2645,7 +2625,7 @@ const utilsExport = {
if (key.length == 1){
let subfield = document.createElementNS(marcNamespace,"marcxml:subfield");
subfield.setAttribute( 'code', x[key][0])
subfield.innerHTML = x[key][1].replace(/[\r\n]+/g, ' ')
subfield.innerHTML = x[key][1].replace(/[\r\n]+/g, ' ').replace('\u200E', '')
field.appendChild(subfield)
useSubfieldsValues.push(`$${x[key][0]} ${x[key][1].replace(/[\r\n]+/g, ' ')}`)
hasValue = true
Expand Down Expand Up @@ -2693,7 +2673,268 @@ const utilsExport = {
console.log(xml)
return {xml: xml, text: marcTxt}

}
},


/**
* Adjust marc authority record for BCP codes and related changes
* @@param {Object} marcXML - XML Document of the record that is being adjusted
* @@param {Object} updates - The updates to apply to the record
* @@param {Array} target - List of lists: [MARC tag to look for, index of update to apply targat that matches next element, non-latin variant]
* @return {Array} two elements, the update MARCXML and the record in JSON that can be turned in HTML for display
*/
adjustAuthRecord: function (marcXML, updates, targets) {
let record = marcXML.getElementsByTagName('marcxml:record')[0]
record = record.cloneNode(true)

// make sure leader/05 is "c"
let leader = record.getElementsByTagName('marcxml:leader')[0]
let leaderString = leader.innerHTML
leaderString = leaderString.substring(0,5) + 'c' + leaderString.substring(6)
leader.innerHTML = leaderString

let marc667List = record.querySelectorAll('[tag="667"]')
let marc670List = record.querySelectorAll('[tag="670"]')


// Get the 667s, remove "...not evaluated..."
// remove
let target667s = []
for (let sixSixSeven of marc667List) {
if (/>non-latin script reference[s ]{1}/gi.test(sixSixSeven.innerHTML)) {
target667s.push(sixSixSeven)
} else if (sixSixSeven.innerHTML.includes('Non-Latin script variants with (bcp47) in subfield 7')) {
target667s.push(sixSixSeven)
} else if (sixSixSeven.innerHTML.includes('Non-Latin script variants coded for PCC testing')) {
target667s.push(sixSixSeven)
} else if (sixSixSeven.innerHTML.includes('script references evaluated')) { // 667 from strawn tool
target667s.push(sixSixSeven)
}
}

target667s.map(item => record.removeChild(item)) // remove existing notes, and add new note

// add test note
let testNote = document.createElementNS('http://www.loc.gov/MARC21/slim', 'marcxml:datafield')
testNote.setAttribute('tag', '667')
testNote.setAttribute('ind1', " ")
testNote.setAttribute('ind2', " ")
let testNoteA = document.createElementNS('http://www.loc.gov/MARC21/slim', 'marcxml:subfield');
testNoteA.setAttribute("code", 'a')
testNoteA.innerHTML = "Non-Latin script variants with (bcp47) in subfield 7 are for PCC testing. Please do not remove or edit 4XX fields that contain subfield 7."
testNote.appendChild(testNoteA)
record.appendChild(testNote)
marc667List = record.querySelectorAll('[tag="667"]') // update the list

// update 008 and 667 if non-latin references have been evaluated
if (updates.refEval) {
if (updates.refEval == true) {
let zeroZeroEight = record.querySelectorAll('[tag="008"]')[0]
let currentValue = zeroZeroEight.innerHTML
let updatedValue = utilsMisc.setCharAt(currentValue, 29, 'a')
zeroZeroEight.innerHTML = updatedValue
}

if (updates.refEval == 'some') {
let note = "Non-Latin script variants with (bcp47) in subfield 7 have been evaluated. Others have not yet been evaluated."
let someNote = document.createElementNS('http://www.loc.gov/MARC21/slim', 'marcxml:datafield')
someNote.setAttribute('tag', '667')
someNote.setAttribute('ind1', " ")
someNote.setAttribute('ind2', " ")
let someNoteA = document.createElementNS('http://www.loc.gov/MARC21/slim', 'marcxml:subfield');
someNoteA.setAttribute("code", 'a')
someNoteA.innerHTML = note
someNote.appendChild(someNoteA)
record.appendChild(someNote)
}
}

// 670 notes
for (let item of updates['source670s']) {
let note670 = document.createElementNS('http://www.loc.gov/MARC21/slim', 'marcxml:datafield')
note670.setAttribute('tag', '670')
note670.setAttribute('ind1', " ")
note670.setAttribute('ind2', " ")
for (let sub of Object.keys(item)) {
if (sub != 'note') {
let subfield = document.createElementNS('http://www.loc.gov/MARC21/slim', 'marcxml:subfield');
subfield.setAttribute("code", sub)
subfield.innerHTML = item[sub].trim()
note670.appendChild(subfield)
}
}
marc670List = record.querySelectorAll('[tag="667"]')
record.appendChild(note670)
}

// 040 if the last $d is DLC, don't add another one
let marc040 = record.querySelectorAll('[tag="040"]')[0]
let lastEl = Array.from(marc040.children).at(-1)
if (lastEl.textContent != "DLC") {
let new040D = document.createElementNS('http://www.loc.gov/MARC21/slim', 'marcxml:subfield');
new040D.setAttribute("code", 'd')
new040D.innerHTML = 'DLC'
marc040.appendChild(new040D)
}

let forDeletion = []

let langEval = []
let langUneval = []
for (let target of targets) {
let targetNameXML = record.querySelectorAll('[tag="' + target[0] + '"]')[target[1]]
let index = [].indexOf.call(record.children, targetNameXML)

if (!targetNameXML) {
targetNameXML = { 'children': [] }
for (let idx of Object.keys(updates)) {
if (idx.startsWith("##")) { break }
targetNameXML = record.querySelectorAll('[tag="' + target[0] + '"]')[idx]
index = [].indexOf.call(record.children, targetNameXML)
}
}

// Get the existing subfields
let existingCodes = {}
let evaluated = false
for (let child of targetNameXML.children) {
let code = child.getAttribute("code")
if (existingCodes[code]) {
existingCodes[code].push(child)
} else {
existingCodes[code] = [child]
}
}

// for additions add a fake target with an idx that will match that update
let idx = target[1]
let update = updates[idx]

if (update['subfield_7']) {
evaluated = true
langEval.push(...update['subfield_7'])
} else {
langUneval.push(update['subfield_a'])
}


if (Object.keys(update).includes('delete') && update.delete) {
forDeletion.push(targetNameXML)
} else {
let indicators = update.indicators.split("")
if (!String(target[1]).startsWith("##")) {
targetNameXML.setAttribute("ind1", indicators[0])
targetNameXML.setAttribute("ind2", indicators[1])

// existingCodes not present in the update
let deleteCodes = Object.keys(existingCodes).map(code => {
if (!Object.keys(update).includes('subfield_' + code)) {
return code
}
})

if (update.hasBCP) {
// delete existing $7
for (let existing7 of existingCodes['7']) {
targetNameXML.removeChild(existing7)
}
delete existingCodes['7']
}

for (let key of Object.keys(update)) {
if (key.includes('subfield_')) {
let subfield = key.split("_")[1]
let value = update[key]

// if we're looking at the first update
let targets = existingCodes[subfield]

if (targets) { // if the subfield is existing update it
for (let target of targets) {
target.innerHTML = value
for (let code of deleteCodes) {
if (code) {
for (let element of existingCodes[code]) {
if (targetNameXML.contains(element)) {
targetNameXML.removeChild(element)
}
}
}
}
}
} else { // otherwise, create it
if (typeof value == 'string') {
let newSubField = document.createElementNS('http://www.loc.gov/MARC21/slim', 'marcxml:subfield');
newSubField.setAttribute("code", subfield)
newSubField.innerHTML = value.trim()
targetNameXML.appendChild(newSubField)
} else {
for (let bcp of value) {
let newSubField = document.createElementNS('http://www.loc.gov/MARC21/slim', 'marcxml:subfield');
newSubField.setAttribute("code", subfield)
newSubField.innerHTML = bcp.trim()
targetNameXML.appendChild(newSubField)
}
}
}

}
}
} else { // it's a new field for the top element
let newField = document.createElementNS('http://www.loc.gov/MARC21/slim', 'marcxml:datafield')
newField.setAttribute('tag', update.tag)
newField.setAttribute('ind1', indicators[0])
newField.setAttribute('ind2', indicators[1])
record.appendChild(newField)

for (let [idx, key] of Object.keys(update).entries()) {
if (key.includes('subfield_')) {
let newSubField = document.createElementNS('http://www.loc.gov/MARC21/slim', 'marcxml:subfield');
let subfield = key.split("_")[1]
let value = update[key]


if (typeof value == 'string') {
newSubField.setAttribute("code", subfield)
newSubField.innerHTML = value.trim()
newField.appendChild(newSubField)
} else {
for (let i in value) {
let bcp = value[i]
let newSubField = document.createElementNS('http://www.loc.gov/MARC21/slim', 'marcxml:subfield');
newSubField.setAttribute("code", subfield)
newSubField.innerHTML = bcp.trim()
newField.appendChild(newSubField)
}
}
}
}

}
}
// }
}

// make deletions
for (let del of forDeletion) {
record.removeChild(del)
}

// sort the record by tag
let sortedChildren = Array.from(record.children).sort((a, b) => {
let tagA = a.getAttribute('tag');
let tagB = b.getAttribute('tag');
if (tagA < tagB) return -1;
if (tagA > tagB) return 1;
return 0;
});

record.innerHTML = ''; // Clear existing children
sortedChildren.forEach(child => record.appendChild(child))

let parsedRecord = utilsParse.parseMarcXml(record)
return [record, parsedRecord]
},

}

Expand Down
Loading
Loading