Commit 2048b5e1 authored by Miguel Rincon's avatar Miguel Rincon

Use "never contacted" wording in runner's frontend

This change replaces "not connected" with "never contacted" in the UI of
the runners administration.

Old URLs which use not connected are redirected for backwards
compatibility.

Changelog: changed
parent 051cccd6
...@@ -2,6 +2,8 @@ import { GlToast } from '@gitlab/ui'; ...@@ -2,6 +2,8 @@ import { GlToast } from '@gitlab/ui';
import Vue from 'vue'; import Vue from 'vue';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql'; import createDefaultClient from '~/lib/graphql';
import { visitUrl } from '~/lib/utils/url_utility';
import { updateOutdatedUrl } from '~/runner/runner_search_utils';
import AdminRunnersApp from './admin_runners_app.vue'; import AdminRunnersApp from './admin_runners_app.vue';
Vue.use(GlToast); Vue.use(GlToast);
...@@ -14,6 +16,15 @@ export const initAdminRunners = (selector = '#js-admin-runners') => { ...@@ -14,6 +16,15 @@ export const initAdminRunners = (selector = '#js-admin-runners') => {
return null; return null;
} }
// Redirect outdated URLs
const updatedUrlQuery = updateOutdatedUrl();
if (updatedUrlQuery) {
visitUrl(updatedUrlQuery);
// Prevent mounting the rest of the app, redirecting now.
return null;
}
// TODO `activeRunnersCount` should be implemented using a GraphQL API // TODO `activeRunnersCount` should be implemented using a GraphQL API
// https://gitlab.com/gitlab-org/gitlab/-/issues/333806 // https://gitlab.com/gitlab-org/gitlab/-/issues/333806
const { const {
......
...@@ -28,7 +28,15 @@ export default { ...@@ -28,7 +28,15 @@ export default {
<template> <template>
<div> <div>
<runner-status-badge :runner="runner" size="sm" /> <runner-status-badge
<runner-paused-badge v-if="paused" size="sm" /> :runner="runner"
size="sm"
class="gl-display-inline-block gl-max-w-full gl-text-truncate"
/>
<runner-paused-badge
v-if="paused"
size="sm"
class="gl-display-inline-block gl-max-w-full gl-text-truncate"
/>
</div> </div>
</template> </template>
...@@ -4,11 +4,10 @@ import { __, s__, sprintf } from '~/locale'; ...@@ -4,11 +4,10 @@ import { __, s__, sprintf } from '~/locale';
import { getTimeago } from '~/lib/utils/datetime_utility'; import { getTimeago } from '~/lib/utils/datetime_utility';
import { import {
I18N_ONLINE_RUNNER_TIMEAGO_DESCRIPTION, I18N_ONLINE_RUNNER_TIMEAGO_DESCRIPTION,
I18N_NOT_CONNECTED_RUNNER_DESCRIPTION, I18N_NEVER_CONTACTED_RUNNER_DESCRIPTION,
I18N_OFFLINE_RUNNER_TIMEAGO_DESCRIPTION, I18N_OFFLINE_RUNNER_TIMEAGO_DESCRIPTION,
I18N_STALE_RUNNER_DESCRIPTION, I18N_STALE_RUNNER_DESCRIPTION,
STATUS_ONLINE, STATUS_ONLINE,
STATUS_NOT_CONNECTED,
STATUS_NEVER_CONTACTED, STATUS_NEVER_CONTACTED,
STATUS_OFFLINE, STATUS_OFFLINE,
STATUS_STALE, STATUS_STALE,
...@@ -45,12 +44,11 @@ export default { ...@@ -45,12 +44,11 @@ export default {
timeAgo: this.contactedAtTimeAgo, timeAgo: this.contactedAtTimeAgo,
}), }),
}; };
case STATUS_NOT_CONNECTED:
case STATUS_NEVER_CONTACTED: case STATUS_NEVER_CONTACTED:
return { return {
variant: 'muted', variant: 'muted',
label: s__('Runners|not connected'), label: s__('Runners|never contacted'),
tooltip: I18N_NOT_CONNECTED_RUNNER_DESCRIPTION, tooltip: I18N_NEVER_CONTACTED_RUNNER_DESCRIPTION,
}; };
case STATUS_OFFLINE: case STATUS_OFFLINE:
return { return {
......
...@@ -6,7 +6,7 @@ import { ...@@ -6,7 +6,7 @@ import {
STATUS_PAUSED, STATUS_PAUSED,
STATUS_ONLINE, STATUS_ONLINE,
STATUS_OFFLINE, STATUS_OFFLINE,
STATUS_NOT_CONNECTED, STATUS_NEVER_CONTACTED,
STATUS_STALE, STATUS_STALE,
PARAM_KEY_STATUS, PARAM_KEY_STATUS,
} from '../../constants'; } from '../../constants';
...@@ -16,7 +16,7 @@ const options = [ ...@@ -16,7 +16,7 @@ const options = [
{ value: STATUS_PAUSED, title: s__('Runners|Paused') }, { value: STATUS_PAUSED, title: s__('Runners|Paused') },
{ value: STATUS_ONLINE, title: s__('Runners|Online') }, { value: STATUS_ONLINE, title: s__('Runners|Online') },
{ value: STATUS_OFFLINE, title: s__('Runners|Offline') }, { value: STATUS_OFFLINE, title: s__('Runners|Offline') },
{ value: STATUS_NOT_CONNECTED, title: s__('Runners|Not connected') }, { value: STATUS_NEVER_CONTACTED, title: s__('Runners|Never contacted') },
{ value: STATUS_STALE, title: s__('Runners|Stale') }, { value: STATUS_STALE, title: s__('Runners|Stale') },
]; ];
......
...@@ -18,8 +18,8 @@ export const I18N_PROJECT_RUNNER_DESCRIPTION = s__('Runners|Associated with one ...@@ -18,8 +18,8 @@ export const I18N_PROJECT_RUNNER_DESCRIPTION = s__('Runners|Associated with one
export const I18N_ONLINE_RUNNER_TIMEAGO_DESCRIPTION = s__( export const I18N_ONLINE_RUNNER_TIMEAGO_DESCRIPTION = s__(
'Runners|Runner is online; last contact was %{timeAgo}', 'Runners|Runner is online; last contact was %{timeAgo}',
); );
export const I18N_NOT_CONNECTED_RUNNER_DESCRIPTION = s__( export const I18N_NEVER_CONTACTED_RUNNER_DESCRIPTION = s__(
'Runners|This runner has never connected to this instance', 'Runners|This runner has never contacted this instance',
); );
export const I18N_OFFLINE_RUNNER_TIMEAGO_DESCRIPTION = s__( export const I18N_OFFLINE_RUNNER_TIMEAGO_DESCRIPTION = s__(
'Runners|No recent contact from this runner; last contact was %{timeAgo}', 'Runners|No recent contact from this runner; last contact was %{timeAgo}',
...@@ -60,7 +60,6 @@ export const STATUS_ACTIVE = 'ACTIVE'; ...@@ -60,7 +60,6 @@ export const STATUS_ACTIVE = 'ACTIVE';
export const STATUS_PAUSED = 'PAUSED'; export const STATUS_PAUSED = 'PAUSED';
export const STATUS_ONLINE = 'ONLINE'; export const STATUS_ONLINE = 'ONLINE';
export const STATUS_NOT_CONNECTED = 'NOT_CONNECTED';
export const STATUS_NEVER_CONTACTED = 'NEVER_CONTACTED'; export const STATUS_NEVER_CONTACTED = 'NEVER_CONTACTED';
export const STATUS_OFFLINE = 'OFFLINE'; export const STATUS_OFFLINE = 'OFFLINE';
export const STATUS_STALE = 'STALE'; export const STATUS_STALE = 'STALE';
......
...@@ -16,6 +16,7 @@ import { ...@@ -16,6 +16,7 @@ import {
PARAM_KEY_BEFORE, PARAM_KEY_BEFORE,
DEFAULT_SORT, DEFAULT_SORT,
RUNNER_PAGE_SIZE, RUNNER_PAGE_SIZE,
STATUS_NEVER_CONTACTED,
} from './constants'; } from './constants';
/** /**
...@@ -79,6 +80,33 @@ const getPaginationFromParams = (params) => { ...@@ -79,6 +80,33 @@ const getPaginationFromParams = (params) => {
}; };
}; };
// Outdated URL parameters
const STATUS_NOT_CONNECTED = 'NOT_CONNECTED';
/**
* Returns an updated URL for old (or deprecated) admin runner URLs.
*
* Use for redirecting users to currently used URLs.
*
* @param {String?} URL
* @returns Updated URL if outdated, `null` otherwise
*/
export const updateOutdatedUrl = (url = window.location.href) => {
const urlObj = new URL(url);
const query = urlObj.search;
const params = queryToObject(query, { gatherArrays: true });
const runnerType = params[PARAM_KEY_STATUS]?.[0] || null;
if (runnerType === STATUS_NOT_CONNECTED) {
const updatedParams = {
[PARAM_KEY_STATUS]: [STATUS_NEVER_CONTACTED],
};
return setUrlParams(updatedParams, url, false, true, true);
}
return null;
};
/** /**
* Takes a URL query and transforms it into a "search" object * Takes a URL query and transforms it into a "search" object
* @param {String?} query * @param {String?} query
......
...@@ -24,7 +24,7 @@ module Ci ...@@ -24,7 +24,7 @@ module Ci
span_class = 'gl-text-gray-600' span_class = 'gl-text-gray-600'
end end
when :not_connected, :never_contacted when :not_connected, :never_contacted
title = s_("Runners|New runner, has not connected yet") title = s_("Runners|New runner, has not contacted yet")
icon = 'warning-solid' icon = 'warning-solid'
when :offline when :offline
title = s_("Runners|Runner is offline, last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(runner.contacted_at) } title = s_("Runners|Runner is offline, last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(runner.contacted_at) }
......
...@@ -30474,10 +30474,13 @@ msgstr "" ...@@ -30474,10 +30474,13 @@ msgstr ""
msgid "Runners|Name" msgid "Runners|Name"
msgstr "" msgstr ""
msgid "Runners|Never contacted"
msgstr ""
msgid "Runners|New registration token generated!" msgid "Runners|New registration token generated!"
msgstr "" msgstr ""
msgid "Runners|New runner, has not connected yet" msgid "Runners|New runner, has not contacted yet"
msgstr "" msgstr ""
msgid "Runners|No contact from this runner in over 3 months" msgid "Runners|No contact from this runner in over 3 months"
...@@ -30489,9 +30492,6 @@ msgstr "" ...@@ -30489,9 +30492,6 @@ msgstr ""
msgid "Runners|Not available to run jobs" msgid "Runners|Not available to run jobs"
msgstr "" msgstr ""
msgid "Runners|Not connected"
msgstr ""
msgid "Runners|Offline" msgid "Runners|Offline"
msgstr "" msgstr ""
...@@ -30606,7 +30606,7 @@ msgstr "" ...@@ -30606,7 +30606,7 @@ msgstr ""
msgid "Runners|The runner will be permanently deleted and no longer available for projects or groups in the instance. Are you sure you want to continue?" msgid "Runners|The runner will be permanently deleted and no longer available for projects or groups in the instance. Are you sure you want to continue?"
msgstr "" msgstr ""
msgid "Runners|This runner has never connected to this instance" msgid "Runners|This runner has never contacted this instance"
msgstr "" msgstr ""
msgid "Runners|This runner is associated with one or more projects." msgid "Runners|This runner is associated with one or more projects."
...@@ -30675,7 +30675,7 @@ msgstr "" ...@@ -30675,7 +30675,7 @@ msgstr ""
msgid "Runners|locked" msgid "Runners|locked"
msgstr "" msgstr ""
msgid "Runners|not connected" msgid "Runners|never contacted"
msgstr "" msgstr ""
msgid "Runners|offline" msgid "Runners|offline"
......
...@@ -192,17 +192,21 @@ RSpec.describe "Admin Runners" do ...@@ -192,17 +192,21 @@ RSpec.describe "Admin Runners" do
expect(page).not_to have_content 'runner-a-2' expect(page).not_to have_content 'runner-a-2'
end end
it 'shows correct runner when type is selected and search term is entered' do it 'shows correct runner when status filter is entered' do
create(:ci_runner, :instance, description: 'runner-connected', contacted_at: Time.now) never_connected = create(:ci_runner, :instance, description: 'runner-never-contacted', contacted_at: nil)
create(:ci_runner, :instance, description: 'runner-not-connected', contacted_at: nil) create(:ci_runner, :instance, description: 'runner-contacted', contacted_at: Time.now)
visit admin_runners_path visit admin_runners_path
# use the string "Not" to avoid using space and trigger an early selection # use the string "Never" to avoid using space and trigger an early selection
input_filtered_search_filter_is_only('Status', 'Not') input_filtered_search_filter_is_only('Status', 'Never')
expect(page).to have_content 'runner-never-contacted'
expect(page).not_to have_content 'runner-contacted'
expect(page).not_to have_content 'runner-connected' within "[data-testid='runner-row-#{never_connected.id}']" do
expect(page).to have_content 'runner-not-connected' expect(page).to have_selector '.badge', text: 'never contacted'
end
end end
end end
...@@ -378,6 +382,14 @@ RSpec.describe "Admin Runners" do ...@@ -378,6 +382,14 @@ RSpec.describe "Admin Runners" do
end end
end end
context "when visiting outdated URLs" do
it 'updates NOT_CONNECTED runner status to NEVER_CONNECTED' do
visit admin_runners_path('status[]': 'NOT_CONNECTED')
expect(page).to have_current_path(admin_runners_path('status[]': 'NEVER_CONTACTED') )
end
end
describe 'runners registration' do describe 'runners registration' do
let!(:token) { Gitlab::CurrentSettings.runners_registration_token } let!(:token) { Gitlab::CurrentSettings.runners_registration_token }
......
...@@ -69,7 +69,9 @@ describe('RunnerList', () => { ...@@ -69,7 +69,9 @@ describe('RunnerList', () => {
const { id, description, version, ipAddress, shortSha } = mockRunners[0]; const { id, description, version, ipAddress, shortSha } = mockRunners[0];
// Badges // Badges
expect(findCell({ fieldKey: 'status' }).text()).toMatchInterpolatedText('not connected paused'); expect(findCell({ fieldKey: 'status' }).text()).toMatchInterpolatedText(
'never contacted paused',
);
// Runner summary // Runner summary
expect(findCell({ fieldKey: 'summary' }).text()).toContain( expect(findCell({ fieldKey: 'summary' }).text()).toContain(
......
...@@ -6,7 +6,6 @@ import { ...@@ -6,7 +6,6 @@ import {
STATUS_ONLINE, STATUS_ONLINE,
STATUS_OFFLINE, STATUS_OFFLINE,
STATUS_STALE, STATUS_STALE,
STATUS_NOT_CONNECTED,
STATUS_NEVER_CONTACTED, STATUS_NEVER_CONTACTED,
} from '~/runner/constants'; } from '~/runner/constants';
...@@ -50,20 +49,7 @@ describe('RunnerTypeBadge', () => { ...@@ -50,20 +49,7 @@ describe('RunnerTypeBadge', () => {
expect(getTooltip().value).toBe('Runner is online; last contact was 1 minute ago'); expect(getTooltip().value).toBe('Runner is online; last contact was 1 minute ago');
}); });
it('renders not connected state', () => { it('renders never contacted state', () => {
createComponent({
runner: {
contactedAt: null,
status: STATUS_NOT_CONNECTED,
},
});
expect(wrapper.text()).toBe('not connected');
expect(findBadge().props('variant')).toBe('muted');
expect(getTooltip().value).toMatch('This runner has never connected');
});
it('renders never contacted state as not connected, for backwards compatibility', () => {
createComponent({ createComponent({
runner: { runner: {
contactedAt: null, contactedAt: null,
...@@ -71,9 +57,9 @@ describe('RunnerTypeBadge', () => { ...@@ -71,9 +57,9 @@ describe('RunnerTypeBadge', () => {
}, },
}); });
expect(wrapper.text()).toBe('not connected'); expect(wrapper.text()).toBe('never contacted');
expect(findBadge().props('variant')).toBe('muted'); expect(findBadge().props('variant')).toBe('muted');
expect(getTooltip().value).toMatch('This runner has never connected'); expect(getTooltip().value).toMatch('This runner has never contacted');
}); });
it('renders offline state', () => { it('renders offline state', () => {
......
import { RUNNER_PAGE_SIZE } from '~/runner/constants'; import { RUNNER_PAGE_SIZE } from '~/runner/constants';
import { import {
searchValidator, searchValidator,
updateOutdatedUrl,
fromUrlQueryToSearch, fromUrlQueryToSearch,
fromSearchToUrl, fromSearchToUrl,
fromSearchToVariables, fromSearchToVariables,
...@@ -190,6 +191,23 @@ describe('search_params.js', () => { ...@@ -190,6 +191,23 @@ describe('search_params.js', () => {
}); });
}); });
describe('updateOutdatedUrl', () => {
it('returns null for urls that do not need updating', () => {
expect(updateOutdatedUrl('http://test.host/')).toBe(null);
expect(updateOutdatedUrl('http://test.host/?a=b')).toBe(null);
});
it('returns updated url for updating NOT_CONNECTED to NEVER_CONTACTED', () => {
expect(updateOutdatedUrl('http://test.host/admin/runners?status[]=NOT_CONNECTED')).toBe(
'http://test.host/admin/runners?status[]=NEVER_CONTACTED',
);
expect(updateOutdatedUrl('http://test.host/admin/runners?status[]=NOT_CONNECTED&a=b')).toBe(
'http://test.host/admin/runners?status[]=NEVER_CONTACTED&a=b',
);
});
});
describe('fromUrlQueryToSearch', () => { describe('fromUrlQueryToSearch', () => {
examples.forEach(({ name, urlQuery, search }) => { examples.forEach(({ name, urlQuery, search }) => {
it(`Converts ${name} to a search object`, () => { it(`Converts ${name} to a search object`, () => {
......
...@@ -12,7 +12,7 @@ RSpec.describe Ci::RunnersHelper do ...@@ -12,7 +12,7 @@ RSpec.describe Ci::RunnersHelper do
describe '#runner_status_icon', :clean_gitlab_redis_cache do describe '#runner_status_icon', :clean_gitlab_redis_cache do
it "returns - not contacted yet" do it "returns - not contacted yet" do
runner = create(:ci_runner) runner = create(:ci_runner)
expect(helper.runner_status_icon(runner)).to include("not connected yet") expect(helper.runner_status_icon(runner)).to include("not contacted yet")
end end
it "returns offline text" do it "returns offline text" do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment