client/utils/useDefaultFields.js
import _ from 'lodash';
const applyDefaults = (type, fields, property, defaults) => {
const field = _.find(fields, { property });
if (field) {
if (_.isBoolean(field[type]) && field[type] === false)
return _.remove(fields, { property });
return _.defaults(field, defaults);
}
return fields.unshift(defaults);
};
export const useUsernameField = (isEditField, fields, connections, hasSelectedConnection, initialValues) => {
const type = isEditField ? 'edit' : 'create';
const selectedConnection = _.find(connections, (conn) => conn.name === hasSelectedConnection);
const requireUsername = selectedConnection && selectedConnection.options ? selectedConnection.options.requires_username : false;
const noUsername = connections.length > 0
? !requireUsername && (!initialValues || !initialValues.username)
// if we have no connections, we *might* need a username field, we don't know -
// because we don't have the connections to check
: false;
const defaults = {
property: 'username',
label: 'Username',
disable: noUsername,
[type]: {
type: 'text',
// if we have no connections we should show the field but not require it
required: connections.length > 0
}
};
return applyDefaults(type, fields, 'username', defaults);
};
export const useMembershipsField = (isEditField, fields, hasMembership, memberships, createMemberships, getDictValue) => {
const type = isEditField ? 'edit' : 'create';
const allMemberships = _(memberships || [])
.concat(hasMembership)
.uniq()
.sort()
.value();
if (allMemberships.length <= 1 && !createMemberships) {
return _.remove(fields, { property: 'memberships' });
}
const defaults = {
property: 'memberships',
label: getDictValue('memberships', 'Memberships'),
[type]: {
type: 'select',
component: 'InputMultiCombo',
options: allMemberships.map(m => ({ value: m, label: m }))
}
};
return applyDefaults(type, fields, 'memberships', defaults);
};
export const useConnectionsField = (isEditField, fields, connections, onConnectionChange) => {
const type = isEditField ? 'edit' : 'create';
// if we have exactly one connection then don't show this field and use that connection
// however if we have zero connections, we should show the free text connections field
if (!connections || connections.length === 1) {
return _.remove(fields, { property: 'connection' });
}
const isConnectionLimitExceeded = connections.length === 0;
const defaults = {
property: 'connection',
label: isConnectionLimitExceeded ? 'Connection Name' : 'Connection',
[type]: {
required: true,
type: isConnectionLimitExceeded ? 'text' : 'select',
component: isConnectionLimitExceeded ? 'InputText' : 'InputCombo',
options: isConnectionLimitExceeded ? undefined : connections.map(conn => ({ value: conn.name, label: conn.name })),
onChange: onConnectionChange
}
};
return applyDefaults(type, fields, 'connection', defaults);
};
export const useMfaField = (isEditField, fields, providers, onProviderChange) => {
const type = isEditField ? 'edit' : 'create';
const defaults = {
property: 'multifactor',
label: 'MFA Provider',
[type]: {
required: true,
type: 'select',
component: 'InputCombo',
options: providers.map(prov => ({ value: prov, label: prov })),
onChange: onProviderChange
}
};
return applyDefaults(type, fields, 'multifactor', defaults);
};
export const useDisabledConnectionField = (isEditField, fields, connection, connections) => {
const type = isEditField ? 'edit' : 'create';
if (!connection || !connections || connections.length < 2) {
return _.remove(fields, { property: 'connection' });
}
const defaults = {
property: 'connection',
label: 'Connection',
[type]: {
type: 'text',
disabled: true
}
};
applyDefaults(type, fields, 'connection', defaults);
const field = _.find(fields, { property: 'connection' });
// If connection is an editable field, we need to display it on other pages, but only as disabled
if (field && (
(_.isObject(field[type]) && field[type].disabled !== true) || _.isBoolean(field[type])
)) field[type] = defaults[type];
};
export const usePasswordFields = (isEditField, fields) => {
const type = isEditField ? 'edit' : 'create';
const repeatPasswordDefaults = {
property: 'repeatPassword',
label: 'Repeat Password',
[type]: {
required: true,
type: 'password',
component: 'InputText',
validationFunction:
(value, values) =>
(value !== values.password ? 'passwords must match' : false )
}
};
const passwordDefaults = {
property: 'password',
label: 'Password',
[type]: {
required: true,
type: 'password',
component: 'InputText'
}
};
applyDefaults(type, fields, 'repeatPassword', repeatPasswordDefaults);
applyDefaults(type, fields, 'password', passwordDefaults);
};
export const useEmailField = (isEditField, fields) => {
const type = isEditField ? 'edit' : 'create';
const defaults = {
property: 'email',
label: 'Email',
[type]: {
type: 'text',
component: 'InputText',
required: true
}
};
applyDefaults(type, fields, 'email', defaults);
};
export const useClientField = (isEditField, fields, clients) => {
const type = isEditField ? 'edit' : 'create';
const defaults = {
property: 'client',
label: 'Client',
[type]: {
type: 'select',
component: 'InputCombo',
required: false,
options: clients.map(option => ({ value: option.client_id, label: option.name}))
}
};
applyDefaults(type, fields, 'client', defaults);
};
export const useDisabledEmailField = (isEditField, fields) => {
const type = isEditField ? 'edit' : 'create';
const defaults = {
property: 'email',
label: 'Email',
[type]: {
type: 'text',
component: 'InputText',
disabled: true
}
};
applyDefaults(type, fields, 'email', defaults);
const field = _.find(fields, { property: 'email' });
// If connection is an editable field, we need to display it on other pages, but only as disabled
if (field && (
(_.isObject(field[type]) && field[type].disabled !== true) || _.isBoolean(field[type])
)) field[type] = defaults[type];
};