Finish up the queryTransitions refactor
parent
d3a2c2e962
commit
8bc46b1cae
|
@ -175,6 +175,7 @@ describe('Chronograf.Reducers.queryConfig', () => {
|
|||
|
||||
const nextState = reducer(initialState, action);
|
||||
|
||||
console.log('im nextstate :)', nextState)
|
||||
expect(nextState[queryId].tags).to.eql({
|
||||
k1: ['v0', 'v1'],
|
||||
k2: ['foo'],
|
||||
|
|
|
@ -1,7 +1,16 @@
|
|||
import defaultQueryConfig from 'src/utils/defaultQueryConfig';
|
||||
import {chooseNamespace, chooseMeasurement, toggleField} from 'src/utils/queryTransitions';
|
||||
import {
|
||||
applyFuncsToField,
|
||||
chooseMeasurement,
|
||||
chooseNamespace,
|
||||
chooseTag,
|
||||
groupByTag,
|
||||
groupByTime,
|
||||
toggleField,
|
||||
toggleTagAcceptance,
|
||||
updateRawQuery,
|
||||
} from 'src/utils/queryTransitions';
|
||||
import update from 'react-addons-update';
|
||||
import u from 'updeep';
|
||||
|
||||
export default function queryConfigs(state = {}, action) {
|
||||
switch (action.type) {
|
||||
|
@ -12,19 +21,19 @@ export default function queryConfigs(state = {}, action) {
|
|||
case 'CHOOSE_NAMESPACE': {
|
||||
const {queryId, database, retentionPolicy} = action.payload;
|
||||
const nextQueryConfig = chooseNamespace(defaultQueryConfig(queryId), {database, retentionPolicy});
|
||||
const nextState = update(state, {
|
||||
[queryId]: {$set: nextQueryConfig},
|
||||
|
||||
return Object.assign({}, state, {
|
||||
[queryId]: nextQueryConfig,
|
||||
});
|
||||
return nextState;
|
||||
}
|
||||
|
||||
case 'CHOOSE_MEASUREMENT': {
|
||||
const {queryId, measurement} = action.payload;
|
||||
const nextQueryConfig = chooseMeasurement(state[queryId], measurement);
|
||||
const nextState = update(state, {
|
||||
[queryId]: {$set: nextQueryConfig},
|
||||
|
||||
return Object.assign({}, state, {
|
||||
[queryId]: nextQueryConfig,
|
||||
});
|
||||
return nextState;
|
||||
}
|
||||
|
||||
case 'CREATE_PANEL':
|
||||
|
@ -48,26 +57,20 @@ export default function queryConfigs(state = {}, action) {
|
|||
|
||||
case 'GROUP_BY_TIME': {
|
||||
const {queryId, time} = action.payload;
|
||||
const nextState = update(state, {
|
||||
[queryId]: {
|
||||
groupBy: {
|
||||
time: {$set: time},
|
||||
},
|
||||
},
|
||||
});
|
||||
const nextQueryConfig = groupByTime(state[queryId], time);
|
||||
|
||||
return nextState;
|
||||
return Object.assign({}, state, {
|
||||
[queryId]: nextQueryConfig,
|
||||
});
|
||||
}
|
||||
|
||||
case 'TOGGLE_TAG_ACCEPTANCE': {
|
||||
const {queryId} = action.payload;
|
||||
const nextState = update(state, {
|
||||
[queryId]: {
|
||||
areTagsAccepted: {$set: !state[queryId].areTagsAccepted},
|
||||
},
|
||||
});
|
||||
const nextQueryConfig = toggleTagAcceptance(state[queryId]);
|
||||
|
||||
return nextState;
|
||||
return Object.assign({}, state, {
|
||||
[queryId]: nextQueryConfig,
|
||||
});
|
||||
}
|
||||
|
||||
case 'DELETE_QUERY': {
|
||||
|
@ -91,115 +94,36 @@ export default function queryConfigs(state = {}, action) {
|
|||
|
||||
case 'APPLY_FUNCS_TO_FIELD': {
|
||||
const {queryId, fieldFunc} = action.payload;
|
||||
const {field, funcs} = fieldFunc;
|
||||
const shouldRemoveFuncs = funcs.length === 0;
|
||||
const nextQueryConfig = applyFuncsToField(state[queryId], fieldFunc);
|
||||
|
||||
const nextState = update(state, {
|
||||
[queryId]: {$apply: (queryConfig) => {
|
||||
const nextFields = queryConfig.fields.map((f) => {
|
||||
// If one field has no funcs, all fields must have no funcs
|
||||
if (shouldRemoveFuncs) {
|
||||
return update(f, {funcs: {$set: []}});
|
||||
}
|
||||
|
||||
if (f.field === field || !f.funcs || !f.funcs.length) {
|
||||
return update(f, {funcs: {$set: funcs}});
|
||||
}
|
||||
|
||||
return f;
|
||||
});
|
||||
|
||||
// If there are no functions, then there should be no GROUP BY time
|
||||
if (shouldRemoveFuncs) {
|
||||
const nextGroupBy = update(state[queryId].groupBy, {time: {$set: null}});
|
||||
return update(queryConfig, {fields: {$set: nextFields}, groupBy: {$set: nextGroupBy}});
|
||||
}
|
||||
|
||||
return update(queryConfig, {fields: {$set: nextFields}});
|
||||
}},
|
||||
return Object.assign({}, state, {
|
||||
[queryId]: nextQueryConfig,
|
||||
});
|
||||
|
||||
return nextState;
|
||||
}
|
||||
|
||||
case 'CHOOSE_TAG': {
|
||||
const {queryId, tag} = action.payload;
|
||||
const nextQueryConfig = chooseTag(state[queryId], tag);
|
||||
|
||||
const tagValues = state[queryId].tags[tag.key];
|
||||
const shouldRemoveTag = tagValues && tagValues.length === 1 && tagValues[0] === tag.value;
|
||||
if (shouldRemoveTag) {
|
||||
const nextState = update(state, {
|
||||
[queryId]: {
|
||||
tags: {$apply: (tags) => {
|
||||
const tagsCopy = Object.assign({}, tags);
|
||||
delete tagsCopy[tag.key];
|
||||
return tagsCopy;
|
||||
}},
|
||||
},
|
||||
});
|
||||
|
||||
return nextState;
|
||||
}
|
||||
|
||||
const nextState = update(state, {
|
||||
[queryId]: {
|
||||
tags: {
|
||||
[tag.key]: {$apply: (vals) => {
|
||||
if (!vals) {
|
||||
return [tag.value];
|
||||
}
|
||||
|
||||
// If the tag value is already selected, deselect it by removing it from the list
|
||||
const valsCopy = vals.slice();
|
||||
const i = valsCopy.indexOf(tag.value);
|
||||
if (i > -1) {
|
||||
valsCopy.splice(i, 1);
|
||||
return valsCopy;
|
||||
}
|
||||
|
||||
return update(valsCopy, {$push: [tag.value]});
|
||||
}},
|
||||
},
|
||||
},
|
||||
return Object.assign({}, state, {
|
||||
[queryId]: nextQueryConfig,
|
||||
});
|
||||
|
||||
return nextState;
|
||||
}
|
||||
|
||||
case 'GROUP_BY_TAG': {
|
||||
const {queryId, tagKey} = action.payload;
|
||||
|
||||
const nextState = update(state, {
|
||||
[queryId]: {
|
||||
groupBy: {
|
||||
tags: {$apply: (groupByTags) => {
|
||||
// If the tag value is already selected, deselect it by removing it from the list
|
||||
const groupByTagsCopy = groupByTags.slice();
|
||||
const i = groupByTagsCopy.indexOf(tagKey);
|
||||
if (i > -1) {
|
||||
groupByTagsCopy.splice(i, 1);
|
||||
return groupByTagsCopy;
|
||||
}
|
||||
|
||||
return update(groupByTagsCopy, {$push: [tagKey]});
|
||||
}},
|
||||
},
|
||||
},
|
||||
const nextQueryConfig = groupByTag(state[queryId], tagKey);
|
||||
return Object.assign({}, state, {
|
||||
[queryId]: nextQueryConfig,
|
||||
});
|
||||
|
||||
return nextState;
|
||||
}
|
||||
|
||||
case 'UPDATE_RAW_QUERY': {
|
||||
const {queryID, text} = action.payload;
|
||||
|
||||
const updateQuery = {
|
||||
[queryID]: {
|
||||
rawText: u.constant(text),
|
||||
},
|
||||
};
|
||||
|
||||
return u(updateQuery, state);
|
||||
const nextQueryConfig = updateRawQuery(state[queryID], text);
|
||||
return Object.assign({}, state, {
|
||||
[queryID]: nextQueryConfig,
|
||||
});
|
||||
}
|
||||
}
|
||||
return state;
|
||||
|
|
|
@ -33,3 +33,102 @@ export function toggleField(query, {field, funcs}) {
|
|||
fields: query.fields.concat({field, funcs}),
|
||||
});
|
||||
}
|
||||
|
||||
export function groupByTime(query, time) {
|
||||
return Object.assign({}, query, {
|
||||
groupBy: Object.assign({}, query.groupBy, {
|
||||
time,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
export function toggleTagAcceptance(query) {
|
||||
return Object.assign({}, query, {
|
||||
areTagsAccepted: !query.areTagsAccepted,
|
||||
});
|
||||
}
|
||||
|
||||
export function applyFuncsToField(query, {field, funcs}) {
|
||||
const shouldRemoveFuncs = funcs.length === 0;
|
||||
const nextFields = query.fields.map((f) => {
|
||||
// If one field has no funcs, all fields must have no funcs
|
||||
if (shouldRemoveFuncs) {
|
||||
return Object.assign({}, f, {funcs: []});
|
||||
}
|
||||
|
||||
// If there is a func applied to only one field, add it to the other fields
|
||||
if (f.field === field || !f.funcs || !f.funcs.length) {
|
||||
return Object.assign({}, f, {funcs});
|
||||
}
|
||||
|
||||
return f;
|
||||
});
|
||||
|
||||
// If there are no functions, then there should be no GROUP BY time
|
||||
if (shouldRemoveFuncs) {
|
||||
const nextGroupBy = Object.assign({}, query.groupBy, {time: null});
|
||||
return Object.assign({}, query, {
|
||||
fields: nextFields,
|
||||
groupBy: nextGroupBy,
|
||||
});
|
||||
}
|
||||
|
||||
return Object.assign({}, query, {fields: nextFields});
|
||||
}
|
||||
|
||||
export function updateRawQuery(query, rawText) {
|
||||
return Object.assign({}, query, {
|
||||
rawText,
|
||||
});
|
||||
}
|
||||
|
||||
export function groupByTag(query, tagKey) {
|
||||
const oldTags = query.groupBy.tags;
|
||||
let newTags;
|
||||
|
||||
// Toggle the presence of the tagKey
|
||||
if (oldTags.includes(tagKey)) {
|
||||
const i = oldTags.indexOf(tagKey);
|
||||
newTags = oldTags.slice();
|
||||
newTags.splice(i, 1);
|
||||
} else {
|
||||
newTags = oldTags.concat(tagKey);
|
||||
}
|
||||
|
||||
return Object.assign({}, query, {
|
||||
groupBy: Object.assign({}, query.groupBy, {tags: newTags}),
|
||||
});
|
||||
}
|
||||
|
||||
export function chooseTag(query, tag) {
|
||||
const tagValues = query.tags[tag.key];
|
||||
const shouldRemoveTag = tagValues && tagValues.length === 1 && tagValues[0] === tag.value;
|
||||
if (shouldRemoveTag) {
|
||||
const newTags = Object.assign({}, query.tags);
|
||||
delete newTags[tag.key];
|
||||
return Object.assign({}, query, {tags: newTags});
|
||||
}
|
||||
|
||||
const oldTagValues = query.tags[tag.key];
|
||||
if (!oldTagValues) {
|
||||
return updateTagValues([tag.value]);
|
||||
}
|
||||
|
||||
// If the tag value is already selected, deselect it by removing it from the list
|
||||
const tagValuesCopy = oldTagValues.slice();
|
||||
const i = tagValuesCopy.indexOf(tag.value);
|
||||
if (i > -1) {
|
||||
tagValuesCopy.splice(i, 1);
|
||||
return updateTagValues(tagValuesCopy);
|
||||
}
|
||||
|
||||
return updateTagValues(query.tags[tag.key].concat(tag.value));
|
||||
|
||||
function updateTagValues(newTagValues) {
|
||||
return Object.assign({}, query, {
|
||||
tags: Object.assign({}, query.tags, {
|
||||
[tag.key]: newTagValues,
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue