Commit c03b3938 authored by Kushal Pandya's avatar Kushal Pandya

Merge branch '196843-disable-form-when-no-dictionary' into 'master'

Disable expiration policy if dict is absent from API

See merge request gitlab-org/gitlab!23511
parents c55ba092 77d30346
<script> <script>
import { mapActions } from 'vuex'; import { mapActions, mapState } from 'vuex';
import { GlAlert } from '@gitlab/ui';
import { sprintf, s__ } from '~/locale';
import { FETCH_SETTINGS_ERROR_MESSAGE } from '../constants'; import { FETCH_SETTINGS_ERROR_MESSAGE } from '../constants';
import SettingsForm from './settings_form.vue'; import SettingsForm from './settings_form.vue';
...@@ -7,6 +10,23 @@ import SettingsForm from './settings_form.vue'; ...@@ -7,6 +10,23 @@ import SettingsForm from './settings_form.vue';
export default { export default {
components: { components: {
SettingsForm, SettingsForm,
GlAlert,
},
computed: {
...mapState(['isDisabled']),
notAvailableMessage() {
return sprintf(
s__(
'ContainerRegistry|Currently, the Container Registry tag expiration feature is not available for projects created before GitLab version 12.8. For updates and more information, visit Issue %{linkStart}#196124%{linkEnd}',
),
{
linkStart:
'<a href="https://gitlab.com/gitlab-org/gitlab/issues/196124" target="_blank" rel="noopener noreferrer">',
linkEnd: '</a>',
},
false,
);
},
}, },
mounted() { mounted() {
this.fetchSettings().catch(() => this.fetchSettings().catch(() =>
...@@ -34,6 +54,9 @@ export default { ...@@ -34,6 +54,9 @@ export default {
}} }}
</li> </li>
</ul> </ul>
<settings-form ref="settings-form" /> <settings-form v-if="!isDisabled" />
<gl-alert v-else :dismissible="false">
<p v-html="notAvailableMessage"></p>
</gl-alert>
</div> </div>
</template> </template>
...@@ -4,7 +4,13 @@ import * as types from './mutation_types'; ...@@ -4,7 +4,13 @@ import * as types from './mutation_types';
export const setInitialState = ({ commit }, data) => commit(types.SET_INITIAL_STATE, data); export const setInitialState = ({ commit }, data) => commit(types.SET_INITIAL_STATE, data);
export const updateSettings = ({ commit }, data) => commit(types.UPDATE_SETTINGS, data); export const updateSettings = ({ commit }, data) => commit(types.UPDATE_SETTINGS, data);
export const toggleLoading = ({ commit }) => commit(types.TOGGLE_LOADING); export const toggleLoading = ({ commit }) => commit(types.TOGGLE_LOADING);
export const receiveSettingsSuccess = ({ commit }, data = {}) => commit(types.SET_SETTINGS, data); export const receiveSettingsSuccess = ({ commit }, data) => {
if (data) {
commit(types.SET_SETTINGS, data);
} else {
commit(types.SET_IS_DISABLED, true);
}
};
export const resetSettings = ({ commit }) => commit(types.RESET_SETTINGS); export const resetSettings = ({ commit }) => commit(types.RESET_SETTINGS);
export const fetchSettings = ({ dispatch, state }) => { export const fetchSettings = ({ dispatch, state }) => {
......
...@@ -3,3 +3,4 @@ export const UPDATE_SETTINGS = 'UPDATE_SETTINGS'; ...@@ -3,3 +3,4 @@ export const UPDATE_SETTINGS = 'UPDATE_SETTINGS';
export const TOGGLE_LOADING = 'TOGGLE_LOADING'; export const TOGGLE_LOADING = 'TOGGLE_LOADING';
export const SET_SETTINGS = 'SET_SETTINGS'; export const SET_SETTINGS = 'SET_SETTINGS';
export const RESET_SETTINGS = 'RESET_SETTINGS'; export const RESET_SETTINGS = 'RESET_SETTINGS';
export const SET_IS_DISABLED = 'SET_IS_DISABLED';
...@@ -16,6 +16,9 @@ export default { ...@@ -16,6 +16,9 @@ export default {
state.settings = settings; state.settings = settings;
state.original = Object.freeze(settings); state.original = Object.freeze(settings);
}, },
[types.SET_IS_DISABLED](state, isDisabled) {
state.isDisabled = isDisabled;
},
[types.RESET_SETTINGS](state) { [types.RESET_SETTINGS](state) {
state.settings = { ...state.original }; state.settings = { ...state.original };
}, },
......
...@@ -7,6 +7,10 @@ export default () => ({ ...@@ -7,6 +7,10 @@ export default () => ({
* Boolean to determine if the UI is loading data from the API * Boolean to determine if the UI is loading data from the API
*/ */
isLoading: false, isLoading: false,
/*
* Boolean to determine if the user is allowed to interact with the form
*/
isDisabled: false,
/* /*
* This contains the data shown and manipulated in the UI * This contains the data shown and manipulated in the UI
* Has the following structure: * Has the following structure:
......
...@@ -5056,6 +5056,9 @@ msgstr "" ...@@ -5056,6 +5056,9 @@ msgstr ""
msgid "ContainerRegistry|Copy push command" msgid "ContainerRegistry|Copy push command"
msgstr "" msgstr ""
msgid "ContainerRegistry|Currently, the Container Registry tag expiration feature is not available for projects created before GitLab version 12.8. For updates and more information, visit Issue %{linkStart}#196124%{linkEnd}"
msgstr ""
msgid "ContainerRegistry|Docker connection error" msgid "ContainerRegistry|Docker connection error"
msgstr "" msgstr ""
......
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import { GlAlert } from '@gitlab/ui';
import component from '~/registry/settings/components/registry_settings_app.vue'; import component from '~/registry/settings/components/registry_settings_app.vue';
import SettingsForm from '~/registry/settings/components/settings_form.vue';
import { createStore } from '~/registry/settings/store/'; import { createStore } from '~/registry/settings/store/';
import { SET_IS_DISABLED } from '~/registry/settings/store/mutation_types';
import { FETCH_SETTINGS_ERROR_MESSAGE } from '~/registry/settings/constants'; import { FETCH_SETTINGS_ERROR_MESSAGE } from '~/registry/settings/constants';
describe('Registry Settings App', () => { describe('Registry Settings App', () => {
let wrapper; let wrapper;
let store; let store;
const findSettingsComponent = () => wrapper.find({ ref: 'settings-form' }); const findSettingsComponent = () => wrapper.find(SettingsForm);
const findAlert = () => wrapper.find(GlAlert);
const mountComponent = ({ dispatchMock } = {}) => { const mountComponent = ({ dispatchMock = 'mockResolvedValue', isDisabled = false } = {}) => {
store = createStore(); store = createStore();
store.commit(SET_IS_DISABLED, isDisabled);
const dispatchSpy = jest.spyOn(store, 'dispatch'); const dispatchSpy = jest.spyOn(store, 'dispatch');
if (dispatchMock) { if (dispatchMock) {
dispatchSpy[dispatchMock](); dispatchSpy[dispatchMock]();
...@@ -30,12 +35,12 @@ describe('Registry Settings App', () => { ...@@ -30,12 +35,12 @@ describe('Registry Settings App', () => {
}); });
it('renders', () => { it('renders', () => {
mountComponent({ dispatchMock: 'mockResolvedValue' }); mountComponent();
expect(wrapper.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
it('call the store function to load the data on mount', () => { it('call the store function to load the data on mount', () => {
mountComponent({ dispatchMock: 'mockResolvedValue' }); mountComponent();
expect(store.dispatch).toHaveBeenCalledWith('fetchSettings'); expect(store.dispatch).toHaveBeenCalledWith('fetchSettings');
}); });
...@@ -49,7 +54,21 @@ describe('Registry Settings App', () => { ...@@ -49,7 +54,21 @@ describe('Registry Settings App', () => {
}); });
it('renders the setting form', () => { it('renders the setting form', () => {
mountComponent({ dispatchMock: 'mockResolvedValue' }); mountComponent();
expect(findSettingsComponent().exists()).toBe(true); expect(findSettingsComponent().exists()).toBe(true);
}); });
describe('isDisabled', () => {
beforeEach(() => {
mountComponent({ isDisabled: true });
});
it('the form is hidden', () => {
expect(findSettingsComponent().exists()).toBe(false);
});
it('shows an alert', () => {
expect(findAlert().exists()).toBe(true);
});
});
}); });
...@@ -8,7 +8,6 @@ describe('Actions Registry Store', () => { ...@@ -8,7 +8,6 @@ describe('Actions Registry Store', () => {
actionName | mutationName | payload actionName | mutationName | payload
${'setInitialState'} | ${types.SET_INITIAL_STATE} | ${'foo'} ${'setInitialState'} | ${types.SET_INITIAL_STATE} | ${'foo'}
${'updateSettings'} | ${types.UPDATE_SETTINGS} | ${'foo'} ${'updateSettings'} | ${types.UPDATE_SETTINGS} | ${'foo'}
${'receiveSettingsSuccess'} | ${types.SET_SETTINGS} | ${'foo'}
${'toggleLoading'} | ${types.TOGGLE_LOADING} | ${undefined} ${'toggleLoading'} | ${types.TOGGLE_LOADING} | ${undefined}
${'resetSettings'} | ${types.RESET_SETTINGS} | ${undefined} ${'resetSettings'} | ${types.RESET_SETTINGS} | ${undefined}
`('%s action invokes %s mutation with payload %s', ({ actionName, mutationName, payload }) => { `('%s action invokes %s mutation with payload %s', ({ actionName, mutationName, payload }) => {
...@@ -17,6 +16,27 @@ describe('Actions Registry Store', () => { ...@@ -17,6 +16,27 @@ describe('Actions Registry Store', () => {
}); });
}); });
describe('receiveSettingsSuccess', () => {
it('calls SET_SETTINGS when data is present', () => {
testAction(
actions.receiveSettingsSuccess,
'foo',
{},
[{ type: types.SET_SETTINGS, payload: 'foo' }],
[],
);
});
it('calls SET_IS_DISABLED when data is not present', () => {
testAction(
actions.receiveSettingsSuccess,
null,
{},
[{ type: types.SET_IS_DISABLED, payload: true }],
[],
);
});
});
describe('fetchSettings', () => { describe('fetchSettings', () => {
const state = { const state = {
projectId: 'bar', projectId: 'bar',
......
...@@ -32,6 +32,7 @@ describe('Mutations Registry Store', () => { ...@@ -32,6 +32,7 @@ describe('Mutations Registry Store', () => {
expect(mockState.settings).toEqual(expectedState.settings); expect(mockState.settings).toEqual(expectedState.settings);
}); });
}); });
describe('SET_SETTINGS', () => { describe('SET_SETTINGS', () => {
it('should set the settings and original', () => { it('should set the settings and original', () => {
const payload = { foo: 'baz' }; const payload = { foo: 'baz' };
...@@ -41,6 +42,7 @@ describe('Mutations Registry Store', () => { ...@@ -41,6 +42,7 @@ describe('Mutations Registry Store', () => {
expect(mockState.original).toEqual(expectedState.settings); expect(mockState.original).toEqual(expectedState.settings);
}); });
}); });
describe('RESET_SETTINGS', () => { describe('RESET_SETTINGS', () => {
it('should copy original over settings', () => { it('should copy original over settings', () => {
mockState.settings = { foo: 'bar' }; mockState.settings = { foo: 'bar' };
...@@ -49,10 +51,18 @@ describe('Mutations Registry Store', () => { ...@@ -49,10 +51,18 @@ describe('Mutations Registry Store', () => {
expect(mockState.settings).toEqual(mockState.original); expect(mockState.settings).toEqual(mockState.original);
}); });
}); });
describe('TOGGLE_LOADING', () => { describe('TOGGLE_LOADING', () => {
it('should toggle the loading', () => { it('should toggle the loading', () => {
mutations[types.TOGGLE_LOADING](mockState); mutations[types.TOGGLE_LOADING](mockState);
expect(mockState.isLoading).toEqual(true); expect(mockState.isLoading).toEqual(true);
}); });
}); });
describe('SET_IS_DISABLED', () => {
it('should set isDisabled', () => {
mutations[types.SET_IS_DISABLED](mockState, true);
expect(mockState.isDisabled).toEqual(true);
});
});
}); });
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