Line endings fixed so that we don't have CRLF in Git. Better now than later.
This commit is contained in:
parent
2fe7f82be3
commit
d482d214d9
69 changed files with 6405 additions and 6405 deletions
|
|
@ -1,55 +1,55 @@
|
|||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import {Fieldset, InputField} from "../../lib/form";
|
||||
|
||||
export function getFieldTypes(t) {
|
||||
|
||||
const fieldTypes = {
|
||||
text: {
|
||||
label: t('text'),
|
||||
},
|
||||
website: {
|
||||
label: t('website'),
|
||||
},
|
||||
longtext: {
|
||||
label: t('multilineText'),
|
||||
},
|
||||
gpg: {
|
||||
label: t('gpgPublicKey'),
|
||||
},
|
||||
number: {
|
||||
label: t('number'),
|
||||
},
|
||||
'checkbox-grouped': {
|
||||
label: t('checkboxesFromOptionFields'),
|
||||
},
|
||||
'radio-grouped': {
|
||||
label: t('radioButtonsFromOptionFields')
|
||||
},
|
||||
'dropdown-grouped': {
|
||||
label: t('dropDownFromOptionFields')
|
||||
},
|
||||
'radio-enum': {
|
||||
label: t('radioButtonsEnumerated')
|
||||
},
|
||||
'dropdown-enum': {
|
||||
label: t('dropDownEnumerated')
|
||||
},
|
||||
'date': {
|
||||
label: t('date')
|
||||
},
|
||||
'birthday': {
|
||||
label: t('birthday')
|
||||
},
|
||||
json: {
|
||||
label: t('jsonValueForCustomRendering')
|
||||
},
|
||||
option: {
|
||||
label: t('option')
|
||||
}
|
||||
};
|
||||
|
||||
return fieldTypes;
|
||||
}
|
||||
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import {Fieldset, InputField} from "../../lib/form";
|
||||
|
||||
export function getFieldTypes(t) {
|
||||
|
||||
const fieldTypes = {
|
||||
text: {
|
||||
label: t('text'),
|
||||
},
|
||||
website: {
|
||||
label: t('website'),
|
||||
},
|
||||
longtext: {
|
||||
label: t('multilineText'),
|
||||
},
|
||||
gpg: {
|
||||
label: t('gpgPublicKey'),
|
||||
},
|
||||
number: {
|
||||
label: t('number'),
|
||||
},
|
||||
'checkbox-grouped': {
|
||||
label: t('checkboxesFromOptionFields'),
|
||||
},
|
||||
'radio-grouped': {
|
||||
label: t('radioButtonsFromOptionFields')
|
||||
},
|
||||
'dropdown-grouped': {
|
||||
label: t('dropDownFromOptionFields')
|
||||
},
|
||||
'radio-enum': {
|
||||
label: t('radioButtonsEnumerated')
|
||||
},
|
||||
'dropdown-enum': {
|
||||
label: t('dropDownEnumerated')
|
||||
},
|
||||
'date': {
|
||||
label: t('date')
|
||||
},
|
||||
'birthday': {
|
||||
label: t('birthday')
|
||||
},
|
||||
json: {
|
||||
label: t('jsonValueForCustomRendering')
|
||||
},
|
||||
option: {
|
||||
label: t('option')
|
||||
}
|
||||
};
|
||||
|
||||
return fieldTypes;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
$editorNormalHeight: 400px;
|
||||
@import "../../lib/sandbox-common";
|
||||
|
||||
.editor {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.host {
|
||||
border: none;
|
||||
width: 100%;
|
||||
}
|
||||
$editorNormalHeight: 400px;
|
||||
@import "../../lib/sandbox-common";
|
||||
|
||||
.editor {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.host {
|
||||
border: none;
|
||||
width: 100%;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,46 +1,46 @@
|
|||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import {ImportSource, MappingType, ImportStatus, RunStatus} from '../../../../shared/imports';
|
||||
|
||||
export function getImportLabels(t) {
|
||||
|
||||
const importSourceLabels = {
|
||||
[ImportSource.CSV_FILE]: t('csvFile'),
|
||||
[ImportSource.LIST]: t('list'),
|
||||
};
|
||||
|
||||
const importStatusLabels = {
|
||||
[ImportStatus.PREP_SCHEDULED]: t('created'),
|
||||
[ImportStatus.PREP_RUNNING]: t('preparing'),
|
||||
[ImportStatus.PREP_STOPPING]: t('stopping'),
|
||||
[ImportStatus.PREP_FINISHED]: t('ready'),
|
||||
[ImportStatus.PREP_FAILED]: t('preparationFailed'),
|
||||
[ImportStatus.RUN_SCHEDULED]: t('scheduled'),
|
||||
[ImportStatus.RUN_RUNNING]: t('running'),
|
||||
[ImportStatus.RUN_STOPPING]: t('stopping'),
|
||||
[ImportStatus.RUN_FINISHED]: t('finished'),
|
||||
[ImportStatus.RUN_FAILED]: t('failed')
|
||||
};
|
||||
|
||||
const runStatusLabels = {
|
||||
[RunStatus.SCHEDULED]: t('starting'),
|
||||
[RunStatus.RUNNING]: t('running'),
|
||||
[RunStatus.STOPPING]: t('stopping'),
|
||||
[RunStatus.FINISHED]: t('finished'),
|
||||
[RunStatus.FAILED]: t('failed')
|
||||
};
|
||||
|
||||
const mappingTypeLabels = {
|
||||
[MappingType.BASIC_SUBSCRIBE]: t('basicImportOfSubscribers'),
|
||||
[MappingType.BASIC_UNSUBSCRIBE]: t('unsubscribeEmails'),
|
||||
}
|
||||
|
||||
return {
|
||||
importStatusLabels,
|
||||
mappingTypeLabels,
|
||||
importSourceLabels,
|
||||
runStatusLabels
|
||||
};
|
||||
}
|
||||
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import {ImportSource, MappingType, ImportStatus, RunStatus} from '../../../../shared/imports';
|
||||
|
||||
export function getImportLabels(t) {
|
||||
|
||||
const importSourceLabels = {
|
||||
[ImportSource.CSV_FILE]: t('csvFile'),
|
||||
[ImportSource.LIST]: t('list'),
|
||||
};
|
||||
|
||||
const importStatusLabels = {
|
||||
[ImportStatus.PREP_SCHEDULED]: t('created'),
|
||||
[ImportStatus.PREP_RUNNING]: t('preparing'),
|
||||
[ImportStatus.PREP_STOPPING]: t('stopping'),
|
||||
[ImportStatus.PREP_FINISHED]: t('ready'),
|
||||
[ImportStatus.PREP_FAILED]: t('preparationFailed'),
|
||||
[ImportStatus.RUN_SCHEDULED]: t('scheduled'),
|
||||
[ImportStatus.RUN_RUNNING]: t('running'),
|
||||
[ImportStatus.RUN_STOPPING]: t('stopping'),
|
||||
[ImportStatus.RUN_FINISHED]: t('finished'),
|
||||
[ImportStatus.RUN_FAILED]: t('failed')
|
||||
};
|
||||
|
||||
const runStatusLabels = {
|
||||
[RunStatus.SCHEDULED]: t('starting'),
|
||||
[RunStatus.RUNNING]: t('running'),
|
||||
[RunStatus.STOPPING]: t('stopping'),
|
||||
[RunStatus.FINISHED]: t('finished'),
|
||||
[RunStatus.FAILED]: t('failed')
|
||||
};
|
||||
|
||||
const mappingTypeLabels = {
|
||||
[MappingType.BASIC_SUBSCRIBE]: t('basicImportOfSubscribers'),
|
||||
[MappingType.BASIC_UNSUBSCRIBE]: t('unsubscribeEmails'),
|
||||
}
|
||||
|
||||
return {
|
||||
importStatusLabels,
|
||||
mappingTypeLabels,
|
||||
importSourceLabels,
|
||||
runStatusLabels
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,152 +1,152 @@
|
|||
$desktopMinWidth: 768px;
|
||||
|
||||
$mobileLeftPaneResidualWidth: 0px;
|
||||
$mobileAnimationStartPosition: 100px;
|
||||
|
||||
$desktopLeftPaneResidualWidth: 200px;
|
||||
$desktopAnimationStartPosition: 300px;
|
||||
|
||||
@mixin optionsHidden {
|
||||
transform: translateX($mobileAnimationStartPosition);
|
||||
@media (min-width: $desktopMinWidth) {
|
||||
transform: translateX($desktopAnimationStartPosition);
|
||||
}
|
||||
}
|
||||
|
||||
@mixin optionsVisible {
|
||||
transform: translateX($mobileLeftPaneResidualWidth);
|
||||
@media (min-width: $desktopMinWidth) {
|
||||
transform: translateX($desktopLeftPaneResidualWidth);
|
||||
}
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.ruleActionLink {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.rulePane {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
.leftPane {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
margin-right: -100%;
|
||||
|
||||
.leftPaneInner {
|
||||
.ruleTree {
|
||||
background: #fbfbfb;
|
||||
border: #cfcfcf 1px solid;
|
||||
border-radius: 4px;
|
||||
padding: 10px 0px;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 30px;
|
||||
|
||||
// Without this, the placeholders when rearranging the tree are not shown
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.leftPaneOverlay {
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
|
||||
width: $mobileLeftPaneResidualWidth;
|
||||
@media (min-width: $desktopMinWidth) {
|
||||
width: $desktopLeftPaneResidualWidth;
|
||||
}
|
||||
}
|
||||
|
||||
.paneDivider {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: url('./divider.png') repeat-y;
|
||||
|
||||
@include optionsHidden;
|
||||
|
||||
padding-left: 50px;
|
||||
z-index: 1;
|
||||
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
|
||||
.paneDividerSolidBackground {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rightPane {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
vertical-align: top;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
|
||||
@include optionsHidden;
|
||||
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
|
||||
.rightPaneInner {
|
||||
margin-right: $mobileLeftPaneResidualWidth;
|
||||
@media (min-width: $desktopMinWidth) {
|
||||
margin-right: $desktopLeftPaneResidualWidth;
|
||||
}
|
||||
|
||||
.ruleOptions {
|
||||
margin-left: 60px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.ruleOptionsVisible {
|
||||
.leftPaneOverlay {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.paneDivider {
|
||||
transition: transform 300ms ease-out, opacity 100ms ease-out;
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
|
||||
@include optionsVisible;
|
||||
}
|
||||
|
||||
.rightPane {
|
||||
transition: transform 300ms ease-out, opacity 100ms ease-out;
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
|
||||
@include optionsVisible;
|
||||
}
|
||||
}
|
||||
|
||||
&.ruleOptionsHidden {
|
||||
.paneDivider {
|
||||
transition: visibility 0s linear 300ms, transform 300ms ease-in, opacity 100ms ease-in 200ms;
|
||||
}
|
||||
|
||||
.rightPane {
|
||||
transition: visibility 0s linear 300ms, transform 300ms ease-in, opacity 100ms ease-in 200ms;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
$desktopMinWidth: 768px;
|
||||
|
||||
$mobileLeftPaneResidualWidth: 0px;
|
||||
$mobileAnimationStartPosition: 100px;
|
||||
|
||||
$desktopLeftPaneResidualWidth: 200px;
|
||||
$desktopAnimationStartPosition: 300px;
|
||||
|
||||
@mixin optionsHidden {
|
||||
transform: translateX($mobileAnimationStartPosition);
|
||||
@media (min-width: $desktopMinWidth) {
|
||||
transform: translateX($desktopAnimationStartPosition);
|
||||
}
|
||||
}
|
||||
|
||||
@mixin optionsVisible {
|
||||
transform: translateX($mobileLeftPaneResidualWidth);
|
||||
@media (min-width: $desktopMinWidth) {
|
||||
transform: translateX($desktopLeftPaneResidualWidth);
|
||||
}
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.ruleActionLink {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.rulePane {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
.leftPane {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
margin-right: -100%;
|
||||
|
||||
.leftPaneInner {
|
||||
.ruleTree {
|
||||
background: #fbfbfb;
|
||||
border: #cfcfcf 1px solid;
|
||||
border-radius: 4px;
|
||||
padding: 10px 0px;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 30px;
|
||||
|
||||
// Without this, the placeholders when rearranging the tree are not shown
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.leftPaneOverlay {
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
|
||||
width: $mobileLeftPaneResidualWidth;
|
||||
@media (min-width: $desktopMinWidth) {
|
||||
width: $desktopLeftPaneResidualWidth;
|
||||
}
|
||||
}
|
||||
|
||||
.paneDivider {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: url('./divider.png') repeat-y;
|
||||
|
||||
@include optionsHidden;
|
||||
|
||||
padding-left: 50px;
|
||||
z-index: 1;
|
||||
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
|
||||
.paneDividerSolidBackground {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rightPane {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
vertical-align: top;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
|
||||
@include optionsHidden;
|
||||
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
|
||||
.rightPaneInner {
|
||||
margin-right: $mobileLeftPaneResidualWidth;
|
||||
@media (min-width: $desktopMinWidth) {
|
||||
margin-right: $desktopLeftPaneResidualWidth;
|
||||
}
|
||||
|
||||
.ruleOptions {
|
||||
margin-left: 60px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.ruleOptionsVisible {
|
||||
.leftPaneOverlay {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.paneDivider {
|
||||
transition: transform 300ms ease-out, opacity 100ms ease-out;
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
|
||||
@include optionsVisible;
|
||||
}
|
||||
|
||||
.rightPane {
|
||||
transition: transform 300ms ease-out, opacity 100ms ease-out;
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
|
||||
@include optionsVisible;
|
||||
}
|
||||
}
|
||||
|
||||
&.ruleOptionsHidden {
|
||||
.paneDivider {
|
||||
transition: visibility 0s linear 300ms, transform 300ms ease-in, opacity 100ms ease-in 200ms;
|
||||
}
|
||||
|
||||
.rightPane {
|
||||
transition: visibility 0s linear 300ms, transform 300ms ease-in, opacity 100ms ease-in 200ms;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,459 +1,459 @@
|
|||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import {DatePicker, Dropdown, InputField} from "../../lib/form";
|
||||
import { parseDate, parseBirthday, formatDate, formatBirthday, DateFormat, birthdayYear, getDateFormatString, getBirthdayFormatString } from '../../../../shared/date';
|
||||
import { tMark } from "../../lib/i18n";
|
||||
|
||||
export function getRuleHelpers(t, fields) {
|
||||
|
||||
const ruleHelpers = {};
|
||||
|
||||
ruleHelpers.compositeRuleTypes = {
|
||||
all: {
|
||||
dropdownLabel: t('allRulesMustMatch'),
|
||||
treeLabel: rule => t('allRulesMustMatch')
|
||||
},
|
||||
some: {
|
||||
dropdownLabel: t('atLeastOneRuleMustMatch'),
|
||||
treeLabel: rule => t('atLeastOneRuleMustMatch')
|
||||
},
|
||||
none: {
|
||||
dropdownLabel: t('noRuleMayMatch'),
|
||||
treeLabel: rule => t('noRuleMayMatch')
|
||||
}
|
||||
};
|
||||
|
||||
ruleHelpers.primitiveRuleTypes = {};
|
||||
|
||||
ruleHelpers.primitiveRuleTypes.text = {
|
||||
eq: {
|
||||
dropdownLabel: t('equalTo'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsEqualToValue', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
like: {
|
||||
dropdownLabel: t('matchWithSqlLike'),
|
||||
treeLabel: rule => t('valueInColumnColNameMatchesWithSqlLike', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
re: {
|
||||
dropdownLabel: t('matchWithRegularExpressions'),
|
||||
treeLabel: rule => t('valueInColumnColNameMatchesWithRegular', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
lt: {
|
||||
dropdownLabel: t('alphabeticallyBefore'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsAlphabetically', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
le: {
|
||||
dropdownLabel: t('alphabeticallyBeforeOrEqualTo'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsAlphabetically-1', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
gt: {
|
||||
dropdownLabel: t('alphabeticallyAfter'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsAlphabetically-2', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
ge: {
|
||||
dropdownLabel: t('alphabeticallyAfterOrEqualTo'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsAlphabetically-3', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
}
|
||||
};
|
||||
|
||||
ruleHelpers.primitiveRuleTypes.website = {
|
||||
eq: {
|
||||
dropdownLabel: t('equalTo'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsEqualToValue', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
like: {
|
||||
dropdownLabel: t('matchWithSqlLike'),
|
||||
treeLabel: rule => t('valueInColumnColNameMatchesWithSqlLike', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
re: {
|
||||
dropdownLabel: t('matchWithRegularExpressions'),
|
||||
treeLabel: rule => t('valueInColumnColNameMatchesWithRegular', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
}
|
||||
};
|
||||
|
||||
ruleHelpers.primitiveRuleTypes.number = {
|
||||
eq: {
|
||||
dropdownLabel: t('equalTo'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsEqualToValue-1', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
lt: {
|
||||
dropdownLabel: t('lessThan'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsLessThanValue', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
le: {
|
||||
dropdownLabel: t('lessThanOrEqualTo'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsLessThanOrEqualTo', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
gt: {
|
||||
dropdownLabel: t('greaterThan'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsGreaterThanValue', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
ge: {
|
||||
dropdownLabel: t('greaterThanOrEqualTo'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsGreaterThanOrEqual', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
}
|
||||
};
|
||||
|
||||
// FXIME - the localization here is still wrong
|
||||
function getRelativeDateTreeLabel(rule, variants) {
|
||||
if (rule.value === 0) {
|
||||
return t(variants[0], {colName: ruleHelpers.getColumnName(rule.column)})
|
||||
} else if (rule.value > 0) {
|
||||
return t(variants[1], {colName: ruleHelpers.getColumnName(rule.column), value: rule.value});
|
||||
} else {
|
||||
return t(variants[2], {colName: ruleHelpers.getColumnName(rule.column), value: -rule.value});
|
||||
}
|
||||
}
|
||||
|
||||
ruleHelpers.primitiveRuleTypes.date = {
|
||||
eq: {
|
||||
dropdownLabel: t('on'),
|
||||
treeLabel: rule => t('dateInColumnColNameIsValue', {colName: ruleHelpers.getColumnName(rule.column), value: formatDate(DateFormat.INTL, rule.value)}),
|
||||
},
|
||||
lt: {
|
||||
dropdownLabel: t('before'),
|
||||
treeLabel: rule => t('dateInColumnColNameIsBeforeValue', {colName: ruleHelpers.getColumnName(rule.column), value: formatDate(DateFormat.INTL, rule.value)}),
|
||||
},
|
||||
le: {
|
||||
dropdownLabel: t('beforeOrOn'),
|
||||
treeLabel: rule => t('dateInColumnColNameIsBeforeOrOnValue', {colName: ruleHelpers.getColumnName(rule.column), value: formatDate(DateFormat.INTL, rule.value)}),
|
||||
},
|
||||
gt: {
|
||||
dropdownLabel: t('after'),
|
||||
treeLabel: rule => t('dateInColumnColNameIsAfterValue', {colName: ruleHelpers.getColumnName(rule.column), value: formatDate(DateFormat.INTL, rule.value)}),
|
||||
},
|
||||
ge: {
|
||||
dropdownLabel: t('afterOrOn'),
|
||||
treeLabel: rule => t('dateInColumnColNameIsAfterOrOnValue', {colName: ruleHelpers.getColumnName(rule.column), value: formatDate(DateFormat.INTL, rule.value)}),
|
||||
},
|
||||
eqTodayPlusDays: {
|
||||
dropdownLabel: t('onXthDayBeforeafterCurrentDate'),
|
||||
treeLabel: rule => getRelativeDateTreeLabel(rule, [tMark('dateInColumnColNameIsTheCurrentDate'), tMark('dateInColumnColNameIsTheValuethDayAfter'), tMark('dateInColumnColNameIsTheValuethDayBefore')]),
|
||||
},
|
||||
ltTodayPlusDays: {
|
||||
dropdownLabel: t('beforeXthDayBeforeafterCurrentDate'),
|
||||
treeLabel: rule => getRelativeDateTreeLabel(rule, [tMark('dateInColumnColNameIsBeforeTheCurrent'), tMark('dateInColumnColNameIsBeforeTheValuethDay'), tMark('dateInColumnColNameIsBeforeTheValuethDay-1')]),
|
||||
},
|
||||
leTodayPlusDays: {
|
||||
dropdownLabel: t('beforeOrOnXthDayBeforeafterCurrentDate'),
|
||||
treeLabel: rule => getRelativeDateTreeLabel(rule, [tMark('dateInColumnColNameIsBeforeOrOnThe'), tMark('dateInColumnColNameIsBeforeOrOnThe-1'), tMark('dateInColumnColNameIsBeforeOrOnThe-2')]),
|
||||
},
|
||||
gtTodayPlusDays: {
|
||||
dropdownLabel: t('afterXthDayBeforeafterCurrentDate'),
|
||||
treeLabel: rule => getRelativeDateTreeLabel(rule, [tMark('dateInColumnColNameIsAfterTheCurrentDate'), tMark('dateInColumnColNameIsAfterTheValuethDay'), tMark('dateInColumnColNameIsAfterTheValuethDay-1')]),
|
||||
},
|
||||
geTodayPlusDays: {
|
||||
dropdownLabel: t('afterOrOnXthDayBeforeafterCurrentDate'),
|
||||
treeLabel: rule => getRelativeDateTreeLabel(rule, [tMark('dateInColumnColNameIsAfterOrOnTheCurrent'), tMark('dateInColumnColNameIsAfterOrOnTheValueth'), tMark('dateInColumnColNameIsAfterOrOnTheValueth-1')]),
|
||||
}
|
||||
};
|
||||
|
||||
ruleHelpers.primitiveRuleTypes.birthday = {
|
||||
eq: {
|
||||
dropdownLabel: t('on'),
|
||||
treeLabel: rule => t('dateInColumnColNameIsValue', {colName: ruleHelpers.getColumnName(rule.column), value: formatBirthday(DateFormat.INTL, rule.value)}),
|
||||
},
|
||||
lt: {
|
||||
dropdownLabel: t('before'),
|
||||
treeLabel: rule => t('dateInColumnColNameIsBeforeValue', {colName: ruleHelpers.getColumnName(rule.column), value: formatBirthday(DateFormat.INTL, rule.value)}),
|
||||
},
|
||||
le: {
|
||||
dropdownLabel: t('beforeOrOn'),
|
||||
treeLabel: rule => t('dateInColumnColNameIsBeforeOrOnValue', {colName: ruleHelpers.getColumnName(rule.column), value: formatBirthday(DateFormat.INTL, rule.value)}),
|
||||
},
|
||||
gt: {
|
||||
dropdownLabel: t('after'),
|
||||
treeLabel: rule => t('dateInColumnColNameIsAfterValue', {colName: ruleHelpers.getColumnName(rule.column), value: formatBirthday(DateFormat.INTL, rule.value)}),
|
||||
},
|
||||
ge: {
|
||||
dropdownLabel: t('afterOrOn'),
|
||||
treeLabel: rule => t('dateInColumnColNameIsAfterOrOnValue', {colName: ruleHelpers.getColumnName(rule.column), value: formatBirthday(DateFormat.INTL, rule.value)}),
|
||||
}
|
||||
};
|
||||
|
||||
ruleHelpers.primitiveRuleTypes.option = {
|
||||
isTrue: {
|
||||
dropdownLabel: t('isSelected'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsSelected', {colName: ruleHelpers.getColumnName(rule.column)}),
|
||||
},
|
||||
isFalse: {
|
||||
dropdownLabel: t('isNotSelected'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsNotSelected', {colName: ruleHelpers.getColumnName(rule.column)}),
|
||||
}
|
||||
};
|
||||
|
||||
ruleHelpers.primitiveRuleTypes['dropdown-enum'] = ruleHelpers.primitiveRuleTypes['radio-enum'] = {
|
||||
eq: {
|
||||
dropdownLabel: t('keyEqualTo'),
|
||||
treeLabel: rule => t('theSelectedKeyInColumnColNameIsEqualTo', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
like: {
|
||||
dropdownLabel: t('keyMatchWithSqlLike'),
|
||||
treeLabel: rule => t('theSelectedKeyInColumnColNameMatchesWith', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
re: {
|
||||
dropdownLabel: t('keyMatchWithRegularExpressions'),
|
||||
treeLabel: rule => t('theSelectedKeyInColumnColNameMatchesWith-1', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
lt: {
|
||||
dropdownLabel: t('keyAlphabeticallyBefore'),
|
||||
treeLabel: rule => t('theSelectedKeyInColumnColNameIs', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
le: {
|
||||
dropdownLabel: t('keyAlphabeticallyBeforeOrEqualTo'),
|
||||
treeLabel: rule => t('theSelectedKeyInColumnColNameIs-1', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
gt: {
|
||||
dropdownLabel: t('keyAlphabeticallyAfter'),
|
||||
treeLabel: rule => t('theSelectedKeyInColumnColNameIs-2', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
ge: {
|
||||
dropdownLabel: t('keyAlphabeticallyAfterOrEqualTo'),
|
||||
treeLabel: rule => t('theSelectedKeyInColumnColNameIs-3', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const stringValueSettings = allowEmpty => ({
|
||||
getForm: () => <InputField id="value" label={t('value')} />,
|
||||
getFormData: rule => ({
|
||||
value: rule.value
|
||||
}),
|
||||
assignRuleSettings: (rule, getter) => {
|
||||
rule.value = getter('value');
|
||||
},
|
||||
validate: state => {
|
||||
if (!allowEmpty && !state.getIn(['value', 'value'])) {
|
||||
state.setIn(['value', 'error'], t('valueMustNotBeEmpty'));
|
||||
} else {
|
||||
state.setIn(['value', 'error'], null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const numberValueSettings = {
|
||||
getForm: () => <InputField id="value" label={t('value')} />,
|
||||
getFormData: rule => ({
|
||||
value: rule.value.toString()
|
||||
}),
|
||||
assignRuleSettings: (rule, getter) => {
|
||||
rule.value = parseInt(getter('value'));
|
||||
},
|
||||
validate: state => {
|
||||
const value = state.getIn(['value', 'value']).trim();
|
||||
if (value === '') {
|
||||
state.setIn(['value', 'error'], t('valueMustNotBeEmpty'));
|
||||
} else if (isNaN(value)) {
|
||||
state.setIn(['value', 'error'], t('valueMustBeANumber'));
|
||||
} else {
|
||||
state.setIn(['value', 'error'], null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const birthdayValueSettings = {
|
||||
getForm: () => <DatePicker id="birthday" label={t('date')} birthday />,
|
||||
getFormData: rule => ({
|
||||
birthday: formatBirthday(DateFormat.INTL, rule.value)
|
||||
}),
|
||||
assignRuleSettings: (rule, getter) => {
|
||||
rule.value = parseBirthday(DateFormat.INTL, getter('birthday')).toISOString();
|
||||
},
|
||||
validate: state => {
|
||||
const value = state.getIn(['birthday', 'value']);
|
||||
const date = parseBirthday(DateFormat.INTL, value);
|
||||
if (!value) {
|
||||
state.setIn(['birthday', 'error'], t('dateMustNotBeEmpty'));
|
||||
} else if (!date) {
|
||||
state.setIn(['birthday', 'error'], t('dateIsInvalid'));
|
||||
} else {
|
||||
state.setIn(['birthday', 'error'], null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const dateValueSettings = {
|
||||
getForm: () => <DatePicker id="date" label={t('date')} />,
|
||||
getFormData: rule => ({
|
||||
date: formatDate(DateFormat.INTL, rule.value)
|
||||
}),
|
||||
assignRuleSettings: (rule, getter) => {
|
||||
rule.value = parseDate(DateFormat.INTL, getter('date')).toISOString();
|
||||
},
|
||||
validate: state => {
|
||||
const value = state.getIn(['date', 'value']);
|
||||
const date = parseDate(DateFormat.INTL, value);
|
||||
if (!value) {
|
||||
state.setIn(['date', 'error'], t('dateMustNotBeEmpty'));
|
||||
} else if (!date) {
|
||||
state.setIn(['date', 'error'], t('dateIsInvalid'));
|
||||
} else {
|
||||
state.setIn(['date', 'error'], null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const dateRelativeValueSettings = {
|
||||
getForm: () =>
|
||||
<div>
|
||||
<InputField id="daysValue" label={t('numberOfDays')}/>
|
||||
<Dropdown id="direction" label={t('beforeAfter')} options={[
|
||||
{ key: 'before', label: t('beforeCurrentDate') },
|
||||
{ key: 'after', label: t('afterCurrentDate') }
|
||||
]}/>
|
||||
</div>,
|
||||
getFormData: rule => ({
|
||||
daysValue: Math.abs(rule.value).toString(),
|
||||
direction: rule.value >= 0 ? 'after' : 'before'
|
||||
}),
|
||||
assignRuleSettings: (rule, getter) => {
|
||||
const direction = getter('direction');
|
||||
rule.value = parseInt(getter('daysValue')) * (direction === 'before' ? -1 : 1);
|
||||
},
|
||||
validate: state => {
|
||||
const value = state.getIn(['daysValue', 'value']);
|
||||
if (!value) {
|
||||
state.setIn(['daysValue', 'error'], t('numberOfDaysMustNotBeEmpty'));
|
||||
} else if (isNaN(value)) {
|
||||
state.setIn(['daysValue', 'error'], t('numberOfDaysMustBeANumber'));
|
||||
} else {
|
||||
state.setIn(['daysValue', 'error'], null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const optionValueSettings = {
|
||||
getForm: () => null,
|
||||
getFormData: rule => ({}),
|
||||
assignRuleSettings: (rule, getter) => {},
|
||||
validate: state => {}
|
||||
};
|
||||
|
||||
|
||||
function assignSettingsToRuleTypes(ruleTypes, keys, settings) {
|
||||
for (const key of keys) {
|
||||
Object.assign(ruleTypes[key], settings);
|
||||
}
|
||||
}
|
||||
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes.text, ['eq', 'like', 're'], stringValueSettings(true));
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes.text, ['lt', 'le', 'gt', 'ge'], stringValueSettings(false));
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes.website, ['eq', 'like', 're'], stringValueSettings(true));
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes.number, ['eq', 'lt', 'le', 'gt', 'ge'], numberValueSettings);
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes.birthday, ['eq', 'lt', 'le', 'gt', 'ge'], birthdayValueSettings);
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes.date, ['eq', 'lt', 'le', 'gt', 'ge'], dateValueSettings);
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes.date, ['eqTodayPlusDays', 'ltTodayPlusDays', 'leTodayPlusDays', 'gtTodayPlusDays', 'geTodayPlusDays'], dateRelativeValueSettings);
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes.option, ['isTrue', 'isFalse'], optionValueSettings);
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes['dropdown-enum'], ['eq', 'like', 're'], stringValueSettings(true));
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes['dropdown-enum'], ['lt', 'le', 'gt', 'ge'], stringValueSettings(false));
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes['radio-enum'], ['eq', 'like', 're'], stringValueSettings(true));
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes['radio-enum'], ['lt', 'le', 'gt', 'ge'], stringValueSettings(false));
|
||||
|
||||
ruleHelpers.primitiveRuleTypesFormDataDefaults = {
|
||||
value: '',
|
||||
date: '',
|
||||
daysValue: '',
|
||||
birthday: '',
|
||||
direction: 'before'
|
||||
};
|
||||
|
||||
|
||||
|
||||
ruleHelpers.getCompositeRuleTypeOptions = () => {
|
||||
const order = ['all', 'some', 'none'];
|
||||
return order.map(key => ({ key, label: ruleHelpers.compositeRuleTypes[key].dropdownLabel }));
|
||||
};
|
||||
|
||||
ruleHelpers.getPrimitiveRuleTypeOptions = columnType => {
|
||||
const order = {
|
||||
text: ['eq', 'like', 're', 'lt', 'le', 'gt', 'ge'],
|
||||
website: ['eq', 'like', 're'],
|
||||
number: ['eq', 'lt', 'le', 'gt', 'ge'],
|
||||
birthday: ['eq', 'lt', 'le', 'gt', 'ge'],
|
||||
date: ['eq', 'lt', 'le', 'gt', 'ge', 'eqTodayPlusDays', 'ltTodayPlusDays', 'leTodayPlusDays', 'gtTodayPlusDays', 'geTodayPlusDays'],
|
||||
option: ['isTrue', 'isFalse'],
|
||||
'dropdown-enum': ['eq', 'like', 're', 'lt', 'le', 'gt', 'ge'],
|
||||
'radio-enum': ['eq', 'like', 're', 'lt', 'le', 'gt', 'ge']
|
||||
};
|
||||
|
||||
return order[columnType].map(key => ({ key, label: ruleHelpers.primitiveRuleTypes[columnType][key].dropdownLabel }));
|
||||
};
|
||||
|
||||
const predefColumns = [
|
||||
{
|
||||
column: 'email',
|
||||
name: t('emailAddress-1'),
|
||||
type: 'text',
|
||||
key: 'EMAIL'
|
||||
},
|
||||
{
|
||||
column: 'opt_in_country',
|
||||
name: t('signupCountry'),
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
column: 'created',
|
||||
name: t('signUpDate'),
|
||||
type: 'date'
|
||||
},
|
||||
{
|
||||
column: 'latest_open',
|
||||
name: t('latestOpen'),
|
||||
type: 'date'
|
||||
},
|
||||
{
|
||||
column: 'latest_click',
|
||||
name: t('latestClick'),
|
||||
type: 'date'
|
||||
},
|
||||
{
|
||||
column: 'is_test',
|
||||
name: t('Test user'),
|
||||
type: 'option'
|
||||
}
|
||||
];
|
||||
|
||||
ruleHelpers.fields = [
|
||||
...predefColumns,
|
||||
...fields.filter(fld => fld.type in ruleHelpers.primitiveRuleTypes)
|
||||
];
|
||||
|
||||
ruleHelpers.fieldsByColumn = {};
|
||||
for (const fld of ruleHelpers.fields) {
|
||||
ruleHelpers.fieldsByColumn[fld.column] = fld;
|
||||
}
|
||||
|
||||
ruleHelpers.getColumnType = column => {
|
||||
const field = ruleHelpers.fieldsByColumn[column];
|
||||
if (field) {
|
||||
return field.type;
|
||||
}
|
||||
};
|
||||
|
||||
ruleHelpers.getColumnName = column => {
|
||||
const field = ruleHelpers.fieldsByColumn[column];
|
||||
if (field) {
|
||||
return field.name;
|
||||
}
|
||||
};
|
||||
|
||||
ruleHelpers.getRuleTypeSettings = rule => {
|
||||
if (ruleHelpers.isCompositeRuleType(rule.type)) {
|
||||
return ruleHelpers.compositeRuleTypes[rule.type];
|
||||
} else {
|
||||
const colType = ruleHelpers.getColumnType(rule.column);
|
||||
|
||||
if (colType) {
|
||||
if (rule.type in ruleHelpers.primitiveRuleTypes[colType]) {
|
||||
return ruleHelpers.primitiveRuleTypes[colType][rule.type];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ruleHelpers.isCompositeRuleType = ruleType => ruleType in ruleHelpers.compositeRuleTypes;
|
||||
|
||||
return ruleHelpers;
|
||||
}
|
||||
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import {DatePicker, Dropdown, InputField} from "../../lib/form";
|
||||
import { parseDate, parseBirthday, formatDate, formatBirthday, DateFormat, birthdayYear, getDateFormatString, getBirthdayFormatString } from '../../../../shared/date';
|
||||
import { tMark } from "../../lib/i18n";
|
||||
|
||||
export function getRuleHelpers(t, fields) {
|
||||
|
||||
const ruleHelpers = {};
|
||||
|
||||
ruleHelpers.compositeRuleTypes = {
|
||||
all: {
|
||||
dropdownLabel: t('allRulesMustMatch'),
|
||||
treeLabel: rule => t('allRulesMustMatch')
|
||||
},
|
||||
some: {
|
||||
dropdownLabel: t('atLeastOneRuleMustMatch'),
|
||||
treeLabel: rule => t('atLeastOneRuleMustMatch')
|
||||
},
|
||||
none: {
|
||||
dropdownLabel: t('noRuleMayMatch'),
|
||||
treeLabel: rule => t('noRuleMayMatch')
|
||||
}
|
||||
};
|
||||
|
||||
ruleHelpers.primitiveRuleTypes = {};
|
||||
|
||||
ruleHelpers.primitiveRuleTypes.text = {
|
||||
eq: {
|
||||
dropdownLabel: t('equalTo'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsEqualToValue', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
like: {
|
||||
dropdownLabel: t('matchWithSqlLike'),
|
||||
treeLabel: rule => t('valueInColumnColNameMatchesWithSqlLike', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
re: {
|
||||
dropdownLabel: t('matchWithRegularExpressions'),
|
||||
treeLabel: rule => t('valueInColumnColNameMatchesWithRegular', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
lt: {
|
||||
dropdownLabel: t('alphabeticallyBefore'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsAlphabetically', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
le: {
|
||||
dropdownLabel: t('alphabeticallyBeforeOrEqualTo'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsAlphabetically-1', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
gt: {
|
||||
dropdownLabel: t('alphabeticallyAfter'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsAlphabetically-2', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
ge: {
|
||||
dropdownLabel: t('alphabeticallyAfterOrEqualTo'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsAlphabetically-3', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
}
|
||||
};
|
||||
|
||||
ruleHelpers.primitiveRuleTypes.website = {
|
||||
eq: {
|
||||
dropdownLabel: t('equalTo'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsEqualToValue', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
like: {
|
||||
dropdownLabel: t('matchWithSqlLike'),
|
||||
treeLabel: rule => t('valueInColumnColNameMatchesWithSqlLike', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
re: {
|
||||
dropdownLabel: t('matchWithRegularExpressions'),
|
||||
treeLabel: rule => t('valueInColumnColNameMatchesWithRegular', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
}
|
||||
};
|
||||
|
||||
ruleHelpers.primitiveRuleTypes.number = {
|
||||
eq: {
|
||||
dropdownLabel: t('equalTo'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsEqualToValue-1', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
lt: {
|
||||
dropdownLabel: t('lessThan'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsLessThanValue', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
le: {
|
||||
dropdownLabel: t('lessThanOrEqualTo'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsLessThanOrEqualTo', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
gt: {
|
||||
dropdownLabel: t('greaterThan'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsGreaterThanValue', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
ge: {
|
||||
dropdownLabel: t('greaterThanOrEqualTo'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsGreaterThanOrEqual', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
}
|
||||
};
|
||||
|
||||
// FXIME - the localization here is still wrong
|
||||
function getRelativeDateTreeLabel(rule, variants) {
|
||||
if (rule.value === 0) {
|
||||
return t(variants[0], {colName: ruleHelpers.getColumnName(rule.column)})
|
||||
} else if (rule.value > 0) {
|
||||
return t(variants[1], {colName: ruleHelpers.getColumnName(rule.column), value: rule.value});
|
||||
} else {
|
||||
return t(variants[2], {colName: ruleHelpers.getColumnName(rule.column), value: -rule.value});
|
||||
}
|
||||
}
|
||||
|
||||
ruleHelpers.primitiveRuleTypes.date = {
|
||||
eq: {
|
||||
dropdownLabel: t('on'),
|
||||
treeLabel: rule => t('dateInColumnColNameIsValue', {colName: ruleHelpers.getColumnName(rule.column), value: formatDate(DateFormat.INTL, rule.value)}),
|
||||
},
|
||||
lt: {
|
||||
dropdownLabel: t('before'),
|
||||
treeLabel: rule => t('dateInColumnColNameIsBeforeValue', {colName: ruleHelpers.getColumnName(rule.column), value: formatDate(DateFormat.INTL, rule.value)}),
|
||||
},
|
||||
le: {
|
||||
dropdownLabel: t('beforeOrOn'),
|
||||
treeLabel: rule => t('dateInColumnColNameIsBeforeOrOnValue', {colName: ruleHelpers.getColumnName(rule.column), value: formatDate(DateFormat.INTL, rule.value)}),
|
||||
},
|
||||
gt: {
|
||||
dropdownLabel: t('after'),
|
||||
treeLabel: rule => t('dateInColumnColNameIsAfterValue', {colName: ruleHelpers.getColumnName(rule.column), value: formatDate(DateFormat.INTL, rule.value)}),
|
||||
},
|
||||
ge: {
|
||||
dropdownLabel: t('afterOrOn'),
|
||||
treeLabel: rule => t('dateInColumnColNameIsAfterOrOnValue', {colName: ruleHelpers.getColumnName(rule.column), value: formatDate(DateFormat.INTL, rule.value)}),
|
||||
},
|
||||
eqTodayPlusDays: {
|
||||
dropdownLabel: t('onXthDayBeforeafterCurrentDate'),
|
||||
treeLabel: rule => getRelativeDateTreeLabel(rule, [tMark('dateInColumnColNameIsTheCurrentDate'), tMark('dateInColumnColNameIsTheValuethDayAfter'), tMark('dateInColumnColNameIsTheValuethDayBefore')]),
|
||||
},
|
||||
ltTodayPlusDays: {
|
||||
dropdownLabel: t('beforeXthDayBeforeafterCurrentDate'),
|
||||
treeLabel: rule => getRelativeDateTreeLabel(rule, [tMark('dateInColumnColNameIsBeforeTheCurrent'), tMark('dateInColumnColNameIsBeforeTheValuethDay'), tMark('dateInColumnColNameIsBeforeTheValuethDay-1')]),
|
||||
},
|
||||
leTodayPlusDays: {
|
||||
dropdownLabel: t('beforeOrOnXthDayBeforeafterCurrentDate'),
|
||||
treeLabel: rule => getRelativeDateTreeLabel(rule, [tMark('dateInColumnColNameIsBeforeOrOnThe'), tMark('dateInColumnColNameIsBeforeOrOnThe-1'), tMark('dateInColumnColNameIsBeforeOrOnThe-2')]),
|
||||
},
|
||||
gtTodayPlusDays: {
|
||||
dropdownLabel: t('afterXthDayBeforeafterCurrentDate'),
|
||||
treeLabel: rule => getRelativeDateTreeLabel(rule, [tMark('dateInColumnColNameIsAfterTheCurrentDate'), tMark('dateInColumnColNameIsAfterTheValuethDay'), tMark('dateInColumnColNameIsAfterTheValuethDay-1')]),
|
||||
},
|
||||
geTodayPlusDays: {
|
||||
dropdownLabel: t('afterOrOnXthDayBeforeafterCurrentDate'),
|
||||
treeLabel: rule => getRelativeDateTreeLabel(rule, [tMark('dateInColumnColNameIsAfterOrOnTheCurrent'), tMark('dateInColumnColNameIsAfterOrOnTheValueth'), tMark('dateInColumnColNameIsAfterOrOnTheValueth-1')]),
|
||||
}
|
||||
};
|
||||
|
||||
ruleHelpers.primitiveRuleTypes.birthday = {
|
||||
eq: {
|
||||
dropdownLabel: t('on'),
|
||||
treeLabel: rule => t('dateInColumnColNameIsValue', {colName: ruleHelpers.getColumnName(rule.column), value: formatBirthday(DateFormat.INTL, rule.value)}),
|
||||
},
|
||||
lt: {
|
||||
dropdownLabel: t('before'),
|
||||
treeLabel: rule => t('dateInColumnColNameIsBeforeValue', {colName: ruleHelpers.getColumnName(rule.column), value: formatBirthday(DateFormat.INTL, rule.value)}),
|
||||
},
|
||||
le: {
|
||||
dropdownLabel: t('beforeOrOn'),
|
||||
treeLabel: rule => t('dateInColumnColNameIsBeforeOrOnValue', {colName: ruleHelpers.getColumnName(rule.column), value: formatBirthday(DateFormat.INTL, rule.value)}),
|
||||
},
|
||||
gt: {
|
||||
dropdownLabel: t('after'),
|
||||
treeLabel: rule => t('dateInColumnColNameIsAfterValue', {colName: ruleHelpers.getColumnName(rule.column), value: formatBirthday(DateFormat.INTL, rule.value)}),
|
||||
},
|
||||
ge: {
|
||||
dropdownLabel: t('afterOrOn'),
|
||||
treeLabel: rule => t('dateInColumnColNameIsAfterOrOnValue', {colName: ruleHelpers.getColumnName(rule.column), value: formatBirthday(DateFormat.INTL, rule.value)}),
|
||||
}
|
||||
};
|
||||
|
||||
ruleHelpers.primitiveRuleTypes.option = {
|
||||
isTrue: {
|
||||
dropdownLabel: t('isSelected'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsSelected', {colName: ruleHelpers.getColumnName(rule.column)}),
|
||||
},
|
||||
isFalse: {
|
||||
dropdownLabel: t('isNotSelected'),
|
||||
treeLabel: rule => t('valueInColumnColNameIsNotSelected', {colName: ruleHelpers.getColumnName(rule.column)}),
|
||||
}
|
||||
};
|
||||
|
||||
ruleHelpers.primitiveRuleTypes['dropdown-enum'] = ruleHelpers.primitiveRuleTypes['radio-enum'] = {
|
||||
eq: {
|
||||
dropdownLabel: t('keyEqualTo'),
|
||||
treeLabel: rule => t('theSelectedKeyInColumnColNameIsEqualTo', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
like: {
|
||||
dropdownLabel: t('keyMatchWithSqlLike'),
|
||||
treeLabel: rule => t('theSelectedKeyInColumnColNameMatchesWith', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
re: {
|
||||
dropdownLabel: t('keyMatchWithRegularExpressions'),
|
||||
treeLabel: rule => t('theSelectedKeyInColumnColNameMatchesWith-1', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
lt: {
|
||||
dropdownLabel: t('keyAlphabeticallyBefore'),
|
||||
treeLabel: rule => t('theSelectedKeyInColumnColNameIs', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
le: {
|
||||
dropdownLabel: t('keyAlphabeticallyBeforeOrEqualTo'),
|
||||
treeLabel: rule => t('theSelectedKeyInColumnColNameIs-1', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
gt: {
|
||||
dropdownLabel: t('keyAlphabeticallyAfter'),
|
||||
treeLabel: rule => t('theSelectedKeyInColumnColNameIs-2', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
},
|
||||
ge: {
|
||||
dropdownLabel: t('keyAlphabeticallyAfterOrEqualTo'),
|
||||
treeLabel: rule => t('theSelectedKeyInColumnColNameIs-3', {colName: ruleHelpers.getColumnName(rule.column), value: rule.value}),
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const stringValueSettings = allowEmpty => ({
|
||||
getForm: () => <InputField id="value" label={t('value')} />,
|
||||
getFormData: rule => ({
|
||||
value: rule.value
|
||||
}),
|
||||
assignRuleSettings: (rule, getter) => {
|
||||
rule.value = getter('value');
|
||||
},
|
||||
validate: state => {
|
||||
if (!allowEmpty && !state.getIn(['value', 'value'])) {
|
||||
state.setIn(['value', 'error'], t('valueMustNotBeEmpty'));
|
||||
} else {
|
||||
state.setIn(['value', 'error'], null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const numberValueSettings = {
|
||||
getForm: () => <InputField id="value" label={t('value')} />,
|
||||
getFormData: rule => ({
|
||||
value: rule.value.toString()
|
||||
}),
|
||||
assignRuleSettings: (rule, getter) => {
|
||||
rule.value = parseInt(getter('value'));
|
||||
},
|
||||
validate: state => {
|
||||
const value = state.getIn(['value', 'value']).trim();
|
||||
if (value === '') {
|
||||
state.setIn(['value', 'error'], t('valueMustNotBeEmpty'));
|
||||
} else if (isNaN(value)) {
|
||||
state.setIn(['value', 'error'], t('valueMustBeANumber'));
|
||||
} else {
|
||||
state.setIn(['value', 'error'], null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const birthdayValueSettings = {
|
||||
getForm: () => <DatePicker id="birthday" label={t('date')} birthday />,
|
||||
getFormData: rule => ({
|
||||
birthday: formatBirthday(DateFormat.INTL, rule.value)
|
||||
}),
|
||||
assignRuleSettings: (rule, getter) => {
|
||||
rule.value = parseBirthday(DateFormat.INTL, getter('birthday')).toISOString();
|
||||
},
|
||||
validate: state => {
|
||||
const value = state.getIn(['birthday', 'value']);
|
||||
const date = parseBirthday(DateFormat.INTL, value);
|
||||
if (!value) {
|
||||
state.setIn(['birthday', 'error'], t('dateMustNotBeEmpty'));
|
||||
} else if (!date) {
|
||||
state.setIn(['birthday', 'error'], t('dateIsInvalid'));
|
||||
} else {
|
||||
state.setIn(['birthday', 'error'], null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const dateValueSettings = {
|
||||
getForm: () => <DatePicker id="date" label={t('date')} />,
|
||||
getFormData: rule => ({
|
||||
date: formatDate(DateFormat.INTL, rule.value)
|
||||
}),
|
||||
assignRuleSettings: (rule, getter) => {
|
||||
rule.value = parseDate(DateFormat.INTL, getter('date')).toISOString();
|
||||
},
|
||||
validate: state => {
|
||||
const value = state.getIn(['date', 'value']);
|
||||
const date = parseDate(DateFormat.INTL, value);
|
||||
if (!value) {
|
||||
state.setIn(['date', 'error'], t('dateMustNotBeEmpty'));
|
||||
} else if (!date) {
|
||||
state.setIn(['date', 'error'], t('dateIsInvalid'));
|
||||
} else {
|
||||
state.setIn(['date', 'error'], null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const dateRelativeValueSettings = {
|
||||
getForm: () =>
|
||||
<div>
|
||||
<InputField id="daysValue" label={t('numberOfDays')}/>
|
||||
<Dropdown id="direction" label={t('beforeAfter')} options={[
|
||||
{ key: 'before', label: t('beforeCurrentDate') },
|
||||
{ key: 'after', label: t('afterCurrentDate') }
|
||||
]}/>
|
||||
</div>,
|
||||
getFormData: rule => ({
|
||||
daysValue: Math.abs(rule.value).toString(),
|
||||
direction: rule.value >= 0 ? 'after' : 'before'
|
||||
}),
|
||||
assignRuleSettings: (rule, getter) => {
|
||||
const direction = getter('direction');
|
||||
rule.value = parseInt(getter('daysValue')) * (direction === 'before' ? -1 : 1);
|
||||
},
|
||||
validate: state => {
|
||||
const value = state.getIn(['daysValue', 'value']);
|
||||
if (!value) {
|
||||
state.setIn(['daysValue', 'error'], t('numberOfDaysMustNotBeEmpty'));
|
||||
} else if (isNaN(value)) {
|
||||
state.setIn(['daysValue', 'error'], t('numberOfDaysMustBeANumber'));
|
||||
} else {
|
||||
state.setIn(['daysValue', 'error'], null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const optionValueSettings = {
|
||||
getForm: () => null,
|
||||
getFormData: rule => ({}),
|
||||
assignRuleSettings: (rule, getter) => {},
|
||||
validate: state => {}
|
||||
};
|
||||
|
||||
|
||||
function assignSettingsToRuleTypes(ruleTypes, keys, settings) {
|
||||
for (const key of keys) {
|
||||
Object.assign(ruleTypes[key], settings);
|
||||
}
|
||||
}
|
||||
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes.text, ['eq', 'like', 're'], stringValueSettings(true));
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes.text, ['lt', 'le', 'gt', 'ge'], stringValueSettings(false));
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes.website, ['eq', 'like', 're'], stringValueSettings(true));
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes.number, ['eq', 'lt', 'le', 'gt', 'ge'], numberValueSettings);
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes.birthday, ['eq', 'lt', 'le', 'gt', 'ge'], birthdayValueSettings);
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes.date, ['eq', 'lt', 'le', 'gt', 'ge'], dateValueSettings);
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes.date, ['eqTodayPlusDays', 'ltTodayPlusDays', 'leTodayPlusDays', 'gtTodayPlusDays', 'geTodayPlusDays'], dateRelativeValueSettings);
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes.option, ['isTrue', 'isFalse'], optionValueSettings);
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes['dropdown-enum'], ['eq', 'like', 're'], stringValueSettings(true));
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes['dropdown-enum'], ['lt', 'le', 'gt', 'ge'], stringValueSettings(false));
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes['radio-enum'], ['eq', 'like', 're'], stringValueSettings(true));
|
||||
assignSettingsToRuleTypes(ruleHelpers.primitiveRuleTypes['radio-enum'], ['lt', 'le', 'gt', 'ge'], stringValueSettings(false));
|
||||
|
||||
ruleHelpers.primitiveRuleTypesFormDataDefaults = {
|
||||
value: '',
|
||||
date: '',
|
||||
daysValue: '',
|
||||
birthday: '',
|
||||
direction: 'before'
|
||||
};
|
||||
|
||||
|
||||
|
||||
ruleHelpers.getCompositeRuleTypeOptions = () => {
|
||||
const order = ['all', 'some', 'none'];
|
||||
return order.map(key => ({ key, label: ruleHelpers.compositeRuleTypes[key].dropdownLabel }));
|
||||
};
|
||||
|
||||
ruleHelpers.getPrimitiveRuleTypeOptions = columnType => {
|
||||
const order = {
|
||||
text: ['eq', 'like', 're', 'lt', 'le', 'gt', 'ge'],
|
||||
website: ['eq', 'like', 're'],
|
||||
number: ['eq', 'lt', 'le', 'gt', 'ge'],
|
||||
birthday: ['eq', 'lt', 'le', 'gt', 'ge'],
|
||||
date: ['eq', 'lt', 'le', 'gt', 'ge', 'eqTodayPlusDays', 'ltTodayPlusDays', 'leTodayPlusDays', 'gtTodayPlusDays', 'geTodayPlusDays'],
|
||||
option: ['isTrue', 'isFalse'],
|
||||
'dropdown-enum': ['eq', 'like', 're', 'lt', 'le', 'gt', 'ge'],
|
||||
'radio-enum': ['eq', 'like', 're', 'lt', 'le', 'gt', 'ge']
|
||||
};
|
||||
|
||||
return order[columnType].map(key => ({ key, label: ruleHelpers.primitiveRuleTypes[columnType][key].dropdownLabel }));
|
||||
};
|
||||
|
||||
const predefColumns = [
|
||||
{
|
||||
column: 'email',
|
||||
name: t('emailAddress-1'),
|
||||
type: 'text',
|
||||
key: 'EMAIL'
|
||||
},
|
||||
{
|
||||
column: 'opt_in_country',
|
||||
name: t('signupCountry'),
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
column: 'created',
|
||||
name: t('signUpDate'),
|
||||
type: 'date'
|
||||
},
|
||||
{
|
||||
column: 'latest_open',
|
||||
name: t('latestOpen'),
|
||||
type: 'date'
|
||||
},
|
||||
{
|
||||
column: 'latest_click',
|
||||
name: t('latestClick'),
|
||||
type: 'date'
|
||||
},
|
||||
{
|
||||
column: 'is_test',
|
||||
name: t('Test user'),
|
||||
type: 'option'
|
||||
}
|
||||
];
|
||||
|
||||
ruleHelpers.fields = [
|
||||
...predefColumns,
|
||||
...fields.filter(fld => fld.type in ruleHelpers.primitiveRuleTypes)
|
||||
];
|
||||
|
||||
ruleHelpers.fieldsByColumn = {};
|
||||
for (const fld of ruleHelpers.fields) {
|
||||
ruleHelpers.fieldsByColumn[fld.column] = fld;
|
||||
}
|
||||
|
||||
ruleHelpers.getColumnType = column => {
|
||||
const field = ruleHelpers.fieldsByColumn[column];
|
||||
if (field) {
|
||||
return field.type;
|
||||
}
|
||||
};
|
||||
|
||||
ruleHelpers.getColumnName = column => {
|
||||
const field = ruleHelpers.fieldsByColumn[column];
|
||||
if (field) {
|
||||
return field.name;
|
||||
}
|
||||
};
|
||||
|
||||
ruleHelpers.getRuleTypeSettings = rule => {
|
||||
if (ruleHelpers.isCompositeRuleType(rule.type)) {
|
||||
return ruleHelpers.compositeRuleTypes[rule.type];
|
||||
} else {
|
||||
const colType = ruleHelpers.getColumnType(rule.column);
|
||||
|
||||
if (colType) {
|
||||
if (rule.type in ruleHelpers.primitiveRuleTypes[colType]) {
|
||||
return ruleHelpers.primitiveRuleTypes[colType][rule.type];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ruleHelpers.isCompositeRuleType = ruleType => ruleType in ruleHelpers.compositeRuleTypes;
|
||||
|
||||
return ruleHelpers;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
.mapping {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.erased {
|
||||
color: #808080;
|
||||
.mapping {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.erased {
|
||||
color: #808080;
|
||||
}
|
||||
|
|
@ -1,212 +1,212 @@
|
|||
'use strict';
|
||||
|
||||
import React from "react";
|
||||
import {SubscriptionStatus} from "../../../../shared/lists";
|
||||
import {
|
||||
ACEEditor,
|
||||
CheckBox,
|
||||
CheckBoxGroup,
|
||||
DatePicker,
|
||||
Dropdown,
|
||||
InputField,
|
||||
RadioGroup,
|
||||
TextArea
|
||||
} from "../../lib/form";
|
||||
import {formatBirthday, formatDate, parseBirthday, parseDate} from "../../../../shared/date";
|
||||
import {getFieldColumn} from '../../../../shared/lists';
|
||||
import 'brace/mode/json';
|
||||
|
||||
export function getSubscriptionStatusLabels(t) {
|
||||
|
||||
const subscriptionStatusLabels = {
|
||||
[SubscriptionStatus.SUBSCRIBED]: t('subscribed'),
|
||||
[SubscriptionStatus.UNSUBSCRIBED]: t('unubscribed'),
|
||||
[SubscriptionStatus.BOUNCED]: t('bounced'),
|
||||
[SubscriptionStatus.COMPLAINED]: t('complained'),
|
||||
};
|
||||
|
||||
return subscriptionStatusLabels;
|
||||
}
|
||||
|
||||
export function getFieldTypes(t) {
|
||||
|
||||
const groupedFieldTypes = {};
|
||||
|
||||
const stringFieldType = long => ({
|
||||
form: groupedField => long ? <TextArea key={getFieldColumn(groupedField)} id={getFieldColumn(groupedField)} label={groupedField.name}/> : <InputField key={getFieldColumn(groupedField)} id={getFieldColumn(groupedField)} label={groupedField.name}/>,
|
||||
assignFormData: (groupedField, data) => {
|
||||
const value = data[getFieldColumn(groupedField)];
|
||||
data[getFieldColumn(groupedField)] = value || '';
|
||||
},
|
||||
initFormData: (groupedField, data) => {
|
||||
data[getFieldColumn(groupedField)] = '';
|
||||
},
|
||||
assignEntity: (groupedField, data) => {},
|
||||
validate: (groupedField, state) => {},
|
||||
indexable: true
|
||||
});
|
||||
|
||||
const numberFieldType = {
|
||||
form: groupedField => <InputField key={getFieldColumn(groupedField)} id={getFieldColumn(groupedField)} label={groupedField.name}/>,
|
||||
assignFormData: (groupedField, data) => {
|
||||
const value = data[getFieldColumn(groupedField)];
|
||||
data[getFieldColumn(groupedField)] = value ? value.toString() : '';
|
||||
},
|
||||
initFormData: (groupedField, data) => {
|
||||
data[getFieldColumn(groupedField)] = '';
|
||||
},
|
||||
assignEntity: (groupedField, data) => {
|
||||
data[getFieldColumn(groupedField)] = parseInt(data[getFieldColumn(groupedField)]);
|
||||
},
|
||||
validate: (groupedField, state) => {
|
||||
const value = state.getIn([getFieldColumn(groupedField), 'value']).trim();
|
||||
if (value !== '' && isNaN(value)) {
|
||||
state.setIn([getFieldColumn(groupedField), 'error'], t('valueMustBeANumber'));
|
||||
} else {
|
||||
state.setIn([getFieldColumn(groupedField), 'error'], null);
|
||||
}
|
||||
},
|
||||
indexable: true
|
||||
};
|
||||
|
||||
const dateFieldType = {
|
||||
form: groupedField => <DatePicker key={getFieldColumn(groupedField)} id={getFieldColumn(groupedField)} label={groupedField.name} dateFormat={groupedField.settings.dateFormat} />,
|
||||
assignFormData: (groupedField, data) => {
|
||||
const value = data[getFieldColumn(groupedField)];
|
||||
data[getFieldColumn(groupedField)] = value ? formatDate(groupedField.settings.dateFormat, value) : '';
|
||||
},
|
||||
initFormData: (groupedField, data) => {
|
||||
data[getFieldColumn(groupedField)] = '';
|
||||
},
|
||||
assignEntity: (groupedField, data) => {
|
||||
const date = parseDate(groupedField.settings.dateFormat, data[getFieldColumn(groupedField)]);
|
||||
data[getFieldColumn(groupedField)] = date;
|
||||
},
|
||||
validate: (groupedField, state) => {
|
||||
const value = state.getIn([getFieldColumn(groupedField), 'value']);
|
||||
const date = parseDate(groupedField.settings.dateFormat, value);
|
||||
if (value !== '' && !date) {
|
||||
state.setIn([getFieldColumn(groupedField), 'error'], t('dateIsInvalid'));
|
||||
} else {
|
||||
state.setIn([getFieldColumn(groupedField), 'error'], null);
|
||||
}
|
||||
},
|
||||
indexable: true
|
||||
};
|
||||
|
||||
const birthdayFieldType = {
|
||||
form: groupedField => <DatePicker key={getFieldColumn(groupedField)} id={getFieldColumn(groupedField)} label={groupedField.name} dateFormat={groupedField.settings.dateFormat} birthday />,
|
||||
assignFormData: (groupedField, data) => {
|
||||
const value = data[getFieldColumn(groupedField)];
|
||||
data[getFieldColumn(groupedField)] = value ? formatBirthday(groupedField.settings.dateFormat, value) : '';
|
||||
},
|
||||
initFormData: (groupedField, data) => {
|
||||
data[getFieldColumn(groupedField)] = '';
|
||||
},
|
||||
assignEntity: (groupedField, data) => {
|
||||
const date = parseBirthday(groupedField.settings.dateFormat, data[getFieldColumn(groupedField)]);
|
||||
data[getFieldColumn(groupedField)] = date;
|
||||
},
|
||||
validate: (groupedField, state) => {
|
||||
const value = state.getIn([getFieldColumn(groupedField), 'value']);
|
||||
const date = parseBirthday(groupedField.settings.dateFormat, value);
|
||||
if (value !== '' && !date) {
|
||||
state.setIn([getFieldColumn(groupedField), 'error'], t('dateIsInvalid'));
|
||||
} else {
|
||||
state.setIn([getFieldColumn(groupedField), 'error'], null);
|
||||
}
|
||||
},
|
||||
indexable: true
|
||||
};
|
||||
|
||||
const jsonFieldType = {
|
||||
form: groupedField => <ACEEditor key={getFieldColumn(groupedField)} id={getFieldColumn(groupedField)} label={groupedField.name} mode="json" height="300px"/>,
|
||||
assignFormData: (groupedField, data) => {
|
||||
const value = data[getFieldColumn(groupedField)];
|
||||
data[getFieldColumn(groupedField)] = value || '';
|
||||
},
|
||||
initFormData: (groupedField, data) => {
|
||||
data[getFieldColumn(groupedField)] = '';
|
||||
},
|
||||
assignEntity: (groupedField, data) => {},
|
||||
validate: (groupedField, state) => {},
|
||||
indexable: false
|
||||
};
|
||||
|
||||
const optionFieldType = {
|
||||
form: groupedField => <CheckBox key={getFieldColumn(groupedField)} id={getFieldColumn(groupedField)} text={groupedField.settings.checkedLabel} label={groupedField.name}/>,
|
||||
assignFormData: (groupedField, data) => {
|
||||
const value = data[getFieldColumn(groupedField)];
|
||||
data[getFieldColumn(groupedField)] = !!value;
|
||||
},
|
||||
initFormData: (groupedField, data) => {
|
||||
data[getFieldColumn(groupedField)] = false;
|
||||
},
|
||||
assignEntity: (groupedField, data) => {},
|
||||
validate: (groupedField, state) => {},
|
||||
indexable: true
|
||||
};
|
||||
|
||||
const enumSingleFieldType = componentType => ({
|
||||
form: groupedField => React.createElement(componentType, { key: getFieldColumn(groupedField), id: getFieldColumn(groupedField), label: groupedField.name, options: groupedField.settings.options }, null),
|
||||
assignFormData: (groupedField, data) => {
|
||||
if (data[getFieldColumn(groupedField)] === null) {
|
||||
if (groupedField.default_value) {
|
||||
data[getFieldColumn(groupedField)] = groupedField.default_value;
|
||||
} else if (groupedField.settings.options.length > 0) {
|
||||
data[getFieldColumn(groupedField)] = groupedField.settings.options[0].key;
|
||||
} else {
|
||||
data[getFieldColumn(groupedField)] = '';
|
||||
}
|
||||
}
|
||||
},
|
||||
initFormData: (groupedField, data) => {
|
||||
if (groupedField.default_value) {
|
||||
data[getFieldColumn(groupedField)] = groupedField.default_value;
|
||||
} else if (groupedField.settings.options.length > 0) {
|
||||
data[getFieldColumn(groupedField)] = groupedField.settings.options[0].key;
|
||||
} else {
|
||||
data[getFieldColumn(groupedField)] = '';
|
||||
}
|
||||
},
|
||||
assignEntity: (groupedField, data) => {},
|
||||
validate: (groupedField, state) => {},
|
||||
indexable: false
|
||||
});
|
||||
|
||||
const enumMultipleFieldType = componentType => ({
|
||||
form: groupedField => React.createElement(componentType, { key: getFieldColumn(groupedField), id: getFieldColumn(groupedField), label: groupedField.name, options: groupedField.settings.options }, null),
|
||||
assignFormData: (groupedField, data) => {
|
||||
if (data[getFieldColumn(groupedField)] === null) {
|
||||
data[getFieldColumn(groupedField)] = [];
|
||||
}
|
||||
},
|
||||
initFormData: (groupedField, data) => {
|
||||
data[getFieldColumn(groupedField)] = [];
|
||||
},
|
||||
assignEntity: (groupedField, data) => {},
|
||||
validate: (groupedField, state) => {},
|
||||
indexable: false
|
||||
});
|
||||
|
||||
|
||||
groupedFieldTypes.text = stringFieldType(false);
|
||||
groupedFieldTypes.website = stringFieldType(false);
|
||||
groupedFieldTypes.longtext = stringFieldType(true);
|
||||
groupedFieldTypes.gpg = stringFieldType(true);
|
||||
groupedFieldTypes.number = numberFieldType;
|
||||
groupedFieldTypes.date = dateFieldType;
|
||||
groupedFieldTypes.birthday = birthdayFieldType;
|
||||
groupedFieldTypes.json = jsonFieldType;
|
||||
groupedFieldTypes.option = optionFieldType;
|
||||
groupedFieldTypes['dropdown-enum'] = enumSingleFieldType(Dropdown);
|
||||
groupedFieldTypes['radio-enum'] = enumSingleFieldType(RadioGroup);
|
||||
|
||||
// Here we rely on the fact the model/groupedFields and model/subscriptions preprocess the groupedField info and subscription
|
||||
// such that the grouped entries behave the same as the enum entries
|
||||
groupedFieldTypes['checkbox-grouped'] = enumMultipleFieldType(CheckBoxGroup);
|
||||
groupedFieldTypes['radio-grouped'] = enumSingleFieldType(RadioGroup);
|
||||
groupedFieldTypes['dropdown-grouped'] = enumSingleFieldType(Dropdown);
|
||||
|
||||
return groupedFieldTypes;
|
||||
'use strict';
|
||||
|
||||
import React from "react";
|
||||
import {SubscriptionStatus} from "../../../../shared/lists";
|
||||
import {
|
||||
ACEEditor,
|
||||
CheckBox,
|
||||
CheckBoxGroup,
|
||||
DatePicker,
|
||||
Dropdown,
|
||||
InputField,
|
||||
RadioGroup,
|
||||
TextArea
|
||||
} from "../../lib/form";
|
||||
import {formatBirthday, formatDate, parseBirthday, parseDate} from "../../../../shared/date";
|
||||
import {getFieldColumn} from '../../../../shared/lists';
|
||||
import 'brace/mode/json';
|
||||
|
||||
export function getSubscriptionStatusLabels(t) {
|
||||
|
||||
const subscriptionStatusLabels = {
|
||||
[SubscriptionStatus.SUBSCRIBED]: t('subscribed'),
|
||||
[SubscriptionStatus.UNSUBSCRIBED]: t('unubscribed'),
|
||||
[SubscriptionStatus.BOUNCED]: t('bounced'),
|
||||
[SubscriptionStatus.COMPLAINED]: t('complained'),
|
||||
};
|
||||
|
||||
return subscriptionStatusLabels;
|
||||
}
|
||||
|
||||
export function getFieldTypes(t) {
|
||||
|
||||
const groupedFieldTypes = {};
|
||||
|
||||
const stringFieldType = long => ({
|
||||
form: groupedField => long ? <TextArea key={getFieldColumn(groupedField)} id={getFieldColumn(groupedField)} label={groupedField.name}/> : <InputField key={getFieldColumn(groupedField)} id={getFieldColumn(groupedField)} label={groupedField.name}/>,
|
||||
assignFormData: (groupedField, data) => {
|
||||
const value = data[getFieldColumn(groupedField)];
|
||||
data[getFieldColumn(groupedField)] = value || '';
|
||||
},
|
||||
initFormData: (groupedField, data) => {
|
||||
data[getFieldColumn(groupedField)] = '';
|
||||
},
|
||||
assignEntity: (groupedField, data) => {},
|
||||
validate: (groupedField, state) => {},
|
||||
indexable: true
|
||||
});
|
||||
|
||||
const numberFieldType = {
|
||||
form: groupedField => <InputField key={getFieldColumn(groupedField)} id={getFieldColumn(groupedField)} label={groupedField.name}/>,
|
||||
assignFormData: (groupedField, data) => {
|
||||
const value = data[getFieldColumn(groupedField)];
|
||||
data[getFieldColumn(groupedField)] = value ? value.toString() : '';
|
||||
},
|
||||
initFormData: (groupedField, data) => {
|
||||
data[getFieldColumn(groupedField)] = '';
|
||||
},
|
||||
assignEntity: (groupedField, data) => {
|
||||
data[getFieldColumn(groupedField)] = parseInt(data[getFieldColumn(groupedField)]);
|
||||
},
|
||||
validate: (groupedField, state) => {
|
||||
const value = state.getIn([getFieldColumn(groupedField), 'value']).trim();
|
||||
if (value !== '' && isNaN(value)) {
|
||||
state.setIn([getFieldColumn(groupedField), 'error'], t('valueMustBeANumber'));
|
||||
} else {
|
||||
state.setIn([getFieldColumn(groupedField), 'error'], null);
|
||||
}
|
||||
},
|
||||
indexable: true
|
||||
};
|
||||
|
||||
const dateFieldType = {
|
||||
form: groupedField => <DatePicker key={getFieldColumn(groupedField)} id={getFieldColumn(groupedField)} label={groupedField.name} dateFormat={groupedField.settings.dateFormat} />,
|
||||
assignFormData: (groupedField, data) => {
|
||||
const value = data[getFieldColumn(groupedField)];
|
||||
data[getFieldColumn(groupedField)] = value ? formatDate(groupedField.settings.dateFormat, value) : '';
|
||||
},
|
||||
initFormData: (groupedField, data) => {
|
||||
data[getFieldColumn(groupedField)] = '';
|
||||
},
|
||||
assignEntity: (groupedField, data) => {
|
||||
const date = parseDate(groupedField.settings.dateFormat, data[getFieldColumn(groupedField)]);
|
||||
data[getFieldColumn(groupedField)] = date;
|
||||
},
|
||||
validate: (groupedField, state) => {
|
||||
const value = state.getIn([getFieldColumn(groupedField), 'value']);
|
||||
const date = parseDate(groupedField.settings.dateFormat, value);
|
||||
if (value !== '' && !date) {
|
||||
state.setIn([getFieldColumn(groupedField), 'error'], t('dateIsInvalid'));
|
||||
} else {
|
||||
state.setIn([getFieldColumn(groupedField), 'error'], null);
|
||||
}
|
||||
},
|
||||
indexable: true
|
||||
};
|
||||
|
||||
const birthdayFieldType = {
|
||||
form: groupedField => <DatePicker key={getFieldColumn(groupedField)} id={getFieldColumn(groupedField)} label={groupedField.name} dateFormat={groupedField.settings.dateFormat} birthday />,
|
||||
assignFormData: (groupedField, data) => {
|
||||
const value = data[getFieldColumn(groupedField)];
|
||||
data[getFieldColumn(groupedField)] = value ? formatBirthday(groupedField.settings.dateFormat, value) : '';
|
||||
},
|
||||
initFormData: (groupedField, data) => {
|
||||
data[getFieldColumn(groupedField)] = '';
|
||||
},
|
||||
assignEntity: (groupedField, data) => {
|
||||
const date = parseBirthday(groupedField.settings.dateFormat, data[getFieldColumn(groupedField)]);
|
||||
data[getFieldColumn(groupedField)] = date;
|
||||
},
|
||||
validate: (groupedField, state) => {
|
||||
const value = state.getIn([getFieldColumn(groupedField), 'value']);
|
||||
const date = parseBirthday(groupedField.settings.dateFormat, value);
|
||||
if (value !== '' && !date) {
|
||||
state.setIn([getFieldColumn(groupedField), 'error'], t('dateIsInvalid'));
|
||||
} else {
|
||||
state.setIn([getFieldColumn(groupedField), 'error'], null);
|
||||
}
|
||||
},
|
||||
indexable: true
|
||||
};
|
||||
|
||||
const jsonFieldType = {
|
||||
form: groupedField => <ACEEditor key={getFieldColumn(groupedField)} id={getFieldColumn(groupedField)} label={groupedField.name} mode="json" height="300px"/>,
|
||||
assignFormData: (groupedField, data) => {
|
||||
const value = data[getFieldColumn(groupedField)];
|
||||
data[getFieldColumn(groupedField)] = value || '';
|
||||
},
|
||||
initFormData: (groupedField, data) => {
|
||||
data[getFieldColumn(groupedField)] = '';
|
||||
},
|
||||
assignEntity: (groupedField, data) => {},
|
||||
validate: (groupedField, state) => {},
|
||||
indexable: false
|
||||
};
|
||||
|
||||
const optionFieldType = {
|
||||
form: groupedField => <CheckBox key={getFieldColumn(groupedField)} id={getFieldColumn(groupedField)} text={groupedField.settings.checkedLabel} label={groupedField.name}/>,
|
||||
assignFormData: (groupedField, data) => {
|
||||
const value = data[getFieldColumn(groupedField)];
|
||||
data[getFieldColumn(groupedField)] = !!value;
|
||||
},
|
||||
initFormData: (groupedField, data) => {
|
||||
data[getFieldColumn(groupedField)] = false;
|
||||
},
|
||||
assignEntity: (groupedField, data) => {},
|
||||
validate: (groupedField, state) => {},
|
||||
indexable: true
|
||||
};
|
||||
|
||||
const enumSingleFieldType = componentType => ({
|
||||
form: groupedField => React.createElement(componentType, { key: getFieldColumn(groupedField), id: getFieldColumn(groupedField), label: groupedField.name, options: groupedField.settings.options }, null),
|
||||
assignFormData: (groupedField, data) => {
|
||||
if (data[getFieldColumn(groupedField)] === null) {
|
||||
if (groupedField.default_value) {
|
||||
data[getFieldColumn(groupedField)] = groupedField.default_value;
|
||||
} else if (groupedField.settings.options.length > 0) {
|
||||
data[getFieldColumn(groupedField)] = groupedField.settings.options[0].key;
|
||||
} else {
|
||||
data[getFieldColumn(groupedField)] = '';
|
||||
}
|
||||
}
|
||||
},
|
||||
initFormData: (groupedField, data) => {
|
||||
if (groupedField.default_value) {
|
||||
data[getFieldColumn(groupedField)] = groupedField.default_value;
|
||||
} else if (groupedField.settings.options.length > 0) {
|
||||
data[getFieldColumn(groupedField)] = groupedField.settings.options[0].key;
|
||||
} else {
|
||||
data[getFieldColumn(groupedField)] = '';
|
||||
}
|
||||
},
|
||||
assignEntity: (groupedField, data) => {},
|
||||
validate: (groupedField, state) => {},
|
||||
indexable: false
|
||||
});
|
||||
|
||||
const enumMultipleFieldType = componentType => ({
|
||||
form: groupedField => React.createElement(componentType, { key: getFieldColumn(groupedField), id: getFieldColumn(groupedField), label: groupedField.name, options: groupedField.settings.options }, null),
|
||||
assignFormData: (groupedField, data) => {
|
||||
if (data[getFieldColumn(groupedField)] === null) {
|
||||
data[getFieldColumn(groupedField)] = [];
|
||||
}
|
||||
},
|
||||
initFormData: (groupedField, data) => {
|
||||
data[getFieldColumn(groupedField)] = [];
|
||||
},
|
||||
assignEntity: (groupedField, data) => {},
|
||||
validate: (groupedField, state) => {},
|
||||
indexable: false
|
||||
});
|
||||
|
||||
|
||||
groupedFieldTypes.text = stringFieldType(false);
|
||||
groupedFieldTypes.website = stringFieldType(false);
|
||||
groupedFieldTypes.longtext = stringFieldType(true);
|
||||
groupedFieldTypes.gpg = stringFieldType(true);
|
||||
groupedFieldTypes.number = numberFieldType;
|
||||
groupedFieldTypes.date = dateFieldType;
|
||||
groupedFieldTypes.birthday = birthdayFieldType;
|
||||
groupedFieldTypes.json = jsonFieldType;
|
||||
groupedFieldTypes.option = optionFieldType;
|
||||
groupedFieldTypes['dropdown-enum'] = enumSingleFieldType(Dropdown);
|
||||
groupedFieldTypes['radio-enum'] = enumSingleFieldType(RadioGroup);
|
||||
|
||||
// Here we rely on the fact the model/groupedFields and model/subscriptions preprocess the groupedField info and subscription
|
||||
// such that the grouped entries behave the same as the enum entries
|
||||
groupedFieldTypes['checkbox-grouped'] = enumMultipleFieldType(CheckBoxGroup);
|
||||
groupedFieldTypes['radio-grouped'] = enumSingleFieldType(RadioGroup);
|
||||
groupedFieldTypes['dropdown-grouped'] = enumSingleFieldType(Dropdown);
|
||||
|
||||
return groupedFieldTypes;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue