mirror of
https://github.com/getrebuild/rebuild.git
synced 2024-09-20 15:35:55 +08:00
n2nref compatible
This commit is contained in:
parent
918f503f69
commit
2f11f5be2e
2
@rbv
2
@rbv
|
@ -1 +1 @@
|
||||||
Subproject commit 5077481be27b5c21e2ecc687149718f9498c19a8
|
Subproject commit cf372ef8fec69b191700374676b2c994d12ae8b7
|
|
@ -118,6 +118,7 @@ public class EasyMeta implements BaseMeta {
|
||||||
*
|
*
|
||||||
* @param name
|
* @param name
|
||||||
* @return
|
* @return
|
||||||
|
* @see FieldExtConfigProps
|
||||||
*/
|
*/
|
||||||
public String getExtraAttr(String name) {
|
public String getExtraAttr(String name) {
|
||||||
return getExtraAttrs().getString(name);
|
return getExtraAttrs().getString(name);
|
||||||
|
|
|
@ -19,6 +19,7 @@ import com.rebuild.core.metadata.MetadataHelper;
|
||||||
import com.rebuild.core.metadata.MetadataSorter;
|
import com.rebuild.core.metadata.MetadataSorter;
|
||||||
import com.rebuild.core.metadata.impl.DisplayType;
|
import com.rebuild.core.metadata.impl.DisplayType;
|
||||||
import com.rebuild.core.metadata.impl.EasyMeta;
|
import com.rebuild.core.metadata.impl.EasyMeta;
|
||||||
|
import com.rebuild.core.metadata.impl.FieldExtConfigProps;
|
||||||
import com.rebuild.core.privileges.PrivilegesManager;
|
import com.rebuild.core.privileges.PrivilegesManager;
|
||||||
import com.rebuild.core.support.state.StateHelper;
|
import com.rebuild.core.support.state.StateHelper;
|
||||||
import com.rebuild.web.BaseController;
|
import com.rebuild.web.BaseController;
|
||||||
|
@ -167,12 +168,14 @@ public class MetadataGetting extends BaseController {
|
||||||
map.put("updatable", field.isUpdatable());
|
map.put("updatable", field.isUpdatable());
|
||||||
|
|
||||||
DisplayType dt = EasyMeta.getDisplayType(field);
|
DisplayType dt = EasyMeta.getDisplayType(field);
|
||||||
if (dt == DisplayType.REFERENCE) {
|
if (dt == DisplayType.REFERENCE || dt == DisplayType.N2NREFERENCE) {
|
||||||
Entity refEntity = field.getReferenceEntity();
|
Entity refEntity = field.getReferenceEntity();
|
||||||
Field nameField = MetadataHelper.getNameField(refEntity);
|
Field nameField = MetadataHelper.getNameField(refEntity);
|
||||||
map.put("ref", new String[]{refEntity.getName(), EasyMeta.getDisplayType(nameField).name()});
|
map.put("ref", new String[]{refEntity.getName(), EasyMeta.getDisplayType(nameField).name()});
|
||||||
} else if (dt == DisplayType.STATE) {
|
} else if (dt == DisplayType.STATE) {
|
||||||
map.put("stateClass", StateHelper.getSatetClass(field).getName());
|
map.put("stateClass", StateHelper.getSatetClass(field).getName());
|
||||||
|
} else if (dt == DisplayType.CLASSIFICATION) {
|
||||||
|
map.put("classification", easyField.getExtraAttr(FieldExtConfigProps.CLASSIFICATION_USE));
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,6 @@ module.exports = {
|
||||||
ConfigFormDlg: true,
|
ConfigFormDlg: true,
|
||||||
RbPreview: true,
|
RbPreview: true,
|
||||||
$countdownButton: true,
|
$countdownButton: true,
|
||||||
ChartSelect: true,
|
|
||||||
Share2: true,
|
Share2: true,
|
||||||
$stopEvent: true,
|
$stopEvent: true,
|
||||||
$addResizeHandler: true,
|
$addResizeHandler: true,
|
||||||
|
@ -105,6 +104,7 @@ module.exports = {
|
||||||
$fromNow: true,
|
$fromNow: true,
|
||||||
$expired: true,
|
$expired: true,
|
||||||
$L: true,
|
$L: true,
|
||||||
$isTrue: true
|
$isTrue: true,
|
||||||
|
$fieldIsCompatible: true
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,6 +114,7 @@
|
||||||
referenceEntity: '[[${referenceEntity}]]',
|
referenceEntity: '[[${referenceEntity}]]',
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<script th:src="@{/assets/js/metadata/field-compatible.js}" type="text/babel"></script>
|
||||||
<script th:src="@{/assets/js/metadata/auto-fillin.js}" type="text/babel"></script>
|
<script th:src="@{/assets/js/metadata/auto-fillin.js}" type="text/babel"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -111,6 +111,7 @@ $(document).ready(function () {
|
||||||
chart.w = chart.h = 4
|
chart.w = chart.h = 4
|
||||||
add_widget(chart)
|
add_widget(chart)
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line react/jsx-no-undef
|
||||||
renderRbcomp(<ChartSelect key="ChartSelect" select={select} />, null, function () {
|
renderRbcomp(<ChartSelect key="ChartSelect" select={select} />, null, function () {
|
||||||
dlgChartSelect = this
|
dlgChartSelect = this
|
||||||
this.setState({ appended: appended })
|
this.setState({ appended: appended })
|
||||||
|
|
|
@ -16,10 +16,10 @@ $(document).ready(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const loadRules = () => {
|
const loadRules = () => {
|
||||||
$.get('../auto-fillin-list?field=' + wpc.fieldName, (res) => {
|
$.get(`../auto-fillin-list?field=${wpc.fieldName}`, (res) => {
|
||||||
const tbody = $('#dataList tbody').empty()
|
const $tbody = $('#dataList tbody').empty()
|
||||||
$(res.data).each(function () {
|
$(res.data).each(function () {
|
||||||
let tr = $('<tr></tr>').appendTo(tbody)
|
let tr = $('<tr></tr>').appendTo($tbody)
|
||||||
$('<td><div>' + this.targetFieldLabel + '</div></td>').appendTo(tr)
|
$('<td><div>' + this.targetFieldLabel + '</div></td>').appendTo(tr)
|
||||||
$('<td>' + this.sourceFieldLabel + '</div></td>').appendTo(tr)
|
$('<td>' + this.sourceFieldLabel + '</div></td>').appendTo(tr)
|
||||||
const extc = this.extConfig
|
const extc = this.extConfig
|
||||||
|
@ -63,7 +63,7 @@ class DlgRuleEdit extends RbFormHandler {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<RbModal title="回填规则" ref={(c) => (this._dlg = c)} disposeOnHide={true}>
|
<RbModal title={$L('FillbackRule')} ref={(c) => (this._dlg = c)} disposeOnHide={true}>
|
||||||
<div className="form">
|
<div className="form">
|
||||||
<div className="form-group row">
|
<div className="form-group row">
|
||||||
<label className="col-sm-3 col-form-label text-sm-right">{$L('SourceField')}</label>
|
<label className="col-sm-3 col-form-label text-sm-right">{$L('SourceField')}</label>
|
||||||
|
@ -150,7 +150,7 @@ class DlgRuleEdit extends RbFormHandler {
|
||||||
placeholder: $L('SelectSome,Field'),
|
placeholder: $L('SelectSome,Field'),
|
||||||
allowClear: false,
|
allowClear: false,
|
||||||
})
|
})
|
||||||
.on('change', (e) => this.__renderTargetFields(e.target.value))
|
.on('change', (e) => this._renderTargetFields(e.target.value))
|
||||||
this.__select2.push(s2source)
|
this.__select2.push(s2source)
|
||||||
|
|
||||||
if (this.props.sourceField) {
|
if (this.props.sourceField) {
|
||||||
|
@ -168,40 +168,20 @@ class DlgRuleEdit extends RbFormHandler {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
__renderTargetFields(s) {
|
|
||||||
const source = this.__sourceFieldsCache.find((x) => {
|
_renderTargetFields(s) {
|
||||||
return s === x.name
|
const source = this.__sourceFieldsCache.find((x) => s === x.name)
|
||||||
})
|
|
||||||
let canFillinByType = CAN_FILLIN_MAPPINGS[source.type] || []
|
|
||||||
canFillinByType.push('TEXT')
|
|
||||||
canFillinByType.push('NTEXT')
|
|
||||||
|
|
||||||
// 显示兼容的目标字段
|
// 显示兼容的目标字段
|
||||||
let tFields = []
|
const targetFields = []
|
||||||
$(this.__targetFieldsCache).each(function () {
|
$(this.__targetFieldsCache).each(function () {
|
||||||
if (
|
if (this.creatable && this.name !== wpc.fieldName && $fieldIsCompatible(source, this)) {
|
||||||
!this.creatable ||
|
targetFields.push(this)
|
||||||
this.name === wpc.fieldName ||
|
|
||||||
this.type === 'SERIES' ||
|
|
||||||
this.type === 'MULTISELECT' ||
|
|
||||||
this.type === 'PICKLIST' ||
|
|
||||||
(source.type === 'FILE' && this.type !== 'FILE') ||
|
|
||||||
(source.type === 'IMAGE' && this.type !== 'IMAGE') ||
|
|
||||||
(source.type === 'AVATAR' && this.type !== 'AVATAR')
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
if (source.type === this.type || canFillinByType.includes(this.type)) {
|
|
||||||
if (source.type === 'REFERENCE') {
|
|
||||||
if (source.ref && this.ref && source.ref[0] === this.ref[0]) tFields.push(this)
|
|
||||||
} else if (source.type === 'STATE') {
|
|
||||||
if (source.stateClass && source.stateClass === this.stateClass) tFields.push(this)
|
|
||||||
} else {
|
|
||||||
tFields.push(this)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.setState({ targetFields: tFields })
|
this.setState({ targetFields: targetFields }, () => {
|
||||||
|
if (targetFields.length > 0) this.__select2[0].val(targetFields[0].name)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChange(e) {
|
handleChange(e) {
|
||||||
|
@ -237,10 +217,3 @@ class DlgRuleEdit extends RbFormHandler {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const CAN_FILLIN_MAPPINGS = {
|
|
||||||
NUMBER: ['DECIMAL'],
|
|
||||||
DECIMAL: ['NUMBER'],
|
|
||||||
DATE: ['DATETIME'],
|
|
||||||
DATETIME: ['DATE'],
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) REBUILD <https://getrebuild.com/> and/or its owners. All rights reserved.
|
||||||
|
|
||||||
|
rebuild is dual-licensed under commercial and open source licenses (GPLv3).
|
||||||
|
See LICENSE and COMMERCIAL in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 字段类型兼容
|
||||||
|
|
||||||
|
const FT_COMPATIBLE = {
|
||||||
|
NUMBER: ['DECIMAL'],
|
||||||
|
DECIMAL: ['NUMBER'],
|
||||||
|
DATE: ['DATETIME'],
|
||||||
|
DATETIME: ['DATE'],
|
||||||
|
TEXT: ['*'],
|
||||||
|
NTEXT: ['*'],
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字段兼容判断
|
||||||
|
* see backend `FieldValueCompatibleConversion.java`
|
||||||
|
*
|
||||||
|
* @param s 源字段
|
||||||
|
* @param t 目标字段
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
function $fieldIsCompatible(s, t) {
|
||||||
|
// 不支持
|
||||||
|
if (t.type === 'SERIES') return false
|
||||||
|
if (t.type === 'MULTISELECT') return false
|
||||||
|
if (t.type === 'PICKLIST') return false
|
||||||
|
|
||||||
|
// 必须对应
|
||||||
|
if (s.type === 'FILE' && t.type !== 'FILE') return false
|
||||||
|
if (s.type === 'IMAGE' && t.type !== 'IMAGE') return false
|
||||||
|
if (s.type === 'AVATAR' && t.type !== 'AVATAR') return false
|
||||||
|
|
||||||
|
// 判断附加参数
|
||||||
|
if (t.type === 'REFERENCE' || t.type === 'N2NREFERENCE') {
|
||||||
|
return t.ref && s.ref && t.ref[0] === s.ref[0]
|
||||||
|
}
|
||||||
|
if (t.type === 'CLASSIFICATION') {
|
||||||
|
return t.classification && t.classification === s.classification
|
||||||
|
}
|
||||||
|
if (t.type === 'STATE') {
|
||||||
|
return t.stateClass && t.stateClass === s.stateClass
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t.type === s.type) return true
|
||||||
|
const allow = FT_COMPATIBLE[t.type] || []
|
||||||
|
return allow.includes('*') || allow.includes(s.type)
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ Copyright (c) REBUILD <https://getrebuild.com/> and/or its owners. All rights re
|
||||||
rebuild is dual-licensed under commercial and open source licenses (GPLv3).
|
rebuild is dual-licensed under commercial and open source licenses (GPLv3).
|
||||||
See LICENSE and COMMERCIAL in the project root for license information.
|
See LICENSE and COMMERCIAL in the project root for license information.
|
||||||
*/
|
*/
|
||||||
|
// 打印视图
|
||||||
|
|
||||||
const wpc = window.__PageConfig
|
const wpc = window.__PageConfig
|
||||||
$(document).ready(() => {
|
$(document).ready(() => {
|
||||||
|
@ -32,8 +33,8 @@ class PreviewTable extends React.Component {
|
||||||
<table className="table table-bordered table-sm table-fixed">
|
<table className="table table-bordered table-sm table-fixed">
|
||||||
<tbody>
|
<tbody>
|
||||||
{rows.map((row, idx) => {
|
{rows.map((row, idx) => {
|
||||||
let c1 = row[0]
|
const c1 = row[0]
|
||||||
let c2 = row[1] || {}
|
const c2 = row[1] || {}
|
||||||
if (row.length === 1) {
|
if (row.length === 1) {
|
||||||
if (c1.field === '$DIVIDER$') {
|
if (c1.field === '$DIVIDER$') {
|
||||||
return (
|
return (
|
||||||
|
@ -72,7 +73,7 @@ class PreviewTable extends React.Component {
|
||||||
return (
|
return (
|
||||||
<div className="img-field avatar">
|
<div className="img-field avatar">
|
||||||
<span className="img-thumbnail img-upload">
|
<span className="img-thumbnail img-upload">
|
||||||
<img src={`${rb.baseUrl}/assets/img/avatar.png`} />
|
<img src={`${rb.baseUrl}/assets/img/avatar.png`} alt="Avatar" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -84,7 +85,7 @@ class PreviewTable extends React.Component {
|
||||||
return (
|
return (
|
||||||
<ul className="m-0 p-0 pl-3">
|
<ul className="m-0 p-0 pl-3">
|
||||||
{item.value.map((x) => {
|
{item.value.map((x) => {
|
||||||
return <li key={`file-${x}`}>{$fileCutName(x)}</li>
|
return <li key={x}>{$fileCutName(x)}</li>
|
||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
)
|
)
|
||||||
|
@ -93,8 +94,8 @@ class PreviewTable extends React.Component {
|
||||||
<ul className="list-inline m-0">
|
<ul className="list-inline m-0">
|
||||||
{item.value.map((x) => {
|
{item.value.map((x) => {
|
||||||
return (
|
return (
|
||||||
<li className="list-inline-item" key={`image-${x}`}>
|
<li className="list-inline-item" key={x}>
|
||||||
<img src={`${rb.baseUrl}/filex/img/${x}?imageView2/2/w/100/interlace/1/q/100`} />
|
<img src={`${rb.baseUrl}/filex/img/${x}?imageView2/2/w/100/interlace/1/q/100`} alt="IMG" />
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
@ -104,7 +105,7 @@ class PreviewTable extends React.Component {
|
||||||
return (
|
return (
|
||||||
<div className="img-field avatar">
|
<div className="img-field avatar">
|
||||||
<span className="img-thumbnail img-upload">
|
<span className="img-thumbnail img-upload">
|
||||||
<img src={`${rb.baseUrl}/filex/img/${item.value}?imageView2/2/w/100/interlace/1/q/100`} />
|
<img src={`${rb.baseUrl}/filex/img/${item.value}?imageView2/2/w/100/interlace/1/q/100`} alt="Avatar" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -132,12 +133,24 @@ class PreviewTable extends React.Component {
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
} else if (item.type === 'N2NREFERENCE') {
|
||||||
|
return (
|
||||||
|
<ul className="m-0 p-0 pl-3">
|
||||||
|
{item.value.map((x) => {
|
||||||
|
return <li key={x.id}>{__formatRefText(x)}</li>
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
)
|
||||||
} else if (typeof item.value === 'object') {
|
} else if (typeof item.value === 'object') {
|
||||||
let text = item.value.text
|
return __formatRefText(item.value)
|
||||||
if (!text && item.value.id) text = `@${item.value.id.toUpperCase()}`
|
|
||||||
return text
|
|
||||||
} else {
|
} else {
|
||||||
return item.value
|
return item.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const __formatRefText = function (value) {
|
||||||
|
const text = value.text
|
||||||
|
if (!text && value.id) return `@${value.id.toUpperCase()}`
|
||||||
|
else return text
|
||||||
|
}
|
||||||
|
|
|
@ -398,7 +398,10 @@ class FilterItem extends React.Component {
|
||||||
}
|
}
|
||||||
} else if (fieldType === 'BOOL') {
|
} else if (fieldType === 'BOOL') {
|
||||||
op = ['EQ']
|
op = ['EQ']
|
||||||
|
} else if (fieldType === 'N2NREFERENCE') {
|
||||||
|
op = []
|
||||||
}
|
}
|
||||||
|
|
||||||
op.push('NL', 'NT')
|
op.push('NL', 'NT')
|
||||||
if (this.isApprovalState()) op = ['IN', 'NIN']
|
if (this.isApprovalState()) op = ['IN', 'NIN']
|
||||||
|
|
||||||
|
|
|
@ -277,7 +277,7 @@ class BatchUpdateEditor extends React.Component {
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.__select2.forEach((item) => item.select2('destroy'))
|
this.__select2.forEach((item) => item.select2('destroy'))
|
||||||
this.__select2 = null
|
this.__select2 = null
|
||||||
this.__destroyLastValueComp()
|
this._destroyLastValueComp()
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -341,7 +341,7 @@ class BatchUpdateEditor extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__destroyLastValueComp() {
|
_destroyLastValueComp() {
|
||||||
if (this.__lastSelect2) {
|
if (this.__lastSelect2) {
|
||||||
this.__lastSelect2.select2('destroy')
|
this.__lastSelect2.select2('destroy')
|
||||||
this.__lastSelect2 = null
|
this.__lastSelect2 = null
|
||||||
|
@ -356,7 +356,7 @@ class BatchUpdateEditor extends React.Component {
|
||||||
// Unchanged
|
// Unchanged
|
||||||
if (prevState.selectField === this.state.selectField && prevState.selectOp === this.state.selectOp) return
|
if (prevState.selectField === this.state.selectField && prevState.selectOp === this.state.selectOp) return
|
||||||
if (this.state.selectOp === 'NULL') return
|
if (this.state.selectOp === 'NULL') return
|
||||||
this.__destroyLastValueComp()
|
this._destroyLastValueComp()
|
||||||
|
|
||||||
const field = this.props.fields.find((item) => {
|
const field = this.props.fields.find((item) => {
|
||||||
return this.state.selectField === item.name
|
return this.state.selectField === item.name
|
||||||
|
@ -365,7 +365,7 @@ class BatchUpdateEditor extends React.Component {
|
||||||
if (field.type === 'REFERENCE' || field.type === 'CLASSIFICATION') {
|
if (field.type === 'REFERENCE' || field.type === 'CLASSIFICATION') {
|
||||||
this.__lastSelect2 = $initReferenceSelect2(this._value, {
|
this.__lastSelect2 = $initReferenceSelect2(this._value, {
|
||||||
name: field.name,
|
name: field.name,
|
||||||
label: field.label,
|
placeholder: $L('NewValue'),
|
||||||
entity: this.props.entity,
|
entity: this.props.entity,
|
||||||
searchType: field.type === 'CLASSIFICATION' ? 'classification' : null,
|
searchType: field.type === 'CLASSIFICATION' ? 'classification' : null,
|
||||||
})
|
})
|
||||||
|
|
|
@ -1237,6 +1237,7 @@ const ChartsWidget = {
|
||||||
this.__chartSelect.setState({ appended: ChartsWidget.__currentCharts() })
|
this.__chartSelect.setState({ appended: ChartsWidget.__currentCharts() })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line react/jsx-no-undef
|
||||||
renderRbcomp(<ChartSelect select={(c) => this.renderChart(c, true)} entity={wpc.entity[0]} />, null, function () {
|
renderRbcomp(<ChartSelect select={(c) => this.renderChart(c, true)} entity={wpc.entity[0]} />, null, function () {
|
||||||
ChartsWidget.__chartSelect = this
|
ChartsWidget.__chartSelect = this
|
||||||
this.setState({ appended: ChartsWidget.__currentCharts() })
|
this.setState({ appended: ChartsWidget.__currentCharts() })
|
||||||
|
|
|
@ -490,7 +490,7 @@ var $unmount = function (container, delay, keepContainer) {
|
||||||
var $initReferenceSelect2 = function (el, field) {
|
var $initReferenceSelect2 = function (el, field) {
|
||||||
var search_input = null
|
var search_input = null
|
||||||
return $(el).select2({
|
return $(el).select2({
|
||||||
placeholder: $L('SelectSome').replace('{0}', field.label),
|
placeholder: field.placeholder || $L('SelectSome').replace('{0}', field.label),
|
||||||
minimumInputLength: 0,
|
minimumInputLength: 0,
|
||||||
maximumSelectionLength: $(el).attr('multiple') ? 999 : 2,
|
maximumSelectionLength: $(el).attr('multiple') ? 999 : 2,
|
||||||
ajax: {
|
ajax: {
|
||||||
|
|
Loading…
Reference in a new issue