fix(xo-web): use complex-matcher classes to build filters

Using strings directly breaks with special characters.
This commit is contained in:
Julien Fontanet 2022-08-02 17:30:14 +02:00
parent a4118a5676
commit b63086bf09
7 changed files with 37 additions and 13 deletions

View File

@ -28,5 +28,6 @@
<!--packages-start--> <!--packages-start-->
- @xen-orchestra/mixins patch - @xen-orchestra/mixins patch
- xo-web patch
<!--packages-end--> <!--packages-end-->

View File

@ -1,3 +1,4 @@
import * as CM from 'complex-matcher'
import _ from 'intl' import _ from 'intl'
import CopyToClipboard from 'react-copy-to-clipboard' import CopyToClipboard from 'react-copy-to-clipboard'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
@ -375,7 +376,7 @@ export const Proxy = decorate([
to={{ to={{
pathname: '/proxies', pathname: '/proxies',
query: { query: {
s: `id:${id}`, s: new CM.Property('id', new CM.String(id)).toString(),
}, },
}} }}
> >
@ -409,7 +410,11 @@ export const BackupJob = decorate([
} }
return ( return (
<LinkWrapper link={link} newTab={newTab} to={`/backup/overview?s=id:${id}`}> <LinkWrapper
link={link}
newTab={newTab}
to={`/backup/overview?s=${encodeURIComponent(new CM.Property('id', new CM.String(id)).toString())}`}
>
{job.name} {job.name}
</LinkWrapper> </LinkWrapper>
) )
@ -459,7 +464,11 @@ export const User = decorate([
return defaultRender || unknowItem(id, 'user') return defaultRender || unknowItem(id, 'user')
} }
return ( return (
<LinkWrapper link={link} newTab={newTab} to={`/settings/users?s=id:${id}`}> <LinkWrapper
link={link}
newTab={newTab}
to={`/settings/users?s=${encodeURIComponent(new CM.Property('id', new CM.String(id)).toString())}`}
>
<Icon icon='user' /> {user.email} <Icon icon='user' /> {user.email}
</LinkWrapper> </LinkWrapper>
) )

View File

@ -1,3 +1,4 @@
import * as CM from 'complex-matcher'
import _ from 'intl' import _ from 'intl'
import ActionButton from 'action-button' import ActionButton from 'action-button'
import addSubscriptions from 'add-subscriptions' import addSubscriptions from 'add-subscriptions'
@ -107,11 +108,12 @@ const GoToLogs = decorate([
effects: { effects: {
goTo() { goTo() {
const { jobId, location, router, scheduleId, scrollIntoLogs } = this.props const { jobId, location, router, scheduleId, scrollIntoLogs } = this.props
const search = jobId !== undefined ? ['jobId', jobId] : ['scheduleId', scheduleId]
router.replace({ router.replace({
...location, ...location,
query: { query: {
...location.query, ...location.query,
s_logs: jobId !== undefined ? `jobId:${jobId}` : `scheduleId:${scheduleId}`, s_logs: new CM.Property(search[0], new CM.String(search[1])).toString(),
}, },
}) })
scrollIntoLogs() scrollIntoLogs()

View File

@ -1,3 +1,4 @@
import * as CM from 'complex-matcher'
import _, { FormattedDuration } from 'intl' import _, { FormattedDuration } from 'intl'
import ActionButton from 'action-button' import ActionButton from 'action-button'
import addSubscriptions from 'add-subscriptions' import addSubscriptions from 'add-subscriptions'
@ -56,7 +57,7 @@ const GoToJob = decorate([
const { jobId, location, router, scrollIntoJobs } = this.props const { jobId, location, router, scrollIntoJobs } = this.props
router.replace({ router.replace({
...location, ...location,
query: { ...location.query, s: `id:${jobId}` }, query: { ...location.query, s: new CM.Property('id', new CM.String(jobId)).toString() },
}) })
scrollIntoJobs() scrollIntoJobs()
}, },

View File

@ -1,3 +1,4 @@
import * as CM from 'complex-matcher'
import _, { messages } from 'intl' import _, { messages } from 'intl'
import ActionButton from 'action-button' import ActionButton from 'action-button'
import ActionRowButton from 'action-row-button' import ActionRowButton from 'action-row-button'
@ -57,7 +58,10 @@ const COLUMNS = [
( (
<Link <Link
to={`/srs/${activeVdis[0].$SR}/disks?s=${encodeURIComponent( to={`/srs/${activeVdis[0].$SR}/disks?s=${encodeURIComponent(
`id:|(${activeVdis.map(activeVdi => activeVdi.id).join(' ')})` new CM.Property(
'id',
new CM.Or(activeVdis.map(activeVdi => new CM.String(activeVdi.id)))
).toString()
)}`} )}`}
> >
{activeVdis.length > 1 ? ( {activeVdis.length > 1 ? (

View File

@ -1,3 +1,4 @@
import * as CM from 'complex-matcher'
import _ from 'intl' import _ from 'intl'
import Component from 'base-component' import Component from 'base-component'
import decorate from 'apply-decorators' import decorate from 'apply-decorators'
@ -213,13 +214,18 @@ export default class TabGeneral extends Component {
this._getDiskGroups, this._getDiskGroups,
diskGroups => ids => diskGroups => ids =>
`#/srs/${this.props.sr.id}/disks?s=${encodeURIComponent( `#/srs/${this.props.sr.id}/disks?s=${encodeURIComponent(
`id:|(${flattenDeep( new CM.Property(
map(pick(keyBy(diskGroups, 'id'), ids), ({ id, baseCopies, vdis, snapshots, type }) => 'id',
type === 'orphanedSnapshot' ? id : [map(baseCopies, 'id'), map(vdis, 'id'), map(snapshots, 'id')] new CM.Or(
flattenDeep(
map(pick(keyBy(diskGroups, 'id'), ids), ({ id, baseCopies, vdis, snapshots, type }) =>
type === 'orphanedSnapshot' ? id : [map(baseCopies, 'id'), map(vdis, 'id'), map(snapshots, 'id')]
)
)
.sort()
.map(_ => new CM.String(_))
) )
) ).toString()
.sort()
.join(' ')})`
)}` )}`
) )

View File

@ -1,3 +1,4 @@
import * as CM from 'complex-matcher'
import * as FormGrid from 'form-grid' import * as FormGrid from 'form-grid'
import _ from 'intl' import _ from 'intl'
import ActionButton from 'action-button' import ActionButton from 'action-button'
@ -202,7 +203,7 @@ const getRedirectionUrl = vms =>
? undefined // no redirect ? undefined // no redirect
: vms.length === 1 : vms.length === 1
? `/vms/${vms[0]}` ? `/vms/${vms[0]}`
: `/home?s=${encodeURIComponent(`id:|(${vms.join(' ')})`)}&t=VM` : `/home?s=${encodeURIComponent(new CM.Property('id', new CM.Or(vms.map(_ => new CM.String(_)))).toString())}&t=VM`
export default class Import extends Component { export default class Import extends Component {
constructor(props) { constructor(props) {