Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix(BB-644): Auto append new isbn identifier row #785

Merged
merged 6 commits into from
Mar 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 3 additions & 2 deletions src/client/entity-editor/identifier-editor/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,14 @@ export function removeIdentifierRow(rowId: number): Action {
* @param {string} value - The new value to be used for the identifier value.
* @param {number} suggestedType - The ID for the type suggested by the new
* value.
* @param {boolean} doDebounce - flag for debouncing
* @returns {Action} The resulting UPDATE_IDENTIFIER_VALUE action.
*/
export function debouncedUpdateIdentifierValue(
rowId: number, value: string, suggestedType: number
rowId: number, value: string, suggestedType: number, doDebounce = true
): Action {
return {
meta: {debounce: 'keystroke'},
meta: {debounce: doDebounce ? 'keystroke' : null},
payload: {
rowId,
suggestedType,
Expand Down
26 changes: 19 additions & 7 deletions src/client/entity-editor/identifier-editor/identifier-row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ import {
IdentifierType,
validateIdentifierValue
} from '../validators/common';
import {collapseWhiteSpaces, isbn10To13, isbn13To10} from '../../../common/helpers/utils';
import type {Dispatch} from 'redux';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import Select from 'react-select';
import ValueField from './value-field';
import {collapseWhiteSpaces} from '../../../common/helpers/utils';
import {connect} from 'react-redux';
import {faTimes} from '@fortawesome/free-solid-svg-icons';

Expand Down Expand Up @@ -140,17 +140,29 @@ function handleValueChange(
index: number,
types: Array<IdentifierType>
) {
let value = collapseWhiteSpaces(event.target.value);
let {value} = event.target;
value = collapseWhiteSpaces(value);
const guessedType =
data.guessIdentifierType(value, types);
if (guessedType) {
const result = new RegExp(guessedType.detectionRegex)
.exec(value);
const result = new RegExp(guessedType.detectionRegex).exec(value);
value = result[1];
if (guessedType.id === 9) {
const isbn10Type:any = types.find((el) => el.id === 10);
const isbn10 = isbn13To10(value);
if (isbn10) {
dispatch(debouncedUpdateIdentifierValue(index + 1, isbn10, isbn10Type, false));
}
}
if (guessedType.id === 10) {
const isbn13Type:any = types.find((el) => el.id === 9);
const isbn13 = isbn10To13(value);
if (isbn13) {
dispatch(debouncedUpdateIdentifierValue(index + 1, isbn10To13(value), isbn13Type, false));
}
}
}
return dispatch(
debouncedUpdateIdentifierValue(index, value, guessedType)
);
return dispatch(debouncedUpdateIdentifierValue(index, value, guessedType));
}


Expand Down
63 changes: 63 additions & 0 deletions src/common/helpers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,66 @@ export function getNextEnabledAndResultsArray(array, size) {
nextEnabled: false
};
}

/**
* Convert ISBN-10 to ISBN-13
* @param {string} isbn10 valid ISBN-10
* @returns {string} ISBN-13
*/

export function isbn10To13(isbn10:string):string | null {
const isbn10Regex = RegExp(/^(?=[0-9X]{10}$|(?=(?:[0-9]+[- ]){3})[- 0-9X]{13}$)[0-9]{1,5}[- ]?[0-9]+[- ]?[0-9]+[- ]?[0-9X]$/);
if (!isbn10Regex.test(isbn10)) {
return null;
}
const tempISBN10 = `${isbn10}`.replaceAll('-', '');
let totalSum = 0;

const isbn13 = `978${tempISBN10.substring(0, 9)}`;

for (let i = 0; i < 12; i++) {
totalSum += Number(isbn13.charAt(i)) * ((i % 2) === 0 ? 1 : 3);
}

const lastDigit = (10 - (totalSum % 10)) % 10;
return isbn13 + lastDigit;
}

/**
* Convert ISBN-13 to ISBN-10
* @param {string} isbn13 valid ISBN-13
* @returns {string} ISBN-10
*/

export function isbn13To10(isbn13:string):string | null {
const isbn13Regex = RegExp(/^(?=[0-9]{13}$|(?=(?:[0-9]+[- ]){1,4})[- 0-9]{14,17}$)978[- ]?[0-9]{1,5}[- ]?[0-9]+[- ]?[0-9]+[- ]?[0-9]$/);
if (!isbn13Regex.test(isbn13)) {
return null;
}
const tempISBN13 = isbn13.replaceAll('-', '');
let digits = [];
let sum = 0;
let chkDigit;

digits = `${tempISBN13}`.substring(3, 12).split('');

for (let i = 0; i < 9; i++) {
sum += digits[i] * (10 - i);
}

const chkTmp = 11 - (sum % 11);
switch (chkTmp) {
case 10:
chkDigit = 'X';
break;
case 11:
chkDigit = 0;
break;
default:
chkDigit = chkTmp;
break;
}
digits.push(chkDigit);

return digits.join('');
}
28 changes: 27 additions & 1 deletion test/src/server/helpers/utils.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {createPublisher, truncateEntities} from '../../../test-helpers/create-entities';
import {generateIdenfierState, getIdByField, parseLanguages, searchOption} from '../../../../src/server/helpers/utils';
import {getNextEnabledAndResultsArray, isbn10To13, isbn13To10} from '../../../../src/common/helpers/utils';

import chai from 'chai';
import {getNextEnabledAndResultsArray} from '../../../../src/common/helpers/utils';
import orm from '../../../bookbrainz-data';


Expand Down Expand Up @@ -62,6 +63,31 @@ describe('getNextEnabledAndResultsArray', () => {
});
});

describe('Convert ISBNs', () => {
it('should return null if isbn10 not valid', () => {
const isbn10 = '1-23-45678-9';
const result = isbn10To13(isbn10);
expect(result).to.null;
});
it('should return valid isbn13 from isbn10', () => {
const isbn10 = '1-23-456789-X';
const expectedResult = '9781234567897';
const result = isbn10To13(isbn10);
expect(result).to.equal(expectedResult);
});
it('should return null if isbn13 not valid', () => {
const isbn13 = '879-123-456-7897';
const result = isbn13To10(isbn13);
expect(result).to.null;
});
it('should return valid isbn10 from isbn13', () => {
const isbn13 = '978-1-23456-789-7';
const expectedResult = '123456789X';
const result = isbn13To10(isbn13);
expect(result).to.equal(expectedResult);
});
});

describe('getIdByField', () => {
after(truncateEntities);
it('should return null if item does not exists', async () => {
Expand Down