Skip to content

Commit

Permalink
Merge pull request #751 from Support-pl/dev-fixes
Browse files Browse the repository at this point in the history
subaccount creation
  • Loading branch information
639852 authored Aug 22, 2024
2 parents 37a27c2 + a9373eb commit 5324b37
Show file tree
Hide file tree
Showing 8 changed files with 350 additions and 6 deletions.
19 changes: 17 additions & 2 deletions src/components/cloud/modules/ovh vps/panels/plan.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@
<a-col>
<span style="display: inline-block; width: 70px">CPU:</span>
</a-col>
<a-col v-if="resources.cpu.length > 1" :sm="{ span: 18, order: 0 }" :xs="{ span: 24, order: 1 }">
<a-slider
style="margin-top: 10px"
:marks="{ ...resources.cpu }"
:tip-formatter="null"
:max="resources.cpu.length - 1"
:min="0"
:value="resources.cpu.indexOf(options.cpu.size)"
@change="(i) => setOptions('cpu.size', resources.cpu[i])"
@after-change="setResources(productKey)"
/>
</a-col>
<a-col class="changing__field" style="text-align: right">
<loading-icon v-if="options.cpu.size === 'loading'" />
<template v-else>
Expand Down Expand Up @@ -221,19 +233,22 @@ watch(products, async (value) => {
})
const resources = computed(() => {
const cpu = new Set()
const ram = new Set()
const disk = new Set()
const filteredPlans = props.products.filter(({ group }) => group === product.value)
filteredPlans.forEach(({ resources }) => {
cpu.add(resources.cpu)
ram.add(resources.ram / 1024)
disk.add(resources.disk / 1024)
})
return {
ram: Array.from(ram).sort((a, b) => a - b),
disk: Array.from(disk).sort((a, b) => a - b)
cpu: Array.from(cpu).toSorted((a, b) => a - b),
ram: Array.from(ram).toSorted((a, b) => a - b),
disk: Array.from(disk).toSorted((a, b) => a - b)
}
})
Expand Down
206 changes: 206 additions & 0 deletions src/components/settings/accountCreate.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
<template>
<a-form
ref="formRef"
layout="vertical"
:model="form"
:rules="rules"
>
<a-form-item
v-for="key of mainKeys"
:key="key"
:label="`${capitalize($t(`clientinfo.${key}`))}:`"
:name="key"
>
<a-input v-model:value="form[key]" :disabled="isDisabled" />
</a-form-item>

<a-form-item
:label="`${capitalize($t('clientinfo.countryname'))}:`"
name="countryname"
>
<a-select
v-model:value="form.countryname"
show-search
:filter-option="searchCountries"
:disabled="isDisabled"
>
<a-select-option v-for="country in countries" :key="country.code">
{{ $t(`country.${country.code}`) }}
</a-select-option>
</a-select>
</a-form-item>

<a-form-item
:label="`${capitalize($t('clientinfo.phonenumber'))}:`"
name="phonenumber"
>
<input
v-model="form.phonenumber"
v-phone="phonecode"
type="tel"
class="user__input"
:disabled="!form.countryname || isDisabled"
>
</a-form-item>

<a-form-item
v-if="isPasswordVisible"
:label="`${capitalize($t('clientinfo.password'))}:`"
name="password"
>
<a-input v-model:value="form.password" />
</a-form-item>

<a-space style="margin-top: 10px">
<a-button
v-if="isPasswordVisible"
type="primary"
:loading="isCreateLoading"
@click="createAccount"
>
{{ $t('Submit') }}
</a-button>

<a-button danger @click="emits('cancel')">
{{ $t('Cancel') }}
</a-button>
</a-space>
</a-form>
</template>

<script setup>
import { ref, reactive, computed, onMounted, inject } from 'vue'
import { useI18n } from 'vue-i18n'
import { useAuthStore } from '@/stores/auth.js'
import { useNamespasesStore } from '@/stores/namespaces.js'
import { useNotification } from '@/hooks/utils'
import countries from '@/assets/countries.json'
const props = defineProps({
account: { type: Object, default: null }
})
const emits = defineEmits(['cancel'])
const i18n = useI18n()
const authStore = useAuthStore()
const namespacesStore = useNamespasesStore()
const { openNotification } = useNotification()
const mainKeys = ['firstname', 'lastname', 'email']
const formRef = ref(null)
const form = ref({})
const isDisabled = computed(() => props.account)
const isPasswordVisible = computed(() => !props.account)
const isCreateLoading = ref(false)
const reqRule = reactive({
required: true,
message: 'Field is required',
trigger: 'change'
})
const rules = computed(() => ({
email: [reqRule],
lastname: [reqRule],
firstname: [reqRule],
countryname: [reqRule],
phonenumber: [reqRule],
password: [reqRule]
}))
const phonecode = computed(() =>
countries.find(({ code }) => code === form.value.countryname)?.dial_code
)
function searchCountries (input, option) {
const country = option.children(option)[0].children.toLowerCase()
return country.includes(input.toLowerCase())
}
async function createAccount () {
try {
await formRef.value.validate()
} catch {
openNotification('error', {
message: i18n.t('ssl_product.fields is required')
})
return
}
isCreateLoading.value = true
try {
const namespace = namespacesStore.namespaces.find(({ access }) =>
access.namespace === authStore.userdata.uuid
)
await namespacesStore.createAccount({
title: `${form.value.firstname} ${form.value.lastname}`,
auth: {
type: 'standard',
data: [form.value.email, form.value.password]
},
namespace: namespace.uuid,
currency: authStore.userdata.currency,
data: {
email: form.value.email,
country: form.value.countryname,
phone: form.value.phonenumber
}
})
openNotification('success', { message: `${i18n.t('Done')}!` })
emits('cancel')
} catch (error) {
openNotification('error', {
message: error.response?.data?.message ?? error.message ?? error
})
} finally {
isCreateLoading.value = false
}
}
onMounted(() => {
reqRule.message = `${i18n.t('ssl_product.field is required')}`
if (props.account) {
form.value = {
email: props.account.data.email,
lastname: props.account.title.split(' ').at(0),
firstname: props.account.title.split(' ').at(-1),
countryname: props.account.data.country,
phonenumber: props.account.data.phone
}
}
})
const theme = inject('theme')
const inputColors = computed(() => (theme.value)
? ({ background: 'var(--bright_bg)', border: 'var(--bright_font)' })
: ({ background: 'inherit', border: 'var(--border_color)' })
)
if (namespacesStore.namespaces.length < 1) {
namespacesStore.fetch()
}
</script>
<style scoped>
.user__input {
padding: 4px 11px;
font-size: 14px;
width: 100%;
border: 1px solid v-bind('inputColors.border');
border-radius: 6px;
transition: all 0.2s;
background: v-bind('inputColors.background');
}
.user__input:disabled {
color: v-bind('inputColors.background');
background-color: v-bind('inputColors.border');
border-color: v-bind('inputColors.border');
box-shadow: none;
cursor: not-allowed;
}
</style>
1 change: 1 addition & 0 deletions src/functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ export function transformInstances (instances) {
if (inst.state?.meta.state === 5) status = 'SUSPENDED'
if (inst.data.suspended_manually) status = 'SUSPENDED'
if (inst.state?.meta.state === 'BUILD') status = 'BUILD'
if (!inst.state && !inst.data.is_monitored) status = 'INIT'

const result = {
...inst,
Expand Down
1 change: 1 addition & 0 deletions src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@
"share": "Share",
"link": "link",
"account": "account",
"subaccounts": "subaccounts",
"with": "with",
"Servers": "Virtual Servers",
"Virtual": "Web Hosting",
Expand Down
1 change: 1 addition & 0 deletions src/i18n/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@
"share": "поделиться",
"link": "привязать",
"account": "аккаунт",
"subaccounts": "субаккаунты",
"with": "с",
"Servers": "Сервера",
"Virtual": "Хостинг",
Expand Down
4 changes: 4 additions & 0 deletions src/routes/cloud/cloudPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,10 @@ export default {
if (this.VM.server_on) {
return this.VM.vm_info?.STATE?.replaceAll('_', ' ') ?? 'UNKNOWN'
}

if (!this.VM.state && !this.VM.data.is_monitored) {
return 'INIT'
}
if (!this.VM.state) return 'UNKNOWN'

const state = this.VM.state.meta?.lcm_state_str ?? this.VM.state.state
Expand Down
Loading

0 comments on commit 5324b37

Please sign in to comment.