Skip to content

Commit

Permalink
Merge pull request #5120 from specify/issue-5114
Browse files Browse the repository at this point in the history
Define separate config for bulk carry forward
  • Loading branch information
CarolineDenis authored Jul 24, 2024
2 parents b317b91 + 53845cd commit 6a364e0
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -231,18 +231,18 @@ theories(parseJavaClassName, [
]);
describe('getCarryOverPreference', () => {
test('default carry over fields', () =>
expect(getCarryOverPreference(tables.SpQuery, true)).toEqual(
expect(getCarryOverPreference(tables.SpQuery, true, false)).toEqual(
getFieldsToClone(tables.SpQuery)
));
test('customize carry over fields', () => {
userPreferences.set('form', 'preferences', 'carryForward', {
Locality: ['localityName', 'text1'],
});
expect(getCarryOverPreference(tables.Locality, false)).toEqual([
expect(getCarryOverPreference(tables.Locality, false, false)).toEqual([
'localityName',
'text1',
]);
expect(getCarryOverPreference(tables.SpQuery, true)).toEqual(
expect(getCarryOverPreference(tables.SpQuery, true, false)).toEqual(
getFieldsToClone(tables.SpQuery)
);
});
Expand Down Expand Up @@ -289,7 +289,7 @@ test('getFieldsToNotClone', () => {
(name) => name !== 'text1'
) as RA<TableFields<CollectionObject>>,
});
expect(getFieldsToNotClone(tables.CollectionObject, true)).toEqual([
expect(getFieldsToNotClone(tables.CollectionObject, true, false)).toEqual([
'actualTotalCountAmt',
'catalogNumber',
'timestampModified',
Expand All @@ -302,7 +302,7 @@ test('getFieldsToNotClone', () => {
'currentDetermination',
'projects',
]);
expect(getFieldsToNotClone(tables.CollectionObject, false)).toEqual([
expect(getFieldsToNotClone(tables.CollectionObject, false, false)).toEqual([
'actualTotalCountAmt',
'catalogNumber',
'timestampModified',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,10 @@ export type SpecifyResource<SCHEMA extends AnySchema> = {
viewUrl(): string;
isNew(): boolean;
isBeingInitialized(): boolean;
clone(cloneAll: boolean): Promise<SpecifyResource<SCHEMA>>;
clone(
cloneAll: boolean,
isBulkCarry?: boolean
): Promise<SpecifyResource<SCHEMA>>;
// eslint-disable-next-line @typescript-eslint/naming-convention
toJSON(): SerializedRecord<AnySchema>;
getRelatedObjectCount(
Expand Down
14 changes: 10 additions & 4 deletions specifyweb/frontend/js_src/lib/components/DataModel/resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,10 @@ export const parseJavaClassName = (className: string): string =>

export function getFieldsToNotClone(
table: SpecifyTable,
cloneAll: boolean
cloneAll: boolean,
isBulkCarry: boolean
): RA<string> {
const fieldsToClone = getCarryOverPreference(table, cloneAll);
const fieldsToClone = getCarryOverPreference(table, cloneAll, isBulkCarry);
const uniqueFields = getUniqueFields(table);
return table.fields
.map(({ name }) => name)
Expand All @@ -247,11 +248,16 @@ export function getFieldsToNotClone(

function getCarryOverPreference(
table: SpecifyTable,
cloneAll: boolean
cloneAll: boolean,
isBulkCarry: boolean
): RA<string> {
const config: Partial<RR<keyof Tables, RA<string>>> = cloneAll
? {}
: userPreferences.get('form', 'preferences', 'carryForward');
: userPreferences.get(
'form',
'preferences',
isBulkCarry ? 'bulkCarryForward' : 'carryForward'
);
return config?.[table.name] ?? getFieldsToClone(table);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,14 @@ export const ResourceBase = Backbone.Model.extend({
handleChanged() {
this.needsSaved = true;
},
async clone(cloneAll = false) {
async clone(cloneAll = false, isBulkCarry = false) {
const self = this;

const exemptFields = getFieldsToNotClone(this.specifyTable, cloneAll).map(
(fieldName) => fieldName.toLowerCase()
);
const exemptFields = getFieldsToNotClone(
this.specifyTable,
cloneAll,
isBulkCarry
).map((fieldName) => fieldName.toLowerCase());

const newResource = new this.constructor(
removeKey(this.attributes, ...specialFields, ...exemptFields),
Expand Down
78 changes: 61 additions & 17 deletions specifyweb/frontend/js_src/lib/components/FormMeta/CarryForward.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,12 @@ export function CarryForwardConfig({
table,
parentTable,
type,
isBulkConfig,
}: {
readonly table: SpecifyTable;
readonly parentTable: SpecifyTable | undefined;
readonly type: 'button' | 'cog';
readonly isBulkConfig?: boolean;
}): JSX.Element | null {
const [isOpen, handleOpen, handleClose] = useBooleanState();
const [globalEnabled, setGlobalEnabled] = userPreferences.use(
Expand Down Expand Up @@ -128,9 +130,12 @@ export function CarryForwardConfig({
onClick={handleOpen}
/>
)}
{isCarryForwardEnabled ? <BulkCloneConfig table={table} /> : null}
{isCarryForwardEnabled ? (
<BulkCloneConfig parentTable={parentTable} table={table} />
) : null}
{isOpen && (
<CarryForwardConfigDialog
isBulkConfig={isBulkConfig}
parentTable={parentTable}
table={table}
onClose={handleClose}
Expand All @@ -149,8 +154,10 @@ const normalize = (fields: RA<string>): RA<string> =>
*/
function BulkCloneConfig({
table,
parentTable,
}: {
readonly table: SpecifyTable;
readonly parentTable: SpecifyTable | undefined;
}): JSX.Element | null {
const [globalBulkEnabled, setGlobalBulkEnabled] = userPreferences.use(
'form',
Expand All @@ -160,16 +167,35 @@ function BulkCloneConfig({

const isBulkCarryEnabled = globalBulkEnabled.includes(table.name);

const [isOpen, handleOpen, handleClose] = useBooleanState();

return tableValidForBulkClone(table) ? (
<Label.Inline className="rounded bg-[color:var(--foreground)]">
<Input.Checkbox
checked={isBulkCarryEnabled}
onChange={(): void =>
setGlobalBulkEnabled(toggleItem(globalBulkEnabled, table.name))
}
/>
{formsText.bulkCarryForwardEnabled()}
</Label.Inline>
<>
<Label.Inline className="rounded bg-[color:var(--foreground)]">
<Input.Checkbox
checked={isBulkCarryEnabled}
onChange={(): void =>
setGlobalBulkEnabled(toggleItem(globalBulkEnabled, table.name))
}
/>
{formsText.bulkCarryForwardEnabled()}
<Button.Small
className="ml-2"
title={formsText.bulkCarryForwardSettingsDescription()}
onClick={handleOpen}
>
{icons.cog}
</Button.Small>
</Label.Inline>
{isOpen && (
<CarryForwardConfigDialog
isBulkConfig
parentTable={parentTable}
table={table}
onClose={handleClose}
/>
)}
</>
) : null;
}

Expand All @@ -189,21 +215,25 @@ function CarryForwardConfigDialog({
table,
parentTable,
onClose: handleClose,
isBulkConfig,
}: {
readonly table: SpecifyTable;
readonly parentTable: SpecifyTable | undefined;
readonly onClose: () => void;
readonly isBulkConfig?: boolean;
}): JSX.Element {
const [showHiddenFields, setShowHiddenFields] = userPreferences.use(
'form',
'preferences',
'carryForwardShowHidden'
isBulkConfig === true
? 'bulkCarryForwardShowHidden'
: 'carryForwardShowHidden'
);

const [globalConfig, setGlobalConfig] = userPreferences.use(
'form',
'preferences',
'carryForward'
isBulkConfig === true ? 'bulkCarryForward' : 'carryForward'
);

const uniqueFields = getUniqueFields(table);
Expand Down Expand Up @@ -300,9 +330,15 @@ function CarryForwardConfigDialog({
</Submit.Info>
</>
}
header={formsText.carryForwardTableSettingsDescription({
tableName: table.label,
})}
header={
isBulkConfig === true
? formsText.bulkCarryForwardTableSettingsDescription({
tableName: table.label,
})
: formsText.carryForwardTableSettingsDescription({
tableName: table.label,
})
}
onClose={handleClose}
>
<Form className="overflow-hidden" id={id('form')} onSubmit={handleClose}>
Expand All @@ -311,6 +347,7 @@ function CarryForwardConfigDialog({
carryForward={config}
fields={literalFields}
header={schemaText.fields()}
isBulkConfig={isBulkConfig}
table={table}
uniqueFields={uniqueFields}
onChange={handleChange}
Expand All @@ -319,6 +356,7 @@ function CarryForwardConfigDialog({
carryForward={config}
fields={relationships}
header={schemaText.relationships()}
isBulkConfig={isBulkConfig}
table={table}
uniqueFields={uniqueFields}
onChange={handleChange}
Expand All @@ -343,20 +381,25 @@ function CarryForwardCategory({
uniqueFields,
carryForward,
onChange: handleChange,
isBulkConfig,
}: {
readonly header: string;
readonly table: SpecifyTable;
readonly fields: RA<LiteralField | Relationship>;
readonly uniqueFields: RA<string>;
readonly carryForward: RA<string>;
readonly onChange: (carryForward: RA<string>) => void;
readonly isBulkConfig?: boolean;
}): JSX.Element | null {
return fields.length > 0 ? (
<>
<H3>{header}</H3>
<Ul>
{fields.map((field) => {
const isUnique = uniqueFields.includes(field.name);
const isRequired =
isBulkConfig === true &&
(field.localization.isrequired || field.overrides.isRequired);
return (
<li className="flex gap-1" key={field.name}>
<Label.Inline
Expand All @@ -367,8 +410,8 @@ function CarryForwardCategory({
}
>
<Input.Checkbox
checked={f.includes(carryForward, field.name)}
disabled={isUnique}
checked={f.includes(carryForward, field.name) || isRequired}
disabled={isUnique || isRequired}
onValueChange={(isChecked): void => {
const dependents = filterArray(
Object.entries(dependentFields())
Expand All @@ -389,6 +432,7 @@ function CarryForwardCategory({
</Label.Inline>
{field.isRelationship && field.isDependent() && !isUnique ? (
<CarryForwardConfig
isBulkConfig={isBulkConfig}
parentTable={field.table}
table={field.relatedTable}
type="cog"
Expand Down
5 changes: 4 additions & 1 deletion specifyweb/frontend/js_src/lib/components/Forms/Save.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,10 @@ export function SaveButton<SCHEMA extends AnySchema = AnySchema>({
const clonePromises = Array.from(
{ length: carryForwardAmount },
async () => {
const clonedResource = await resource.clone(false);
const clonedResource = await resource.clone(
false,
true
);
clonedResource.set('catalogNumber', wildCard as never);
return clonedResource;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1170,6 +1170,18 @@ export const userPreferenceDefinitions = {
renderer: f.never,
container: 'div',
}),
bulkCarryForward: definePref<{
readonly [TABLE_NAME in keyof Tables]?: RA<
TableFields<Tables[TABLE_NAME]>
>;
}>({
title: localized('_bulkCarryForward'),
requiresReload: false,
visible: false,
defaultValue: {},
renderer: f.never,
container: 'div',
}),
enableCarryForward: definePref<RA<keyof Tables>>({
title: localized('_enableCarryForward'),
requiresReload: false,
Expand Down Expand Up @@ -1242,6 +1254,14 @@ export const userPreferenceDefinitions = {
type: 'java.lang.Boolean',
container: 'div',
}),
bulkCarryForwardShowHidden: definePref<boolean>({
title: localized('_bulkCarryForwardShowHidden'),
requiresReload: false,
visible: false,
defaultValue: false,
type: 'java.lang.Boolean',
container: 'div',
}),
},
},
},
Expand Down
6 changes: 6 additions & 0 deletions specifyweb/frontend/js_src/lib/localization/forms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -860,6 +860,9 @@ export const formsText = createDictionary({
'uk-ua': 'Налаштуйте поля для перенесення',
'de-ch': 'Konfigurieren der zu übertragenden Felder',
},
bulkCarryForwardSettingsDescription: {
'en-us': 'Configure fields to bulk carry forward',
},
carryForwardTableSettingsDescription: {
'en-us': 'Configure fields to carry forward ({tableName:string})',
'ru-ru': 'Настройте поля для переноса ({tableName:string})',
Expand All @@ -869,6 +872,9 @@ export const formsText = createDictionary({
'de-ch':
'Konfigurieren Sie die zu übertragenden Felder ({tableName:string})',
},
bulkCarryForwardTableSettingsDescription: {
'en-us': 'Configure fields to bulk carry forward ({tableName:string})',
},
carryForwardUniqueField: {
'en-us': 'This field must be unique. It can not be carried over',
'ru-ru': 'Это поле должно быть уникальным. Его нельзя переносить',
Expand Down

0 comments on commit 6a364e0

Please sign in to comment.