owl-properties
Version:
properties kanban uesd in odoo owl2
151 lines (149 loc) • 4.95 kB
JavaScript
import { Component, EventBus, useEffect, useState, useSubEnv, xml } from '@odoo/owl';
import { PropertiesWrapper } from './components/properties/PropertiesWrapper';
import { BaseRenderer } from './components/renderer/BaseRenderer';
import { Input } from './components/renderer/Input';
import { Number } from './components/renderer/Number';
import { Select } from './components/renderer/Select';
import { Slider } from './components/renderer/Slider';
import { Switch } from './components/renderer/Switch';
import { Text } from './components/renderer/Text';
import { classNames } from './utils/classNames';
import { Color } from './components/renderer/Color';
import './index.css';
const registry = new Map();
class PropertiesPanel extends Component {
constructor() {
super(...arguments);
this.state = useState({
activeTab: this.props.active || this.props.tabs[0]?.key,
visibleTabs: [],
});
}
get currentTab() {
// 首先尝试找到当前激活且可见的tab
const activeVisibleTab = this.props.tabs.find((tab) => tab.key === this.state.activeTab && this.isTabVisible(tab));
if (activeVisibleTab) {
return activeVisibleTab;
}
// 如果没有找到,则返回第一个可见的tab
return this.props.tabs.find((tab) => this.isTabVisible(tab));
}
isTabVisible(tab) {
// 如果tab有自定义组件,则始终显示
if (tab.component) {
return true;
}
// 如果tab没有properties或properties为空数组,则不显示
if (!tab.properties || tab.properties.length === 0) {
return false;
}
// 如果所有属性都是invisible,则不显示该tab
return !tab.properties.every((property) => property.invisible?.());
}
switchTab(key) {
this.state.activeTab = key;
this.props.onChangeTab?.(key);
}
setup() {
useEffect(() => {
this.props.ref?.(this);
}, () => []);
useEffect(() => {
if (this.props.active) {
if (this.state.visibleTabs.some((tab) => tab.key === this.props.active)) {
this.state.activeTab = this.props.active;
}
else {
this.switchTab(this.state.visibleTabs[0]?.key);
}
}
}, () => [this.props.active, this.state.visibleTabs]);
useEffect(() => {
this.state.visibleTabs = this.props.tabs.filter((tab) => this.isTabVisible(tab));
}, () => [this.props.tabs]);
useSubEnv({
registry,
bus: this.props.bus,
});
}
}
PropertiesPanel.props = {
tabs: {
type: Array,
optional: true,
},
active: {
type: String,
optional: true,
},
onChangeTab: {
type: Function,
optional: true,
},
forceRender: {
type: Boolean,
optional: true,
},
ref: {
type: Function,
optional: true,
},
bus: {
type: Object,
optional: true,
},
};
PropertiesPanel.defaultProps = {
tabs: [],
forceRender: false,
bus: new EventBus(),
};
PropertiesPanel.components = {
PropertiesWrapper,
};
PropertiesPanel.componentTemplate = `
<t t-if="tab.component" t-component="tab.component" t-props="tab"/>
<t t-else="">
<PropertiesWrapper tab="tab"/>
</t>
`;
PropertiesPanel.template = xml `
<div class="${classNames('&properties-panel')}">
<div class="${classNames('&properties-panel-tabs')}">
<div class="${classNames('&properties-panel-tabs-inner')}">
<t t-foreach="state.visibleTabs" t-as="tab" t-key="tab.key">
<div
class="${classNames('&properties-panel-tab')}"
t-att-class="{'active': this.state.activeTab === tab.key}"
t-on-click="() => this.switchTab(tab.key)"
>
<t t-esc="tab.label"/>
</div>
</t>
</div>
</div>
<div class="${classNames('&properties-panel-content')}">
<t t-if="props.forceRender">
<div t-foreach="state.visibleTabs" t-as="tab" t-key="tab.key"
class="${classNames('&properties-panel-tab-content')}"
t-att-class="{ active: state.activeTab === tab.key }">
${PropertiesPanel.componentTemplate}
</div>
</t>
<t t-else="">
<t t-set="tab" t-value="currentTab"/>
<div t-if="currentTab" class="${classNames('&properties-panel-tab-content', 'active')}">
${PropertiesPanel.componentTemplate}
</div>
</t>
</div>
</div>
`;
registry.set('input', Input);
registry.set('text', Text);
registry.set('number', Number);
registry.set('select', Select);
registry.set('switch', Switch);
registry.set('slider', Slider);
registry.set('color', Color);
export { BaseRenderer, PropertiesPanel, registry, Input, Number, Select, Switch, Slider, Text, Color };