| // Licensed to the Apache Software Foundation (ASF) under one | |
| // or more contributor license agreements. See the NOTICE file | |
| // distributed with this work for additional information | |
| // regarding copyright ownership. The ASF licenses this file | |
| // to you under the Apache License, Version 2.0 (the | |
| // "License"); you may not use this file except in compliance | |
| // with the License. You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, | |
| // software distributed under the License is distributed on an | |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| // KIND, either express or implied. See the License for the | |
| // specific language governing permissions and limitations | |
| // under the License. | |
| <template> | |
| <div> | |
| <div> | |
| <a-alert type="info" v-if="resource.state !== 'DISABLED'"> | |
| <template #message> | |
| <div | |
| v-html="$t('message.autoscale.vmprofile.update')" /> | |
| </template> | |
| </a-alert> | |
| <a-divider/> | |
| <div class="form"> | |
| <div class="form__item" v-if="resource.lbprovider === 'Netscaler'"> | |
| <div class="form__label">{{ $t('label.user') }}</div> | |
| <a-select | |
| :disabled="true" | |
| style="width: 100%" | |
| showSearch | |
| optionFilterProp="label" | |
| :filterOption="(input, option) => { | |
| return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0 | |
| }" | |
| v-focus="true" | |
| v-model:value="autoscaleuserid"> | |
| <a-select-option | |
| v-for="(user, index) in usersList" | |
| :value="user.id" | |
| :key="index" | |
| :label="user.username"> | |
| {{ user.username }} | |
| </a-select-option> | |
| </a-select> | |
| </div> | |
| </div> | |
| <div class="form"> | |
| <div class="form__item"> | |
| <div class="form__label"> | |
| <tooltip-label :title="$t('label.expungevmgraceperiod')" :tooltip="createAutoScaleVmProfileApiParams.expungevmgraceperiod.description"/> | |
| </div> | |
| {{ expungevmgraceperiod }} | |
| </div> | |
| </div> | |
| <div class="form"> | |
| <div class="form__item"> | |
| <div class="form__label"> | |
| <tooltip-label :title="$t('label.templatename')" :tooltip="createAutoScaleVmProfileApiParams.templateid.description"/> | |
| </div> | |
| {{ getTemplateName(templateid) }} | |
| </div> | |
| </div> | |
| <div class="form"> | |
| <div class="form__item"> | |
| <div class="form__label"> | |
| <tooltip-label :title="$t('label.serviceofferingid')" :tooltip="createAutoScaleVmProfileApiParams.serviceofferingid.description"/> | |
| </div> | |
| {{ getServiceOfferingName(serviceofferingid) }} | |
| </div> | |
| </div> | |
| <div class="form" v-if="userdataid"> | |
| <div class="form__item"> | |
| <div class="form__label"> | |
| <tooltip-label :title="$t('label.user.data.id')"/> | |
| </div> | |
| {{ userdataid }} | |
| </div> | |
| </div> | |
| <div class="form" v-if="userdataname"> | |
| <div class="form__item"> | |
| <div class="form__label"> | |
| <tooltip-label :title="$t('label.user.data.name')"/> | |
| </div> | |
| {{ userdataname }} | |
| </div> | |
| </div> | |
| <div class="form" v-if="userdatadetails"> | |
| <div class="form__item"> | |
| <div class="form__label"> | |
| <tooltip-label :title="$t('label.user.data.details')"/> | |
| </div> | |
| {{ userdatadetails }} | |
| </div> | |
| </div> | |
| <div class="form" v-if="userdatapolicy"> | |
| <div class="form__item"> | |
| <div class="form__label"> | |
| <tooltip-label :title="$t('label.user.data.policy')"/> | |
| </div> | |
| {{ userdatapolicy }} | |
| </div> | |
| </div> | |
| <div class="form"> | |
| <div class="form__item"> | |
| <div class="form__label"> | |
| <tooltip-label :title="$t('label.user.data')" :tooltip="createAutoScaleVmProfileApiParams.userdata.description"/> | |
| </div> | |
| <a-textarea v-model:value="userdata" rows="5" :disabled="true"> | |
| </a-textarea> | |
| </div> | |
| </div> | |
| <div class="form"> | |
| <div class="form__item"> | |
| <a-button ref="submit" :disabled="!('updateAutoScaleVmProfile' in $store.getters.apis) || resource.state !== 'DISABLED'" type="primary" @click="editProfileModalVisible = true"> | |
| <template #icon><edit-outlined /></template> | |
| {{ $t('label.edit.autoscale.vmprofile') }} | |
| </a-button> | |
| </div> | |
| <div class="form__item"> | |
| <a-button ref="submit" :disabled="!('updateAutoScaleVmProfile' in $store.getters.apis) || resource.state !== 'DISABLED'" type="primary" @click="showUpdateUserDataForm = true"> | |
| <template #icon><solution-outlined /></template> | |
| {{ $t('label.reset.user.data.on.autoscale.vm.group') }} | |
| </a-button> | |
| </div> | |
| </div> | |
| <a-divider/> | |
| <div class="title"> | |
| <div class="form__label"> | |
| <tooltip-label :title="$t('label.params')" :tooltip="createAutoScaleVmProfileApiParams.otherdeployparams.description"/> | |
| </div> | |
| </div> | |
| <div class="form" v-ctrl-enter="addParam"> | |
| <div class="form__item" ref="newParamName"> | |
| <div class="form__label"><span class="form__required">*</span>{{ $t('label.param.name') }}</div> | |
| <a-select | |
| style="width: 100%" | |
| showSearch | |
| optionFilterProp="value" | |
| :filterOption="(input, option) => { | |
| return option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0 | |
| }" | |
| v-focus="true" | |
| v-model:value="newParam.name"> | |
| <a-select-option v-for="(param, index) in paramNameList" :value="param" :key="index"> | |
| {{ param }} | |
| </a-select-option> | |
| </a-select> | |
| <span class="error-text">{{ $t('label.required') }}</span> | |
| </div> | |
| <div class="form__item" ref="newParamValue"> | |
| <div class="form__label"><span class="form__required">*</span>{{ $t('label.param.value') }}</div> | |
| <a-input v-model:value="newParam.value"></a-input> | |
| <span class="error-text">{{ $t('label.required') }}</span> | |
| </div> | |
| <div class="form__item"> | |
| <div class="form__label">{{ $t('label.action') }}</div> | |
| <a-button ref="submit" :disabled="!('updateAutoScaleVmProfile' in $store.getters.apis) || resource.state !== 'DISABLED'" type="primary" @click="addParam"> | |
| <template #icon><plus-outlined /></template> | |
| {{ $t('label.add.param') }} | |
| </a-button> | |
| </div> | |
| </div> | |
| </div> | |
| <a-divider/> | |
| <a-table | |
| size="small" | |
| style="overflow-y: auto" | |
| :loading="loading" | |
| :columns="columns" | |
| :dataSource="allParams" | |
| :pagination="false" | |
| :rowKey="record => record.name"> | |
| <template #bodyCell="{ column, record }"> | |
| <template v-if="column.key === 'actions'"> | |
| <a-popconfirm | |
| :title="$t('label.delete') + '?'" | |
| @confirm="deleteParam(record.name)" | |
| :okText="$t('label.yes')" | |
| :cancelText="$t('label.no')" | |
| > | |
| <tooltip-button | |
| :tooltip="$t('label.delete')" | |
| :disabled="!('deleteCondition' in $store.getters.apis) || resource.state !== 'DISABLED'" | |
| type="primary" | |
| :danger="true" | |
| icon="delete-outlined" /> | |
| </a-popconfirm> | |
| </template> | |
| </template> | |
| </a-table> | |
| <a-modal | |
| :title="$t('label.edit.autoscale.vmprofile')" | |
| :visible="editProfileModalVisible" | |
| :afterClose="closeModal" | |
| :maskClosable="false" | |
| :closable="true" | |
| :footer="null" | |
| @cancel="editProfileModalVisible = false"> | |
| <div class="form"> | |
| <div class="form__item" v-if="resource.lbprovider === 'Netscaler'"> | |
| <div class="form__label">{{ $t('label.user') }}</div> | |
| <a-select | |
| style="width: 100%" | |
| showSearch | |
| optionFilterProp="label" | |
| :filterOption="(input, option) => { | |
| return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0 | |
| }" | |
| v-focus="true" | |
| v-model:value="autoscaleuserid"> | |
| <a-select-option | |
| v-for="(user, index) in usersList" | |
| :value="user.id" | |
| :key="index" | |
| :label="user.username"> | |
| {{ user.username }} | |
| </a-select-option> | |
| </a-select> | |
| </div> | |
| </div> | |
| <div class="form"> | |
| <div class="form__item"> | |
| <div class="form__label"> | |
| <tooltip-label :title="$t('label.expungevmgraceperiod')" :tooltip="createAutoScaleVmProfileApiParams.expungevmgraceperiod.description"/> | |
| </div> | |
| <a-input v-model:value="expungevmgraceperiod" type="number"></a-input> | |
| </div> | |
| </div> | |
| <div class="form"> | |
| <div class="form__item"> | |
| <div class="form__label"> | |
| <tooltip-label :title="$t('label.templatename')" :tooltip="createAutoScaleVmProfileApiParams.templateid.description"/> | |
| </div> | |
| <a-select | |
| style="width: 100%" | |
| showSearch | |
| optionFilterProp="label" | |
| :filterOption="(input, option) => { | |
| return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0 | |
| }" | |
| v-focus="true" | |
| v-model:value="templateid"> | |
| <a-select-option | |
| v-for="(template, index) in templatesList" | |
| :value="template.id" | |
| :key="index" | |
| :label="template.name"> | |
| {{ template.name }} | |
| </a-select-option> | |
| </a-select> | |
| </div> | |
| </div> | |
| <div class="form"> | |
| <div class="form__item"> | |
| <div class="form__label"> | |
| <tooltip-label :title="$t('label.serviceofferingid')" :tooltip="createAutoScaleVmProfileApiParams.serviceofferingid.description"/> | |
| </div> | |
| <a-select | |
| style="width: 100%" | |
| showSearch | |
| optionFilterProp="label" | |
| :filterOption="(input, option) => { | |
| return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0 | |
| }" | |
| v-focus="true" | |
| v-model:value="serviceofferingid"> | |
| <a-select-option | |
| v-for="(offering, index) in serviceOfferingsList" | |
| :value="offering.id" | |
| :key="index" | |
| :label="offering.name"> | |
| {{ offering.name }} | |
| </a-select-option> | |
| </a-select> | |
| </div> | |
| </div> | |
| <div :span="24" class="action-button"> | |
| <a-button :loading="loading" @click="closeModal">{{ $t('label.cancel') }}</a-button> | |
| <a-button :loading="loading" ref="submit" type="primary" @click="updateAutoScaleVmProfile">{{ $t('label.ok') }}</a-button> | |
| </div> | |
| </a-modal> | |
| <a-modal | |
| :visible="showUpdateUserDataForm" | |
| :title="$t('label.reset.user.data.on.autoscale.vm.group')" | |
| :closable="true" | |
| :maskClosable="false" | |
| :footer="null" | |
| @cancel="showUpdateUserDataForm = false" | |
| centered | |
| width="auto"> | |
| <reset-user-data | |
| :resource="{ ...resource, ...{ resetUserDataApiName: 'updateAutoScaleVmProfile', resetUserDataResourceId: this.resource.vmprofileid, templateid: this.templateid}}" | |
| @close-action="showUpdateUserDataForm = false" | |
| /> | |
| </a-modal> | |
| </div> | |
| </template> | |
| <script> | |
| import { getAPI, postAPI } from '@/api' | |
| import { isAdmin, isAdminOrDomainAdmin } from '@/role' | |
| import Status from '@/components/widgets/Status' | |
| import TooltipButton from '@/components/widgets/TooltipButton' | |
| import TooltipLabel from '@/components/widgets/TooltipLabel' | |
| import ResetUserData from '@views/compute/ResetUserData' | |
| export default { | |
| name: 'conditionsTab', | |
| components: { | |
| ResetUserData, | |
| Status, | |
| TooltipButton, | |
| TooltipLabel | |
| }, | |
| props: { | |
| resource: { | |
| type: Object, | |
| required: true | |
| } | |
| }, | |
| data () { | |
| return { | |
| filterColumns: ['Actions'], | |
| loading: true, | |
| editProfileModalVisible: false, | |
| showUpdateUserDataForm: false, | |
| profileid: null, | |
| autoscaleuserid: null, | |
| expungevmgraceperiod: null, | |
| templateid: null, | |
| serviceofferingid: null, | |
| userdata: null, | |
| userdataid: null, | |
| userdataname: null, | |
| userdatadetails: null, | |
| userdatapolicy: null, | |
| usersList: [], | |
| templatesList: [], | |
| serviceOfferingsList: [], | |
| allParams: [], | |
| newParam: { | |
| name: null, | |
| value: null | |
| }, | |
| counterParams: [], | |
| deployParams: [], | |
| columns: [ | |
| { | |
| title: this.$t('label.param.name'), | |
| dataIndex: 'name' | |
| }, | |
| { | |
| title: this.$t('label.param.value'), | |
| dataIndex: 'value' | |
| }, | |
| { | |
| title: this.$t('label.actions'), | |
| key: 'actions' | |
| } | |
| ] | |
| } | |
| }, | |
| beforeCreate () { | |
| this.createAutoScaleVmProfileApi = this.$store.getters.apis.createAutoScaleVmProfile || {} | |
| this.createAutoScaleVmProfileApiParams = {} | |
| this.createAutoScaleVmProfileApi.params.forEach(param => { | |
| this.createAutoScaleVmProfileApiParams[param.name] = param | |
| }) | |
| }, | |
| created () { | |
| this.fetchInitData() | |
| }, | |
| watch: { | |
| resource: { | |
| deep: true, | |
| handler (newItem) { | |
| if (!newItem || !newItem.id) { | |
| return | |
| } | |
| this.fetchData() | |
| } | |
| } | |
| }, | |
| inject: ['parentFetchData'], | |
| methods: { | |
| fetchInitData () { | |
| this.counterParams = ['snmpcommunity', 'snmpport'] | |
| this.deployParams = ['overridediskofferingid', 'rootdisksize', 'diskofferingid', 'disksize', | |
| 'keypairs', 'affinitygroupids', 'networkids', 'securitygroupids'] | |
| if (this.resource.lbprovider === 'Netscaler') { | |
| this.paramNameList = this.counterParams.concat(this.deployParams) | |
| } else if (('VirtualRouter', 'VpcVirtualRouter').includes(this.resource.lbprovider)) { | |
| this.paramNameList = this.deployParams | |
| } | |
| this.paramNameList = this.paramNameList.sort() | |
| this.fetchUserData() | |
| this.fetchTemplateData() | |
| this.fetchServiceOfferingData() | |
| this.fetchData() | |
| }, | |
| fetchUserData () { | |
| getAPI('listUsers', { | |
| domainid: this.resource.domainid, | |
| account: this.resource.account | |
| }).then(json => { | |
| this.usersList = json.listusersresponse?.user || [] | |
| }) | |
| }, | |
| fetchTemplateData () { | |
| const params = { | |
| listall: 'true', | |
| domainid: this.resource.domainid, | |
| account: this.resource.account | |
| } | |
| if (isAdmin()) { | |
| params.templatefilter = 'all' | |
| params.isready = true | |
| } else { | |
| params.templatefilter = 'executable' | |
| } | |
| getAPI('listTemplates', params).then(json => { | |
| this.templatesList = json.listtemplatesresponse?.template || [] | |
| }) | |
| }, | |
| fetchServiceOfferingData () { | |
| const params = { | |
| listall: 'true', | |
| issystem: 'false' | |
| } | |
| if (isAdminOrDomainAdmin()) { | |
| params.isrecursive = 'true' | |
| } | |
| getAPI('listServiceOfferings', params).then(json => { | |
| this.serviceOfferingsList = json.listserviceofferingsresponse?.serviceoffering || [] | |
| this.serviceOfferingsList = this.serviceOfferingsList.filter(offering => !offering.iscustomized) | |
| }) | |
| }, | |
| fetchData () { | |
| this.loading = true | |
| getAPI('listAutoScaleVmProfiles', { | |
| listAll: true, | |
| id: this.resource.vmprofileid | |
| }).then(response => { | |
| this.profileid = response.listautoscalevmprofilesresponse?.autoscalevmprofile?.[0]?.id | |
| this.autoscaleuserid = response.listautoscalevmprofilesresponse?.autoscalevmprofile?.[0]?.autoscaleuserid | |
| this.expungevmgraceperiod = response.listautoscalevmprofilesresponse?.autoscalevmprofile?.[0]?.expungevmgraceperiod | |
| this.serviceofferingid = response.listautoscalevmprofilesresponse?.autoscalevmprofile?.[0]?.serviceofferingid | |
| this.templateid = response.listautoscalevmprofilesresponse?.autoscalevmprofile?.[0]?.templateid | |
| this.userdata = this.decodeUserData(decodeURIComponent(response.listautoscalevmprofilesresponse?.autoscalevmprofile?.[0]?.userdata || '')) | |
| this.userdataid = response.listautoscalevmprofilesresponse?.autoscalevmprofile?.[0]?.userdataid | |
| this.userdataname = response.listautoscalevmprofilesresponse?.autoscalevmprofile?.[0]?.userdataname | |
| this.userdatadetails = response.listautoscalevmprofilesresponse?.autoscalevmprofile?.[0]?.userdatadetails | |
| this.userdatapolicy = response.listautoscalevmprofilesresponse?.autoscalevmprofile?.[0]?.userdatapolicy | |
| const counterparam = response.listautoscalevmprofilesresponse?.autoscalevmprofile?.[0]?.counterparam || {} | |
| const otherdeployparams = response.listautoscalevmprofilesresponse?.autoscalevmprofile?.[0]?.otherdeployparams || {} | |
| this.finalizeParams(counterparam, otherdeployparams) | |
| }).finally(() => { | |
| this.loading = false | |
| }) | |
| }, | |
| getTemplateName (templateid) { | |
| for (const template of this.templatesList) { | |
| if (template.id === templateid) { | |
| return template.name | |
| } | |
| } | |
| return '' | |
| }, | |
| getServiceOfferingName (serviceofferingid) { | |
| for (const serviceoffering of this.serviceOfferingsList) { | |
| if (serviceoffering.id === serviceofferingid) { | |
| return serviceoffering.name | |
| } | |
| } | |
| return '' | |
| }, | |
| handleCancel () { | |
| this.parentFetchData() | |
| }, | |
| finalizeParams (counterparam, otherdeployparams) { | |
| this.allParams = [] | |
| if (counterparam.snmpcommunity) { | |
| this.allParams.push({ name: 'snmpcommunity', value: counterparam.snmpcommunity }) | |
| } | |
| if (counterparam.snmpport) { | |
| this.allParams.push({ name: 'snmpport', value: counterparam.snmpport }) | |
| } | |
| if (otherdeployparams.diskofferingid) { | |
| this.allParams.push({ name: 'diskofferingid', value: otherdeployparams.diskofferingid }) | |
| } | |
| if (otherdeployparams.securitygroupids) { | |
| this.allParams.push({ name: 'securitygroupids', value: otherdeployparams.securitygroupids }) | |
| } | |
| if (otherdeployparams.rootdisksize) { | |
| this.allParams.push({ name: 'rootdisksize', value: otherdeployparams.rootdisksize }) | |
| } | |
| if (otherdeployparams.disksize) { | |
| this.allParams.push({ name: 'disksize', value: otherdeployparams.disksize }) | |
| } | |
| if (otherdeployparams.overridediskofferingid) { | |
| this.allParams.push({ name: 'overridediskofferingid', value: otherdeployparams.overridediskofferingid }) | |
| } | |
| if (otherdeployparams.keypairs) { | |
| this.allParams.push({ name: 'keypairs', value: otherdeployparams.keypairs }) | |
| } | |
| if (otherdeployparams.affinitygroupids) { | |
| this.allParams.push({ name: 'affinitygroupids', value: otherdeployparams.affinitygroupids }) | |
| } | |
| if (otherdeployparams.networkids) { | |
| this.allParams.push({ name: 'networkids', value: otherdeployparams.networkids }) | |
| } | |
| }, | |
| deleteParam (paramName) { | |
| this.updateAutoScaleVmProfileWithParam(null, null, paramName) | |
| }, | |
| addParam () { | |
| if (this.loading) return | |
| if (!this.newParam.name) { | |
| this.$refs.newParamName.classList.add('error') | |
| } else { | |
| this.$refs.newParamName.classList.remove('error') | |
| } | |
| if (!this.newParam.value) { | |
| this.$refs.newParamValue.classList.add('error') | |
| } else { | |
| this.$refs.newParamValue.classList.remove('error') | |
| } | |
| if (!this.newParam.name || !this.newParam.value) { | |
| return | |
| } | |
| this.updateAutoScaleVmProfileWithParam(this.newParam.name, this.newParam.value, null) | |
| }, | |
| updateAutoScaleVmProfileWithParam (paramNameToAdd, paramValueToAdd, paramNameToRemove) { | |
| if (this.loading) return | |
| this.loading = true | |
| var params = { | |
| id: this.profileid | |
| } | |
| var i = 0 | |
| var j = 0 | |
| for (var index = 0; index < this.allParams.length; index++) { | |
| var param = { ...this.allParams[index] } | |
| if (this.counterParams.includes(param.name) && param.name !== paramNameToAdd && param.name !== paramNameToRemove) { | |
| params['counterparam[' + i + '].name'] = param.name | |
| params['counterparam[' + i + '].value'] = param.value | |
| i++ | |
| } | |
| if (this.deployParams.includes(param.name) && param.name !== paramNameToAdd && param.name !== paramNameToRemove) { | |
| params['otherdeployparams[' + j + '].name'] = param.name | |
| params['otherdeployparams[' + j + '].value'] = param.value | |
| j++ | |
| } | |
| } | |
| if (paramNameToAdd && this.counterParams.includes(paramNameToAdd) && paramValueToAdd) { | |
| params['counterparam[' + i + '].name'] = paramNameToAdd | |
| params['counterparam[' + i + '].value'] = paramValueToAdd | |
| } | |
| if (paramNameToAdd && this.deployParams.includes(paramNameToAdd) && paramValueToAdd) { | |
| params['otherdeployparams[' + j + '].name'] = paramNameToAdd | |
| params['otherdeployparams[' + j + '].value'] = paramValueToAdd | |
| } | |
| postAPI('updateAutoScaleVmProfile', params).then(response => { | |
| this.$pollJob({ | |
| jobId: response.updateautoscalevmprofileresponse.jobid, | |
| successMethod: (result) => { | |
| }, | |
| errorMessage: this.$t('message.update.autoscale.vm.profile.failed'), | |
| errorMethod: () => { | |
| } | |
| }) | |
| }).finally(() => { | |
| this.loading = false | |
| }) | |
| }, | |
| updateAutoScaleVmProfile () { | |
| const params = { | |
| id: this.profileid, | |
| expungevmgraceperiod: this.expungevmgraceperiod, | |
| serviceofferingid: this.serviceofferingid, | |
| templateid: this.templateid | |
| } | |
| if (this.autoscaleuserid) { | |
| params.autoscaleuserid = this.autoscaleuserid | |
| } | |
| const httpMethod = 'GET' | |
| const args = params | |
| const data = {} | |
| postAPI('updateAutoScaleVmProfile', args, httpMethod, data).then(response => { | |
| this.$pollJob({ | |
| jobId: response.updateautoscalevmprofileresponse.jobid, | |
| successMethod: (result) => { | |
| }, | |
| errorMessage: this.$t('message.update.autoscale.vm.profile.failed'), | |
| errorMethod: () => { | |
| } | |
| }) | |
| }).finally(() => { | |
| this.loading = false | |
| }) | |
| }, | |
| decodeUserData (userdata) { | |
| const decodedData = Buffer.from(userdata, 'base64') | |
| return decodedData.toString('utf-8') | |
| }, | |
| closeModal () { | |
| this.editProfileModalVisible = false | |
| } | |
| } | |
| } | |
| </script> | |
| <style scoped lang="scss"> | |
| .condition { | |
| &-container { | |
| display: flex; | |
| width: 100%; | |
| flex-wrap: wrap; | |
| margin-right: -20px; | |
| margin-bottom: -10px; | |
| } | |
| &__item { | |
| padding-right: 20px; | |
| margin-bottom: 20px; | |
| @media (min-width: 760px) { | |
| flex: 1; | |
| } | |
| } | |
| &__title { | |
| font-weight: bold; | |
| } | |
| } | |
| .title { | |
| margin-bottom: 5px; | |
| font-weight: bold; | |
| } | |
| .add-btn { | |
| width: 100%; | |
| padding-top: 15px; | |
| padding-bottom: 15px; | |
| height: auto; | |
| } | |
| .add-actions { | |
| display: flex; | |
| justify-content: flex-end; | |
| margin-right: -20px; | |
| margin-bottom: 20px; | |
| @media (min-width: 760px) { | |
| margin-top: 20px; | |
| } | |
| button { | |
| margin-right: 20px; | |
| } | |
| } | |
| .form { | |
| display: flex; | |
| margin-right: -20px; | |
| margin-bottom: 20px; | |
| flex-direction: column; | |
| align-items: flex-start; | |
| @media (min-width: 760px) { | |
| flex-direction: row; | |
| } | |
| &__item { | |
| display: flex; | |
| flex-direction: column; | |
| flex: 1; | |
| padding-right: 20px; | |
| margin-bottom: 20px; | |
| @media (min-width: 760px) { | |
| margin-bottom: 0; | |
| } | |
| input, | |
| .ant-select { | |
| margin-top: auto; | |
| } | |
| } | |
| &__label { | |
| font-weight: bold; | |
| } | |
| &__required { | |
| margin-right: 5px; | |
| color: red; | |
| } | |
| .error-text { | |
| display: none; | |
| color: red; | |
| font-size: 0.8rem; | |
| } | |
| .error { | |
| input { | |
| border-color: red; | |
| } | |
| .error-text { | |
| display: block; | |
| } | |
| } | |
| } | |
| .pagination { | |
| margin-top: 20px; | |
| } | |
| </style> |