Compare commits

...

2 Commits

Author SHA1 Message Date
mathieuRA
c172a75f10 finish the PR and test it 2024-02-21 09:12:41 +01:00
mathieuRA
7f21e7aeeb feat(xo-web/license): ability to rebind licenses 2024-02-19 16:51:59 +01:00
4 changed files with 104 additions and 94 deletions

View File

@@ -3621,6 +3621,9 @@ export const unlockXosan = (licenseId, srId) => _call('xosan.unlock', { licenseI
export const bindLicense = (licenseId, boundObjectId) => _call('xoa.licenses.bind', { licenseId, boundObjectId })
export const rebindObjectLicense = (boundObjectId, licenseId, productId) =>
_call('xoa.licenses.rebindObject', { boundObjectId, licenseId, productId })
export const bindXcpngLicense = (licenseId, boundObjectId) =>
bindLicense(licenseId, boundObjectId)::tap(subscribeXcpngLicenses.forceRefresh)

View File

@@ -0,0 +1,53 @@
import _ from 'intl'
import ActionButton from 'action-button'
import Component from 'base-component'
import React from 'react'
import SelectLicense from 'select-license'
import { bindLicense, rebindObjectLicense } from 'xo'
import BulkIcons from '../../../common/bulk-icons'
export default class LicenseForm extends Component {
state = {
licenseId: 'none',
}
bind = async () => {
const { userData, item, itemUuidPath = 'uuid', license } = this.props
if (license !== undefined) {
await rebindObjectLicense(item[itemUuidPath], this.state.licenseId, license.productId)
} else {
await bindLicense(this.state.licenseId, item[itemUuidPath])
}
userData.updateLicenses()
this.setState({ licenseId: 'none' })
}
render() {
const { license } = this.props
return (
<div className='d-flex'>
<div>
{license !== undefined && license.id.slice(-4)}
<BulkIcons alerts={this.props.alerts} />
</div>
<form className='form-inline ml-1'>
<SelectLicense
onChange={this.linkState('licenseId')}
productType={this.props.productType}
value={this.state.licenseId}
/>
<ActionButton
btnStyle='primary'
className='ml-1'
disabled={this.state.licenseId === 'none'}
handler={this.bind}
icon='connect'
>
{_(license === undefined ? 'bindLicense' : 'update')}
</ActionButton>
</form>
</div>
)
}
}

View File

@@ -1,74 +1,68 @@
import _ from 'intl'
import ActionButton from 'action-button'
import Component from 'base-component'
import decorate from 'apply-decorators'
import Icon from 'icon'
import React from 'react'
import SelectLicense from 'select-license'
import SortedTable from 'sorted-table'
import Tooltip from 'tooltip'
import { addSubscriptions } from 'utils'
import groupBy from 'lodash/groupBy.js'
import { createSelector } from 'selectors'
import { injectState, provideState } from 'reaclette'
import { Proxy, Vm } from 'render-xo-item'
import { subscribeProxies, bindLicense } from 'xo'
import { subscribeProxies } from 'xo'
import LicenseForm from './license-form'
class ProxyLicensesForm extends Component {
state = {
licenseId: 'none',
}
getAlerts = createSelector(
() => this.props.item,
() => this.props.userData,
(proxy, userData) => {
const alerts = []
const licenses = userData.licensesByVmUuid[proxy.vmUuid]
onChangeLicense = event => {
this.setState({ licenseId: event.target.value })
}
if (proxy.vmUuid === undefined) {
alerts.push({
level: 'danger',
render: (
<p>
{_('proxyUnknownVm')} <a href='https://xen-orchestra.com/'>{_('contactUs')}</a>
</p>
),
})
}
bind = () => {
const { item, userData } = this.props
return bindLicense(this.state.licenseId, item.vmUuid).then(userData.updateLicenses)
}
// Proxy bound to multiple licenses
if (licenses?.length > 1) {
alerts.push({
level: 'danger',
render: (
<p>
{_('proxyMultipleLicenses')}
<br />
{licenses.map(license => license.id.slice(-4)).join(',')}
</p>
),
})
}
return alerts
}
)
render() {
const alerts = this.getAlerts()
const { item, userData } = this.props
const { licenseId } = this.state
const licenses = userData.licensesByVmUuid[item.vmUuid]
if (item.vmUuid === undefined) {
return (
<span className='text-danger'>
{_('proxyUnknownVm')} <a href='https://xen-orchestra.com/'>{_('contactUs')}</a>
</span>
)
}
// Proxy bound to multiple licenses
if (licenses?.length > 1) {
return (
<div>
<span>{licenses.map(license => license.id.slice(-4)).join(',')}</span>{' '}
<Tooltip content={_('proxyMultipleLicenses')}>
<Icon color='text-danger' icon='alarm' />
</Tooltip>
</div>
)
}
const license = licenses?.[0]
return license !== undefined ? (
<span>{license.id.slice(-4)}</span>
) : (
<form className='form-inline'>
<SelectLicense onChange={this.onChangeLicense} productType='xoproxy' />
<ActionButton
btnStyle='primary'
className='ml-1'
disabled={licenseId === 'none'}
handler={this.bind}
handlerParam={licenseId}
icon='connect'
>
{_('bindLicense')}
</ActionButton>
</form>
return (
<LicenseForm
alerts={alerts}
item={item}
itemUuidPath='vmUuid'
license={license}
productType='xoproxy'
userData={userData}
/>
)
}
}

View File

@@ -1,30 +1,17 @@
import _ from 'intl'
import ActionButton from 'action-button'
import Component from 'base-component'
import decorate from 'apply-decorators'
import Icon from 'icon'
import React from 'react'
import SelectLicense from 'select-license'
import SortedTable from 'sorted-table'
import { bindLicense } from 'xo'
import { connectStore } from 'utils'
import { createGetObjectsOfType, createSelector } from 'selectors'
import { groupBy } from 'lodash'
import { injectState, provideState } from 'reaclette'
import { Pool, Sr } from 'render-xo-item'
import BulkIcons from '../../../common/bulk-icons'
import LicenseForm from './license-form'
class XostorLicensesForm extends Component {
state = {
licenseId: 'none',
}
bind = () => {
const { item, userData } = this.props
return bindLicense(this.state.licenseId, item.uuid).then(userData.updateLicenses)
}
getAlerts = createSelector(
() => this.props.item,
() => this.props.userData,
@@ -59,39 +46,12 @@ class XostorLicensesForm extends Component {
render() {
const alerts = this.getAlerts()
if (alerts.length > 0) {
return <BulkIcons alerts={alerts} />
}
const { item, userData } = this.props
const { licenseId } = this.state
const licenses = userData.licensesByXostorUuid[item.id]
const license = licenses?.[0]
return license !== undefined ? (
<span>{license?.id.slice(-4)}</span>
) : (
<div>
{license !== undefined && (
<div className='text-danger mb-1'>
<Icon icon='alarm' /> {_('licenseHasExpired')}
</div>
)}
<form className='form-inline'>
<SelectLicense onChange={this.linkState('licenseId')} productType='xostor' />
<ActionButton
btnStyle='primary'
className='ml-1'
disabled={licenseId === 'none'}
handler={this.bind}
handlerParam={licenseId}
icon='connect'
>
{_('bindLicense')}
</ActionButton>
</form>
</div>
)
return <LicenseForm alerts={alerts} item={item} license={license} productType='xostor' userData={userData} />
}
}