diff options
Diffstat (limited to 'app/assets/javascripts/ml/experiment_tracking/components/ml_experiment.vue')
-rw-r--r-- | app/assets/javascripts/ml/experiment_tracking/components/ml_experiment.vue | 132 |
1 files changed, 99 insertions, 33 deletions
diff --git a/app/assets/javascripts/ml/experiment_tracking/components/ml_experiment.vue b/app/assets/javascripts/ml/experiment_tracking/components/ml_experiment.vue index 5d13122765a..c09aabb0d40 100644 --- a/app/assets/javascripts/ml/experiment_tracking/components/ml_experiment.vue +++ b/app/assets/javascripts/ml/experiment_tracking/components/ml_experiment.vue @@ -1,9 +1,20 @@ <script> -import { GlTable, GlLink, GlPagination, GlTooltipDirective } from '@gitlab/ui'; -import { __ } from '~/locale'; -import { getParameterValues, setUrlParams } from '~/lib/utils/url_utility'; +import { GlTable, GlLink, GlTooltipDirective } from '@gitlab/ui'; import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue'; -import IncubationAlert from './incubation_alert.vue'; +import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue'; +import { FILTERED_SEARCH_TERM } from '~/vue_shared/components/filtered_search_bar/constants'; +import { + LIST_KEY_CREATED_AT, + BASE_SORT_FIELDS, + METRIC_KEY_PREFIX, + FEATURE_NAME, + FEATURE_FEEDBACK_ISSUE, +} from '~/ml/experiment_tracking/constants'; +import { s__ } from '~/locale'; +import { queryToObject, setUrlParams, visitUrl } from '~/lib/utils/url_utility'; +import { capitalizeFirstCharacter } from '~/lib/utils/text_utility'; +import KeysetPagination from '~/vue_shared/components/incubation/pagination.vue'; +import IncubationAlert from '~/vue_shared/components/incubation/incubation_alert.vue'; export default { name: 'MlExperiment', @@ -12,19 +23,36 @@ export default { GlLink, TimeAgo, IncubationAlert, - GlPagination, + RegistrySearch, + KeysetPagination, }, directives: { GlTooltip: GlTooltipDirective, }, - inject: ['candidates', 'metricNames', 'paramNames', 'pagination'], + inject: ['candidates', 'metricNames', 'paramNames', 'pageInfo'], data() { + const query = queryToObject(window.location.search); + + const filter = query.name ? [{ value: { data: query.name }, type: FILTERED_SEARCH_TERM }] : []; + + let orderBy = query.orderBy || LIST_KEY_CREATED_AT; + + if (query.orderByType === 'metric') { + orderBy = `${METRIC_KEY_PREFIX}${orderBy}`; + } + return { - page: parseInt(getParameterValues('page')[0], 10) || 1, + filters: filter, + sorting: { + orderBy, + sort: (query.sort || 'desc').toLowerCase(), + }, }; }, computed: { fields() { + if (this.candidates.length === 0) return []; + return [ { key: 'name', label: this.$options.i18n.nameLabel }, { key: 'created_at', label: this.$options.i18n.createdAtLabel }, @@ -38,39 +66,87 @@ export default { displayPagination() { return this.candidates.length > 0; }, - prevPage() { - return this.pagination.page > 1 ? this.pagination.page - 1 : null; + sortableFields() { + return [ + ...BASE_SORT_FIELDS, + ...this.metricNames.map((name) => ({ + orderBy: `${METRIC_KEY_PREFIX}${name}`, + label: capitalizeFirstCharacter(name), + })), + ]; }, - nextPage() { - return !this.pagination.isLastPage ? this.pagination.page + 1 : null; + parsedQuery() { + const name = this.filters + .map((f) => f.value.data) + .join(' ') + .trim(); + + const filterByQuery = name === '' ? {} : { name }; + + let orderByType = 'column'; + let { orderBy } = this.sorting; + const { sort } = this.sorting; + + if (orderBy.startsWith(METRIC_KEY_PREFIX)) { + orderBy = this.sorting.orderBy.slice(METRIC_KEY_PREFIX.length); + orderByType = 'metric'; + } + + return { ...filterByQuery, orderBy, orderByType, sort }; }, }, methods: { - generateLink(page) { - return setUrlParams({ page }); + submitFilters() { + return visitUrl(setUrlParams({ ...this.parsedQuery })); + }, + updateFilters(newValue) { + this.filters = newValue; + }, + updateSorting(newValue) { + this.sorting = { ...this.sorting, ...newValue }; + }, + updateSortingAndEmitUpdate(newValue) { + this.updateSorting(newValue); + this.submitFilters(); }, }, i18n: { - titleLabel: __('Experiment candidates'), - emptyStateLabel: __('This experiment has no logged candidates'), - artifactsLabel: __('Artifacts'), - detailsLabel: __('Details'), - userLabel: __('User'), - createdAtLabel: __('Created at'), - nameLabel: __('Name'), - noDataContent: __('-'), + titleLabel: s__('MlExperimentTracking|Experiment candidates'), + emptyStateLabel: s__('MlExperimentTracking|No candidates to display'), + artifactsLabel: s__('MlExperimentTracking|Artifacts'), + detailsLabel: s__('MlExperimentTracking|Details'), + userLabel: s__('MlExperimentTracking|User'), + createdAtLabel: s__('MlExperimentTracking|Created at'), + nameLabel: s__('MlExperimentTracking|Name'), + noDataContent: s__('MlExperimentTracking|-'), + filterCandidatesLabel: s__('MlExperimentTracking|Filter candidates'), }, + FEATURE_NAME, + FEATURE_FEEDBACK_ISSUE, }; </script> <template> <div> - <incubation-alert /> + <incubation-alert + :feature-name="$options.FEATURE_NAME" + :link-to-feedback-issue="$options.FEATURE_FEEDBACK_ISSUE" + /> <h3> {{ $options.i18n.titleLabel }} </h3> + <registry-search + :filters="filters" + :sorting="sorting" + :sortable-fields="sortableFields" + @sorting:changed="updateSortingAndEmitUpdate" + @filter:changed="updateFilters" + @filter:submit="submitFilters" + @filter:clear="filters = []" + /> + <gl-table :fields="fields" :items="candidates" @@ -119,16 +195,6 @@ export default { </template> </gl-table> - <gl-pagination - v-if="displayPagination" - v-model="pagination.page" - :prev-page="prevPage" - :next-page="nextPage" - :total-items="pagination.totalItems" - :per-page="pagination.perPage" - :link-gen="generateLink" - align="center" - class="w-100" - /> + <keyset-pagination v-if="displayPagination" v-bind="pageInfo" /> </div> </template> |