use component mixin to refactor components

This commit is contained in:
Dennis Tang 2018-05-09 15:53:44 +02:00
parent 5a2f09136c
commit 01ef0b64ea
7 changed files with 119 additions and 195 deletions

View File

@ -0,0 +1,62 @@
import _ from 'underscore';
import LoadingIcon from '~/vue_shared/components/loading_icon.vue';
import DropdownSearchInput from '~/vue_shared/components/dropdown/dropdown_search_input.vue';
import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
import store from '../stores';
export default {
store,
components: {
LoadingIcon,
DropdownButton,
DropdownSearchInput,
DropdownHiddenInput,
},
props: {
fieldId: {
type: String,
required: true,
},
fieldName: {
type: String,
required: true,
},
defaultValue: {
type: String,
required: false,
default: '',
},
},
data() {
return {
isLoading: false,
hasErrors: false,
searchQuery: '',
};
},
computed: {
results() {
return this.items.filter(item => item.name.toLowerCase().indexOf(this.searchQuery) > -1);
},
},
methods: {
fetchSuccessHandler() {
if (this.defaultValue) {
const itemToSelect = _.find(this.items, item => item.name === this.defaultValue);
if (itemToSelect) {
this.setItem(itemToSelect.name);
}
}
this.isLoading = false;
this.hasErrors = false;
},
fetchFailureHandler() {
this.isLoading = false;
this.hasErrors = true;
},
},
};

View File

@ -2,46 +2,15 @@
import _ from 'underscore';
import { s__ } from '~/locale';
import { mapState, mapGetters, mapActions } from 'vuex';
import LoadingIcon from '~/vue_shared/components/loading_icon.vue';
import DropdownSearchInput from '~/vue_shared/components/dropdown/dropdown_search_input.vue';
import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
import store from '../stores';
import gcpDropdownMixin from './gcp_dropdown_mixin';
export default {
name: 'GkeMachineTypeDropdown',
store,
components: {
LoadingIcon,
DropdownButton,
DropdownSearchInput,
DropdownHiddenInput,
},
props: {
fieldId: {
type: String,
required: true,
},
fieldName: {
type: String,
required: true,
},
defaultValue: {
type: String,
required: false,
default: '',
},
},
data() {
return {
isLoading: false,
hasErrors: false,
searchQuery: '',
};
},
mixins: [gcpDropdownMixin],
computed: {
...mapState(['selectedProject', 'selectedZone', 'selectedMachineType', 'machineTypes']),
...mapState(['selectedProject', 'selectedZone', 'selectedMachineType']),
...mapState({ items: 'machineTypes' }),
...mapGetters(['hasProject', 'hasZone', 'hasMachineType']),
allDropdownsSelected() {
return this.hasProject && this.hasZone && this.hasMachineType;
@ -49,11 +18,6 @@ export default {
isDisabled() {
return !this.selectedProject || !this.selectedZone;
},
results() {
return this.machineTypes.filter(
item => item.name.toLowerCase().indexOf(this.searchQuery) > -1,
);
},
toggleText() {
if (this.isLoading) {
return s__('ClusterIntegration|Fetching machine types');
@ -80,38 +44,19 @@ export default {
},
watch: {
selectedZone() {
this.fetchMachineTypes();
this.isLoading = true;
this.getMachineTypes()
.then(this.fetchSuccessHandler)
.catch(this.fetchFailureHandler);
},
selectedMachineType() {
this.enableSubmit();
},
},
methods: {
...mapActions(['setMachineType', 'getMachineTypes']),
fetchMachineTypes() {
this.isLoading = true;
this.getMachineTypes()
.then(() => {
if (this.defaultValue) {
const machineTypeToSelect = _.find(
this.machineTypes,
item => item.name === this.defaultValue,
);
if (machineTypeToSelect) {
this.setMachineType(machineTypeToSelect.name);
}
}
this.isLoading = false;
this.hasErrors = false;
})
.catch(() => {
this.isLoading = false;
this.hasErrors = true;
});
},
...mapActions(['getMachineTypes']),
...mapActions({ setItem: 'setMachineType' }),
enableSubmit() {
if (this.allDropdownsSelected) {
const submitButtonEl = document.querySelector('.js-gke-cluster-creation-submit');
@ -154,7 +99,7 @@ export default {
v-for="result in results"
:key="result.id"
>
<button @click.prevent="setMachineType(result.name)">
<button @click.prevent="setItem(result.name)">
{{ result.name }}
</button>
</li>

View File

@ -2,59 +2,32 @@
import _ from 'underscore';
import { s__, sprintf } from '~/locale';
import { mapState, mapGetters, mapActions } from 'vuex';
import LoadingIcon from '~/vue_shared/components/loading_icon.vue';
import DropdownSearchInput from '~/vue_shared/components/dropdown/dropdown_search_input.vue';
import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
import store from '../stores';
import gcpDropdownMixin from './gcp_dropdown_mixin';
export default {
name: 'GkeProjectIdDropdown',
store,
components: {
LoadingIcon,
DropdownButton,
DropdownSearchInput,
DropdownHiddenInput,
},
mixins: [gcpDropdownMixin],
props: {
docsUrl: {
type: String,
required: true,
},
fieldId: {
type: String,
required: true,
},
fieldName: {
type: String,
required: true,
},
defaultValue: {
type: String,
required: false,
default: '',
},
},
data() {
return {
isLoading: true,
hasErrors: false,
searchQuery: '',
};
},
computed: {
...mapState(['selectedProject', 'projects']),
...mapState(['selectedProject']),
...mapState({ items: 'projects' }),
...mapGetters(['hasProject']),
hasOneProject() {
return this.projects.length === 1;
return this.items.length === 1;
},
isDisabled() {
return this.projects.length < 2;
},
results() {
return this.projects.filter(item => item.name.toLowerCase().indexOf(this.searchQuery) > -1);
return this.items.length < 2;
},
noSearchResultsText() {
return s__('ClusterIntegration|No projects matched your search');
@ -68,7 +41,7 @@ export default {
return this.selectedProject.name;
}
return !this.projects.length
return !this.items.length
? s__('ClusterIntegration|No projects found')
: s__('ClusterIntegration|Select project');
},
@ -82,7 +55,7 @@ export default {
'ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}.';
}
message = this.projects.length
message = this.items.length
? 'ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}.'
: 'ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}.';
@ -99,34 +72,29 @@ export default {
},
},
created() {
this.fetchProjects();
this.getProjects()
.then(() => {
if (this.defaultValue) {
const projectToSelect = _.find(this.items, item => item.projectId === this.defaultValue);
if (projectToSelect) {
this.setItem(projectToSelect);
}
} else if (this.items.length === 1) {
this.setItem(this.items[0]);
}
this.isLoading = false;
this.hasErrors = false;
})
.catch(() => {
this.isLoading = false;
this.hasErrors = true;
});
},
methods: {
...mapActions(['setProject', 'getProjects']),
fetchProjects() {
this.getProjects()
.then(() => {
if (this.defaultValue) {
const projectToSelect = _.find(
this.projects,
item => item.projectId === this.defaultValue,
);
if (projectToSelect) {
this.setProject(projectToSelect);
}
} else if (this.projects.length === 1) {
this.setProject(this.projects[0]);
}
this.isLoading = false;
this.hasErrors = false;
})
.catch(() => {
this.isLoading = false;
this.hasErrors = true;
});
},
...mapActions(['getProjects']),
...mapActions({ setItem: 'setProject' }),
},
};
</script>
@ -164,7 +132,7 @@ export default {
v-for="result in results"
:key="result.project_number"
>
<button @click.prevent="setProject(result)">
<button @click.prevent="setItem(result)">
{{ result.name }}
</button>
</li>

View File

@ -1,54 +1,19 @@
<script>
import _ from 'underscore';
import { s__ } from '~/locale';
import { mapState, mapGetters, mapActions } from 'vuex';
import LoadingIcon from '~/vue_shared/components/loading_icon.vue';
import DropdownSearchInput from '~/vue_shared/components/dropdown/dropdown_search_input.vue';
import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
import store from '../stores';
import gcpDropdownMixin from './gcp_dropdown_mixin';
export default {
name: 'GkeZoneDropdown',
store,
components: {
LoadingIcon,
DropdownButton,
DropdownSearchInput,
DropdownHiddenInput,
},
props: {
fieldId: {
type: String,
required: true,
},
fieldName: {
type: String,
required: true,
},
defaultValue: {
type: String,
required: false,
default: '',
},
},
data() {
return {
isLoading: false,
hasErrors: false,
searchQuery: '',
};
},
mixins: [gcpDropdownMixin],
computed: {
...mapState(['selectedProject', 'selectedZone', 'zones']),
...mapState(['selectedProject', 'selectedZone']),
...mapState({ items: 'zones' }),
...mapGetters(['hasProject']),
isDisabled() {
return !this.hasProject;
},
results() {
return this.zones.filter(item => item.name.toLowerCase().indexOf(this.searchQuery) > -1);
},
toggleText() {
if (this.isLoading) {
return s__('ClusterIntegration|Fetching zones');
@ -71,33 +36,17 @@ export default {
},
watch: {
selectedProject() {
this.fetchZones();
},
},
methods: {
...mapActions(['setZone', 'getZones']),
fetchZones() {
this.isLoading = true;
this.getZones()
.then(() => {
if (this.defaultValue) {
const zoneToSelect = _.find(this.zones, item => item.name === this.defaultValue);
if (zoneToSelect) {
this.setZone(zoneToSelect.name);
}
}
this.isLoading = false;
this.hasErrors = false;
})
.catch(() => {
this.isLoading = false;
this.hasErrors = true;
});
.then(this.fetchSuccessHandler)
.catch(this.fetchFailureHandler);
},
},
methods: {
...mapActions(['getZones']),
...mapActions({ setItem: 'setZone' }),
},
};
</script>
@ -130,7 +79,7 @@ export default {
v-for="result in results"
:key="result.id"
>
<button @click.prevent="setZone(result.name)">
<button @click.prevent="setItem(result.name)">
{{ result.name }}
</button>
</li>

View File

@ -73,7 +73,7 @@ describe('GkeMachineTypeDropdown', () => {
});
it('returns machine type name if machine type selected', () => {
vm.setMachineType(selectedMachineTypeMock);
vm.setItem(selectedMachineTypeMock);
expect(vm.toggleText).toBe(selectedMachineTypeMock);
});

View File

@ -45,7 +45,7 @@ describe('GkeProjectIdDropdown', () => {
it('returns default toggle text', done => {
vm.$nextTick(() => {
vm.$nextTick(() => {
vm.setProject(emptyProjectMock);
vm.setItem(emptyProjectMock);
expect(vm.toggleText).toBe(LABELS.DEFAULT);
done();
@ -65,7 +65,7 @@ describe('GkeProjectIdDropdown', () => {
it('returns empty toggle text', done => {
vm.$nextTick(() => {
vm.$store.commit(SET_PROJECTS, []);
vm.setProject(emptyProjectMock);
vm.setItem(emptyProjectMock);
vm.$nextTick(() => {
expect(vm.toggleText).toBe(LABELS.EMPTY);

View File

@ -55,7 +55,7 @@ describe('GkeZoneDropdown', () => {
});
it('returns project name if project selected', () => {
vm.setZone(selectedZoneMock);
vm.setItem(selectedZoneMock);
expect(vm.toggleText).toBe(selectedZoneMock);
});