Skip to content

Commit

Permalink
[State Management] Remove AppState from edit_index_pattern page (#54104
Browse files Browse the repository at this point in the history
…) (#55294)

Replaces AppState in edit_index_pattern with state containers and state syncing utils.
In addition makes tab navigation on edit_index_pattern work with browser's undo history
  • Loading branch information
Dosant authored Jan 20, 2020
1 parent 3f93f48 commit f6c882e
Show file tree
Hide file tree
Showing 3 changed files with 243 additions and 134 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@
<button
class="kuiTab"
ng-repeat="editSection in editSections"
ng-class="{ 'kuiTab-isSelected': state.tab === editSection.index }"
ng-click="changeTab(editSection)"
ng-class="{ 'kuiTab-isSelected': getCurrentTab() === editSection.index }"
ng-click="setCurrentTab(editSection.index)"
data-test-subj="tab-{{ editSection.index }}"
>
{{ editSection.title }}
Expand Down Expand Up @@ -152,7 +152,7 @@

<div
class="kuiFieldGroupSection"
ng-if="state.tab == 'indexedFields' && indexedFieldTypes.length > 0"
ng-if="getCurrentTab() == 'indexedFields' && indexedFieldTypes.length > 0"
>
<select
data-test-subj="indexedFieldTypeFilterDropdown"
Expand All @@ -169,7 +169,7 @@

<div
class="kuiFieldGroupSection"
ng-if="state.tab == 'scriptedFields' && scriptedFieldLanguages.length > 0"
ng-if="getCurrentTab() == 'scriptedFields' && scriptedFieldLanguages.length > 0"
>
<select
data-test-subj="scriptedFieldLanguageFilterDropdown"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,134 +37,146 @@ import { ScriptedFieldsTable } from './scripted_fields_table';
import { i18n } from '@kbn/i18n';
import { I18nContext } from 'ui/i18n';
import { npStart } from 'ui/new_platform';
import { subscribeWithScope } from 'ui/utils/subscribe_with_scope';

import { getEditBreadcrumbs } from '../breadcrumbs';
import { createEditIndexPatternPageStateContainer } from './edit_index_pattern_state_container';

const REACT_SOURCE_FILTERS_DOM_ELEMENT_ID = 'reactSourceFiltersTable';
const REACT_INDEXED_FIELDS_DOM_ELEMENT_ID = 'reactIndexedFieldsTable';
const REACT_SCRIPTED_FIELDS_DOM_ELEMENT_ID = 'reactScriptedFieldsTable';

function updateSourceFiltersTable($scope, $state) {
if ($state.tab === 'sourceFilters') {
$scope.$$postDigest(() => {
const node = document.getElementById(REACT_SOURCE_FILTERS_DOM_ELEMENT_ID);
if (!node) {
return;
}

render(
<I18nContext>
<SourceFiltersTable
indexPattern={$scope.indexPattern}
filterFilter={$scope.fieldFilter}
fieldWildcardMatcher={$scope.fieldWildcardMatcher}
onAddOrRemoveFilter={() => {
$scope.editSections = $scope.editSectionsProvider(
$scope.indexPattern,
$scope.fieldFilter,
$scope.indexPatternListProvider
);
$scope.refreshFilters();
$scope.$apply();
}}
/>
</I18nContext>,
node
);
});
} else {
destroySourceFiltersTable();
}
const TAB_INDEXED_FIELDS = 'indexedFields';
const TAB_SCRIPTED_FIELDS = 'scriptedFields';
const TAB_SOURCE_FILTERS = 'sourceFilters';

function updateSourceFiltersTable($scope) {
$scope.$$postDigest(() => {
const node = document.getElementById(REACT_SOURCE_FILTERS_DOM_ELEMENT_ID);
if (!node) {
return;
}

render(
<I18nContext>
<SourceFiltersTable
indexPattern={$scope.indexPattern}
filterFilter={$scope.fieldFilter}
fieldWildcardMatcher={$scope.fieldWildcardMatcher}
onAddOrRemoveFilter={() => {
$scope.editSections = $scope.editSectionsProvider(
$scope.indexPattern,
$scope.fieldFilter,
$scope.indexPatternListProvider
);
$scope.refreshFilters();
$scope.$apply();
}}
/>
</I18nContext>,
node
);
});
}

function destroySourceFiltersTable() {
const node = document.getElementById(REACT_SOURCE_FILTERS_DOM_ELEMENT_ID);
node && unmountComponentAtNode(node);
}

function updateScriptedFieldsTable($scope, $state) {
if ($state.tab === 'scriptedFields') {
$scope.$$postDigest(() => {
const node = document.getElementById(REACT_SCRIPTED_FIELDS_DOM_ELEMENT_ID);
if (!node) {
return;
}

render(
<I18nContext>
<ScriptedFieldsTable
indexPattern={$scope.indexPattern}
fieldFilter={$scope.fieldFilter}
scriptedFieldLanguageFilter={$scope.scriptedFieldLanguageFilter}
helpers={{
redirectToRoute: (obj, route) => {
$scope.kbnUrl.redirectToRoute(obj, route);
$scope.$apply();
},
getRouteHref: (obj, route) => $scope.kbnUrl.getRouteHref(obj, route),
}}
onRemoveField={() => {
$scope.editSections = $scope.editSectionsProvider(
$scope.indexPattern,
$scope.fieldFilter,
$scope.indexPatternListProvider
);
$scope.refreshFilters();
function updateScriptedFieldsTable($scope) {
$scope.$$postDigest(() => {
const node = document.getElementById(REACT_SCRIPTED_FIELDS_DOM_ELEMENT_ID);
if (!node) {
return;
}

render(
<I18nContext>
<ScriptedFieldsTable
indexPattern={$scope.indexPattern}
fieldFilter={$scope.fieldFilter}
scriptedFieldLanguageFilter={$scope.scriptedFieldLanguageFilter}
helpers={{
redirectToRoute: (obj, route) => {
$scope.kbnUrl.changeToRoute(obj, route);
$scope.$apply();
}}
/>
</I18nContext>,
node
);
});
} else {
destroyScriptedFieldsTable();
}
},
getRouteHref: (obj, route) => $scope.kbnUrl.getRouteHref(obj, route),
}}
onRemoveField={() => {
$scope.editSections = $scope.editSectionsProvider(
$scope.indexPattern,
$scope.fieldFilter,
$scope.indexPatternListProvider
);
$scope.refreshFilters();
$scope.$apply();
}}
/>
</I18nContext>,
node
);
});
}

function destroyScriptedFieldsTable() {
const node = document.getElementById(REACT_SCRIPTED_FIELDS_DOM_ELEMENT_ID);
node && unmountComponentAtNode(node);
}

function updateIndexedFieldsTable($scope, $state) {
if ($state.tab === 'indexedFields') {
$scope.$$postDigest(() => {
const node = document.getElementById(REACT_INDEXED_FIELDS_DOM_ELEMENT_ID);
if (!node) {
return;
}

render(
<I18nContext>
<IndexedFieldsTable
fields={$scope.fields}
indexPattern={$scope.indexPattern}
fieldFilter={$scope.fieldFilter}
fieldWildcardMatcher={$scope.fieldWildcardMatcher}
indexedFieldTypeFilter={$scope.indexedFieldTypeFilter}
helpers={{
redirectToRoute: (obj, route) => {
$scope.kbnUrl.redirectToRoute(obj, route);
$scope.$apply();
},
getFieldInfo: $scope.getFieldInfo,
}}
/>
</I18nContext>,
node
);
});
} else {
destroyIndexedFieldsTable();
}
function updateIndexedFieldsTable($scope) {
$scope.$$postDigest(() => {
const node = document.getElementById(REACT_INDEXED_FIELDS_DOM_ELEMENT_ID);
if (!node) {
return;
}

render(
<I18nContext>
<IndexedFieldsTable
fields={$scope.fields}
indexPattern={$scope.indexPattern}
fieldFilter={$scope.fieldFilter}
fieldWildcardMatcher={$scope.fieldWildcardMatcher}
indexedFieldTypeFilter={$scope.indexedFieldTypeFilter}
helpers={{
redirectToRoute: (obj, route) => {
$scope.kbnUrl.changeToRoute(obj, route);
$scope.$apply();
},
getFieldInfo: $scope.getFieldInfo,
}}
/>
</I18nContext>,
node
);
});
}

function destroyIndexedFieldsTable() {
const node = document.getElementById(REACT_INDEXED_FIELDS_DOM_ELEMENT_ID);
node && unmountComponentAtNode(node);
}

function handleTabChange($scope, newTab) {
destroyIndexedFieldsTable();
destroySourceFiltersTable();
destroyScriptedFieldsTable();
updateTables($scope, newTab);
}

function updateTables($scope, currentTab) {
switch (currentTab) {
case TAB_SCRIPTED_FIELDS:
return updateScriptedFieldsTable($scope);
case TAB_INDEXED_FIELDS:
return updateIndexedFieldsTable($scope);
case TAB_SOURCE_FILTERS:
return updateSourceFiltersTable($scope);
}
}

uiRoutes.when('/management/kibana/index_patterns/:indexPatternId', {
template,
k7Breadcrumbs: getEditBreadcrumbs,
Expand All @@ -187,10 +199,36 @@ uiModules
Promise,
config,
Private,
AppState,
confirmModal
) {
const $state = ($scope.state = new AppState());
const {
startSyncingState,
stopSyncingState,
setCurrentTab,
getCurrentTab,
state$,
} = createEditIndexPatternPageStateContainer({
useHashedUrl: config.get('state:storeInSessionStorage'),
defaultTab: TAB_INDEXED_FIELDS,
});

$scope.getCurrentTab = getCurrentTab;
$scope.setCurrentTab = setCurrentTab;

const stateChangedSub = subscribeWithScope($scope, state$, {
next: ({ tab }) => {
handleTabChange($scope, tab);
},
});

handleTabChange($scope, getCurrentTab()); // setup initial tab depending on initial tab state

startSyncingState(); // starts syncing state between state container and url

const destroyState = () => {
stateChangedSub.unsubscribe();
stopSyncingState();
};

$scope.fieldWildcardMatcher = (...args) =>
fieldWildcardMatcher(...args, config.get('metaFields'));
Expand Down Expand Up @@ -219,8 +257,6 @@ uiModules
);
$scope.refreshFilters();
$scope.fields = $scope.indexPattern.getNonScriptedFields();
updateIndexedFieldsTable($scope, $state);
updateScriptedFieldsTable($scope, $state);
});

$scope.migration = {
Expand Down Expand Up @@ -254,18 +290,6 @@ uiModules
$scope[filter] = val || ''; // null causes filter to check for null explicitly
};

$scope.changeTab = function(obj) {
$state.tab = obj.index;
updateIndexedFieldsTable($scope, $state);
updateScriptedFieldsTable($scope, $state);
updateSourceFiltersTable($scope, $state);
$state.save();
};

$scope.$watch('state.tab', function(tab) {
if (!tab) $scope.changeTab($scope.editSections[0]);
});

$scope.$watchCollection('indexPattern.fields', function() {
$scope.conflictFields = $scope.indexPattern.fields.filter(field => field.type === 'conflict');
});
Expand Down Expand Up @@ -341,37 +365,33 @@ uiModules
$scope.fieldFilter,
managementSetup.indexPattern.list
);

if ($scope.fieldFilter === undefined) {
return;
}

switch ($state.tab) {
case 'indexedFields':
updateIndexedFieldsTable($scope, $state);
case 'scriptedFields':
updateScriptedFieldsTable($scope, $state);
case 'sourceFilters':
updateSourceFiltersTable($scope, $state);
}
updateTables($scope, getCurrentTab());
});

$scope.$watch('indexedFieldTypeFilter', () => {
if ($scope.indexedFieldTypeFilter !== undefined && $state.tab === 'indexedFields') {
updateIndexedFieldsTable($scope, $state);
if ($scope.indexedFieldTypeFilter !== undefined && getCurrentTab() === TAB_INDEXED_FIELDS) {
updateIndexedFieldsTable($scope);
}
});

$scope.$watch('scriptedFieldLanguageFilter', () => {
if ($scope.scriptedFieldLanguageFilter !== undefined && $state.tab === 'scriptedFields') {
updateScriptedFieldsTable($scope, $state);
if (
$scope.scriptedFieldLanguageFilter !== undefined &&
getCurrentTab() === TAB_SCRIPTED_FIELDS
) {
updateScriptedFieldsTable($scope);
}
});

$scope.$on('$destroy', () => {
destroyIndexedFieldsTable();
destroyScriptedFieldsTable();
destroySourceFiltersTable();
destroyState();
});

updateScriptedFieldsTable($scope, $state);
updateSourceFiltersTable($scope, $state);
});
Loading

0 comments on commit f6c882e

Please sign in to comment.