1+ <script setup lang="ts">
2+
3+ import Vue , { PropType } from ' vue' ;
4+ import { ref , computed , watch , onMounted } from ' vue' ;
5+ import { useStore } from ' vuex' ;
6+ import { useRoute } from ' vue-router' ;
7+ import { sortBy } from ' @shell/utils/sort' ;
8+ import LabeledSelect from ' @shell/components/form/LabeledSelect.vue' ;
9+ import { _VIEW } from ' @shell/config/query-params' ;
10+ import { EpinioCompRecord , EpinioConfiguration , EpinioService , EPINIO_TYPES , EpinioAppBindings , EPINIO_APP_MANIFEST } from ' ../../types' ;
11+ import Application from ' ../../models/applications' ;
12+
13+
14+ interface Data {
15+ values: {
16+ configurations: string [],
17+ services: string [],
18+ }
19+ }
20+
21+ interface Props {
22+ initialApplication? : Application ;
23+ application: Application ;
24+ mode: string ;
25+ }
26+
27+ const props = defineProps <Props >();
28+ const emit = defineEmits ([' change' ]);
29+
30+ const store = useStore ();
31+ const route = useRoute ();
32+
33+ const t = store .getters [' i18n/t' ];
34+
35+ const values = ref ({
36+ configurations: [] as string [],
37+ services: [] as EpinioService [],
38+ });
39+
40+ const fetchData = async () => {
41+ await Promise .all ([
42+ store .dispatch (' epinio/findAll' , { type: EPINIO_TYPES .CONFIGURATION }),
43+ store .dispatch (' epinio/findAll' , { type: EPINIO_TYPES .SERVICE_INSTANCE }),
44+ ]);
45+ };
46+
47+ onMounted (fetchData );
48+
49+ // Computed
50+ const namespacedServices = computed (() =>
51+ (store .getters [' epinio/all' ](EPINIO_TYPES .SERVICE_INSTANCE ) || [])
52+ .filter ((s : EpinioService ) => s .metadata .namespace === props .application .metadata .namespace )
53+ );
54+
55+ const namespacedConfigurations = computed (() =>
56+ (store .getters [' epinio/all' ](EPINIO_TYPES .CONFIGURATION ) || [])
57+ .filter ((s : EpinioConfiguration ) => s .metadata .namespace === props .application .metadata .namespace )
58+ );
59+
60+ const configurations = computed (() => {
61+ const list = namespacedConfigurations .value
62+ .filter ((s : EpinioConfiguration ) => ! s .isServiceRelated )
63+ .map ((s : EpinioConfiguration ) => ({
64+ label: s .metadata .name ,
65+ value: s .metadata .name ,
66+ }));
67+
68+ return sortBy (list , ' label' , false );
69+ });
70+
71+ const services = computed (() => {
72+ const list = namespacedServices .value .map ((s : EpinioService ) => ({
73+ label: ` ${s .metadata .name } (${s .catalog_service }) ` ,
74+ value: s ,
75+ }));
76+
77+ return sortBy (list , ' label' , false );
78+ });
79+
80+ const noConfigs = computed (() => ! configurations .value .length );
81+ const hasConfigs = computed (() => !! configurations .value .length );
82+ const noServices = computed (() => ! services .value .length );
83+ const hasServices = computed (() => !! services .value .length );
84+ const isView = computed (() => props .mode === _VIEW );
85+ const isFromManifest = computed (() => route .query .from === EPINIO_APP_MANIFEST );
86+
87+ // Watchers
88+ watch (values , () => emit (' change' , values .value ), { deep: true });
89+
90+ watch (noConfigs , (neu ) => {
91+ if (neu && values .value .configurations ?.length ) {
92+ values .value .configurations = [];
93+ }
94+ });
95+
96+ watch (noServices , (neu ) => {
97+ if (neu && values .value .services ?.length ) {
98+ values .value .services = [];
99+ }
100+ });
101+
102+ watch (hasConfigs , (neu , old ) => {
103+ if (! old && neu ) {
104+ if (props .initialApplication ?.configuration ?.configurations ) {
105+ values .value .configurations = props .initialApplication .baseConfigurationsNames ?.filter (
106+ (cc : string ) => configurations .value .find ((c : any ) => c .value === cc )
107+ ) || [];
108+ }
109+
110+ if (isFromManifest .value ) {
111+ values .value .configurations = namespacedConfigurations .value
112+ .filter ((nc : any ) =>
113+ props .application .configuration .configurations .includes (nc .metadata .name ) &&
114+ ! nc .isServiceRelated
115+ )
116+ .map ((nc : any ) => nc .metadata .name ) || [];
117+ }
118+ }
119+ });
120+
121+ watch (hasServices , (neu , old ) => {
122+ if (! old && neu ) {
123+ if (props .initialApplication ?.serviceConfigurationsNames ) {
124+ values .value .services = props .initialApplication .services || [];
125+ }
126+ }
127+
128+ if (isFromManifest .value ) {
129+ const configurations = namespacedConfigurations .value
130+ .filter ((nc : any ) =>
131+ props .application .configuration .configurations .includes (nc .metadata .name ) &&
132+ nc .isServiceRelated
133+ );
134+
135+ values .value .services = services .value
136+ .filter ((s : any ) => configurations .some ((d : any ) => s .value .metadata .name === d .configuration .origin ))
137+ .map ((elem : any ) => elem .value );
138+ }
139+ });
140+ </script >
141+
142+ <template >
143+ <div >
144+ <div class =" col span-6" >
145+ <LabeledSelect
146+ v-model:value =" values.configurations"
147+ data-testid =" epinio_app-configuration_configurations"
148+ :loading =" $fetchState.pending"
149+ :disabled =" $fetchState.pending || noConfigs || isView"
150+ :options =" configurations"
151+ :searchable =" true"
152+ :mode =" mode"
153+ :multiple =" true"
154+ :label =" t('typeLabel.configurations', { count: 2})"
155+ :placeholder =" noConfigs ? t('epinio.applications.steps.configurations.configurations.select.placeholderNoOptions') : t('epinio.applications.steps.configurations.configurations.select.placeholderWithOptions')"
156+ />
157+ </div >
158+ <div class =" spacer" />
159+ <div class =" col span-6" >
160+ <LabeledSelect
161+ v-model:value =" values.services"
162+ data-testid =" epinio_app-configuration_services"
163+ :loading =" $fetchState.pending"
164+ :disabled =" $fetchState.pending || noServices || isView"
165+ :options =" services"
166+ :searchable =" true"
167+ :mode =" mode"
168+ :multiple =" true"
169+ :label =" t('epinio.applications.steps.configurations.services.select.label')"
170+ :placeholder =" noServices ? t('epinio.applications.steps.configurations.services.select.placeholderNoOptions') : t('epinio.applications.steps.configurations.services.select.placeholderWithOptions')"
171+ />
172+ </div >
173+ </div >
174+ </template >
175+
176+ <style lang='scss' scoped>
177+ .labeled-select {
178+ min-height : 79px ;
179+ }
180+ </style >
0 commit comments