Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Dock): add GetLayoutConfig instance method #2221

Merged
merged 28 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
54b816e
feat: 增加 Reset 方法
ArgoZhang Oct 5, 2023
371f67c
feat: 增加 Reset 方法
ArgoZhang Oct 5, 2023
8d7ad76
refactor: 增加 Readonly 关键字
ArgoZhang Oct 5, 2023
c5669d3
LayoutConfig and SaveLayoutCallback
densen2014 Oct 5, 2023
0d3c1af
Update BootstrapBlazor.Shared.csproj
densen2014 Oct 5, 2023
264f780
分开配置
densen2014 Oct 5, 2023
c379fe5
Merge branch 'feat-dock' into DockLayout
densen2014 Oct 5, 2023
d6d0340
更新复位功能
densen2014 Oct 5, 2023
0b6fad5
GetLayout 获取面板的显示布局
densen2014 Oct 5, 2023
cabfdb2
去掉在saveConfig中调用 OnSaveLayoutCallbackAsync , 原因见备注
densen2014 Oct 5, 2023
79b9daf
Revert "Update BootstrapBlazor.Shared.csproj"
densen2014 Oct 5, 2023
1bc9683
Merge branch 'main' into DockLayout
densen2014 Oct 5, 2023
5279197
refactor: 增加销毁逻辑
ArgoZhang Oct 5, 2023
9772734
fix: 修复 layout 查找逻辑
ArgoZhang Oct 5, 2023
aa4b9ca
doc: 更新资源文件
ArgoZhang Oct 5, 2023
9aba074
refactor: 更新脚本
ArgoZhang Oct 5, 2023
a089208
doc: 更新注释文档
ArgoZhang Oct 5, 2023
ca986ba
refactor: 移除 SaveLayoutCallback 回调方法
ArgoZhang Oct 5, 2023
90d8f86
refactor: 更改方法为 getLayoutConfig
ArgoZhang Oct 5, 2023
ac7cf61
revert: 移除 Update 方法参数
ArgoZhang Oct 5, 2023
f661e1a
revert: 撤销布局逻辑
ArgoZhang Oct 5, 2023
c5fb04d
feat: 移除 LayoutConfig
ArgoZhang Oct 5, 2023
1cdfdac
refactor: 更改标题样式
ArgoZhang Oct 5, 2023
96c6370
refactor: 精简代码
ArgoZhang Oct 5, 2023
f534648
feat: 增加 LayoutConfig 参数
ArgoZhang Oct 5, 2023
9cb739e
refactor: 支持服务器端配置
ArgoZhang Oct 5, 2023
006ca09
refactor: 更新示例代码
ArgoZhang Oct 5, 2023
31d13aa
doc: 更新示例
ArgoZhang Oct 5, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,11 @@ void AddDockView(DemoMenuItem item)
{
Text = Localizer["DockViewLock"],
Url = "dock-view/lock"
},
new()
{
Text = Localizer["DockViewLayout"],
Url = "dock-view/layout"
}
};
AddBadge(item, count: 1);
Expand Down
1 change: 1 addition & 0 deletions src/BootstrapBlazor.Shared/Locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -4503,6 +4503,7 @@
"DockViewComplex": "Complex",
"DockViewVisible": "Visible",
"DockViewLock": "Lock",
"DockViewLayout": "Custom",
"OtherComponents": "Others",
"MouseFollowerIntro": "MouseFollower",
"Live2DDisplayIntro": "Live2D Widget",
Expand Down
1 change: 1 addition & 0 deletions src/BootstrapBlazor.Shared/Locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -4503,6 +4503,7 @@
"DockViewComplex": "组合布局",
"DockViewVisible": "可见性切换",
"DockViewLock": "布局锁定",
"DockViewLayout": "布局自定义",
"OtherComponents": "其他组件",
"MouseFollowerIntro": "鼠标跟随",
"Live2DDisplayIntro": "Live2D 插件",
Expand Down
94 changes: 94 additions & 0 deletions src/BootstrapBlazor.Shared/Samples/DockViews/DockViewLayout.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
@page "/dock-view/layout"
@inherits BaseDockView

<h4>自定义布局</h4>
<p>通过设置 <code>DockView</code> 的属性 <code>LayoutConfig</code> 初始化控制面板的显示布局, 方法 <code>GetLayoutConfig</code> 获取面板的显示布局</p>

<GroupBox Title="布局切换">
<Button OnClick="OnToggleLayout1" Text="布局1"></Button>
<Button OnClick="OnToggleLayout2" Text="布局2"></Button>
<Button OnClick="OnToggleLayout3" Text="布局3"></Button>
<Button OnClick="GetLayout" Text="获取布局"></Button>
<Button OnClick="Reset" Text="复位"></Button>
<code class="config">@LayoutConfigSave</code>
</GroupBox>

<div class="dock-toggle-demo">
<DockView @ref="DockView" Name="DockViewLayout" EnableLocalStorage="true" LayoutConfig="@LayoutConfig">
<DockContent Type="DockContentType.Column">
<DockComponent Title="标签一">
<Table TItem="DynamicObject" DynamicContext="DataTableDynamicContext"
IsStriped="true" IsBordered="true" IsExcel="true" ShowRefresh="false"
ShowDefaultButtons="false">
<DetailRowTemplate>
<div class="p-2 w-100">
<Table TItem="DynamicObject" DynamicContext="GetDetailDataTableDynamicContext(context)" IsStriped="true" IsBordered="true" IsExcel="true">
</Table>
</div>
</DetailRowTemplate>
</Table>
</DockComponent>
<DockComponent Title="标签二">
<Table TItem="Foo" @bind-Items="Items"
IsStriped="true" IsBordered="true" IsMultipleSelect="true"
ShowToolbar="true" ShowExtendButtons="true" ShowSkeleton="true"
OnAddAsync="@OnAddAsync">
<TableColumns>
<TableColumn @bind-Field="@context.DateTime" Width="180" />
<TableColumn @bind-Field="@context.Name" />
<TableColumn @bind-Field="@context.Address" Width="180" TextEllipsis="true" ShowTips="true" />
<TableColumn @bind-Field="@context.Education" />
<TableColumn @bind-Field="@context.Count" />
<TableColumn @bind-Field="@context.Complete" />
</TableColumns>
</Table>
</DockComponent>
<DockComponent Title="标签三">
<FetchData></FetchData>
</DockComponent>
</DockContent>
</DockView>
</div>

@code {
[NotNull]
private DockView? DockView { get; set; }

private async Task GetLayout()
{
LayoutConfigSave = await DockView.GetLayoutConfig();
}

private Task Reset() => DockView.Reset();

private void OnToggleLayout1()
{
LayoutConfig = LayoutConfig1;
}

private void OnToggleLayout2()
{
LayoutConfig = LayoutConfig2;
}

private void OnToggleLayout3()
{
LayoutConfig = LayoutConfig3;
}

string? LayoutConfig;

string? LayoutConfigSave;

string LayoutConfig1 = """"
{"root":{"type":"row","content":[{"type":"column","content":[{"type":"stack","content":[{"type":"component","content":[],"width":50,"minWidth":0,"height":50,"minHeight":0,"id":"bb_45517422","maximised":false,"isClosable":true,"reorderEnabled":true,"title":"标签三","componentType":"component","componentState":{"id":"bb_45517422","showClose":true,"class":null,"key":"标签三","lock":false}}],"width":50,"minWidth":0,"height":33.460076045627375,"minHeight":0,"id":"","isClosable":true,"maximised":false,"activeItemIndex":0},{"type":"stack","content":[{"type":"component","content":[],"width":50,"minWidth":0,"height":50,"minHeight":0,"id":"bb_42425232","maximised":false,"isClosable":true,"reorderEnabled":true,"title":"标签二","componentType":"component","componentState":{"id":"bb_42425232","showClose":true,"class":null,"key":"标签二","lock":false}}],"width":50,"minWidth":0,"height":66.53992395437263,"minHeight":0,"id":"","isClosable":true,"maximised":false,"activeItemIndex":0}],"width":50,"minWidth":50,"height":50,"minHeight":50,"id":"","isClosable":true},{"type":"stack","content":[{"type":"component","content":[],"width":50,"minWidth":0,"height":50,"minHeight":0,"id":"bb_21184535","maximised":false,"isClosable":true,"reorderEnabled":true,"title":"标签一","componentType":"component","componentState":{"id":"bb_21184535","showClose":true,"class":null,"key":"标签一","lock":false}}],"width":50,"minWidth":0,"height":50,"minHeight":0,"id":"bb_54183781","isClosable":true,"maximised":false,"activeItemIndex":0}],"width":50,"minWidth":50,"height":50,"minHeight":50,"id":"","isClosable":true},"openPopouts":[],"settings":{"constrainDragToContainer":true,"reorderEnabled":true,"popoutWholeStack":false,"blockedPopoutsThrowError":true,"closePopoutsOnUnload":true,"responsiveMode":"none","tabOverlapAllowance":0,"reorderOnTabMenuClick":true,"tabControlOffset":10,"popInOnClose":false},"dimensions":{"borderWidth":5,"borderGrabWidth":5,"minItemHeight":10,"minItemWidth":10,"headerHeight":25,"dragProxyWidth":300,"dragProxyHeight":200},"header":{"show":"top","popout":"lock/unlock","dock":"dock","close":"close","maximise":"maximise","minimise":"minimise","tabDropdown":"additional tabs"},"resolved":true}
"""";

string LayoutConfig2 = """"
{"root":{"type":"row","content":[{"type":"stack","content":[{"type":"component","content":[],"width":50,"minWidth":0,"height":50,"minHeight":0,"id":"bb_24636646","maximised":false,"isClosable":true,"reorderEnabled":true,"title":"标签三","componentType":"component","componentState":{"id":"bb_24636646","showClose":true,"class":null,"key":"标签三","lock":false}}],"width":33.333333333333336,"minWidth":0,"height":50,"minHeight":0,"id":"","isClosable":true,"maximised":false,"activeItemIndex":0},{"type":"stack","content":[{"type":"component","content":[],"width":50,"minWidth":0,"height":50,"minHeight":0,"id":"bb_60600063","maximised":false,"isClosable":true,"reorderEnabled":true,"title":"标签一","componentType":"component","componentState":{"id":"bb_60600063","showClose":true,"class":null,"key":"标签一","lock":false}}],"width":33.333333333333336,"minWidth":0,"height":50,"minHeight":0,"id":"bb_54183781","isClosable":true,"maximised":false,"activeItemIndex":0},{"type":"stack","content":[{"type":"component","content":[],"width":50,"minWidth":0,"height":50,"minHeight":0,"id":"bb_6744750","maximised":false,"isClosable":true,"reorderEnabled":true,"title":"标签二","componentType":"component","componentState":{"id":"bb_6744750","showClose":true,"class":null,"key":"标签二","lock":false}}],"width":33.33333333333333,"minWidth":0,"height":50,"minHeight":0,"id":"bb_6744750","isClosable":true,"maximised":false,"activeItemIndex":0}],"width":50,"minWidth":50,"height":50,"minHeight":50,"id":"","isClosable":true},"openPopouts":[],"settings":{"constrainDragToContainer":true,"reorderEnabled":true,"popoutWholeStack":false,"blockedPopoutsThrowError":true,"closePopoutsOnUnload":true,"responsiveMode":"none","tabOverlapAllowance":0,"reorderOnTabMenuClick":true,"tabControlOffset":10,"popInOnClose":false},"dimensions":{"borderWidth":5,"borderGrabWidth":5,"minItemHeight":10,"minItemWidth":10,"headerHeight":25,"dragProxyWidth":300,"dragProxyHeight":200},"header":{"show":"top","popout":"lock/unlock","dock":"dock","close":"close","maximise":"maximise","minimise":"minimise","tabDropdown":"additional tabs"},"resolved":true}
"""";

string LayoutConfig3 = """"
{"root":{"type":"stack","content":[{"type":"component","content":[],"width":50,"minWidth":0,"height":50,"minHeight":0,"id":"bb_24636646","maximised":false,"isClosable":true,"reorderEnabled":true,"title":"标签三","componentType":"component","componentState":{"id":"bb_24636646","showClose":true,"class":null,"key":"标签三","lock":false}},{"type":"component","content":[],"width":50,"minWidth":0,"height":50,"minHeight":0,"id":"bb_60600063","maximised":false,"isClosable":true,"reorderEnabled":true,"title":"标签一","componentType":"component","componentState":{"id":"bb_60600063","showClose":true,"class":null,"key":"标签一","lock":false}},{"type":"component","content":[],"width":50,"minWidth":0,"height":50,"minHeight":0,"id":"bb_6744750","maximised":false,"isClosable":true,"reorderEnabled":true,"title":"标签二","componentType":"component","componentState":{"id":"bb_6744750","showClose":true,"class":null,"key":"标签二","lock":false}}],"width":50,"minWidth":0,"height":50,"minHeight":0,"id":"bb_60600063","isClosable":true,"maximised":false,"activeItemIndex":1},"openPopouts":[],"settings":{"constrainDragToContainer":true,"reorderEnabled":true,"popoutWholeStack":false,"blockedPopoutsThrowError":true,"closePopoutsOnUnload":true,"responsiveMode":"none","tabOverlapAllowance":0,"reorderOnTabMenuClick":true,"tabControlOffset":10,"popInOnClose":false},"dimensions":{"borderWidth":5,"borderGrabWidth":5,"minItemHeight":10,"minItemWidth":10,"headerHeight":25,"dragProxyWidth":300,"dragProxyHeight":200},"header":{"show":"top","popout":"lock/unlock","dock":"dock","close":"close","maximise":"maximise","minimise":"minimise","tabDropdown":"additional tabs"},"resolved":true}
"""";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.config {
display: block;
margin-top: 1rem;
border: 1px solid var(--bs-secondary);
border-radius: var(--bs-border-radius);
padding: 0.5rem;
overflow: auto;
height: 88px;
}

.dock-toggle-demo {
height: calc(100vh - 424px);
margin-top: 1rem;
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
@page "/dock-view/lock"
@inherits BaseDockView

<h4 class="mt-3">锁定面板</h4>
<h4>锁定面板</h4>
<p>通过设置 <code>DockView</code> 的属性 <code>IsLock</code>,控制所有面板是否能拖动</p>
<p>通过设置 <code>DockComponent</code> 的属性 <code>IsLock</code>,控制某个面板是否能拖动</p>

<Button OnClick="OnToggleLock" Text="@LockText"></Button>

<div class="dock-lock-demo">
<DockView Name="DockViewLock" EnableLocalStorage="false" OnLockChangedCallbackAsync="OnLockChangedCallbackAsync" IsLock="@IsLock">
<DockView Name="DockViewLock" EnableLocalStorage="true" OnLockChangedCallbackAsync="OnLockChangedCallbackAsync" IsLock="@IsLock">
<DockContent Type="DockContentType.Row">
<DockComponent Title="标签一" IsLock="true">
<DockComponent Title="标签一">
<Table TItem="DynamicObject" DynamicContext="DataTableDynamicContext"
IsStriped="true" IsBordered="true" IsExcel="true" ShowRefresh="true"
ShowDefaultButtons="false" IsFixedHeader="false">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@page "/dock-view/visible"
@inherits BaseDockView

<h4 class="mt-3">可隐藏的面板</h4>
<h4>可隐藏的面板</h4>
<p>通过设置 <code>DockComponent</code> 的属性 <code>Visible</code> 控制面板的显示和隐藏</p>

<Button OnClick="OnToggleVisible" Text="切换标签一"></Button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<Version>7.0.11</Version>
<Version>7.0.12</Version>
</PropertyGroup>

<PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ public partial class DockView
[Parameter]
public string? LocalStoragePrefix { get; set; }

/// <summary>
/// 获得/设置 布局配置
/// </summary>
[Parameter]
public string? LayoutConfig { get; set; }

private DockViewConfig Config { get; } = new();

private DockContent Content { get; } = new();
Expand Down Expand Up @@ -150,6 +156,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
EnableLocalStorage = EnableLocalStorage,
IsLock = IsLock,
Contents = Config.Contents,
LayoutConfig = LayoutConfig,
LocalStorageKeyPrefix = $"{LocalStoragePrefix}-{Name}",
VisibleChangedCallback = nameof(VisibleChangedCallbackAsync),
InitializedCallback = nameof(InitializedCallbackAsync),
Expand Down Expand Up @@ -203,11 +210,25 @@ public async Task Lock(bool @lock)
}
}

/// <summary>
/// 获取布局配置
/// </summary>
/// <returns></returns>
public Task<string?> GetLayoutConfig() => InvokeAsync<string>("getLayoutConfig", Id);

/// <summary>
/// 重置为默认布局
/// </summary>
/// <returns></returns>
public Task Reset() => InvokeVoidAsync("reset", Id, GetOption(), Interop);
public Task Reset(string? layoutConfig = null)
{
var config = GetOption();
if (layoutConfig != null)
{
config.LayoutConfig = layoutConfig;
}
return InvokeVoidAsync("reset", Id, config);
}

/// <summary>
/// 标签页关闭回调方法 由 JavaScript 调用
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export async function init(id, option, invoke) {
await addLink("./_content/BootstrapBlazor.Dock/css/goldenlayout-bb.css")

const eventsData = new Map()
const dock = { el, eventsData, lock: option.lock }
const dock = { el, eventsData, invoke, lock: option.lock, layoutConfig: option.layoutConfig }
Data.set(id, dock)

option.invokeVisibleChangedCallback = (title, visible) => {
Expand Down Expand Up @@ -74,7 +74,10 @@ export function update(id, option) {
const dock = Data.get(id)

if (dock) {
if (dock.lock !== option.lock) {
if (dock.layoutConfig !== option.layoutConfig) {
reset(id, option)
}
else if (dock.lock !== option.lock) {
// 处理 Lock 逻辑
dock.lock = option.lock
lockDock(dock)
Expand All @@ -92,7 +95,17 @@ export function lock(id, lock) {
lockDock(dock)
}

export function reset(id, option, invoke) {
export function getLayoutConfig(id) {
let config = "";
const dock = Data.get(id)
if (dock) {
const layout = dock.layout
config = JSON.stringify(layout.saveLayout())
}
return config;
}

export function reset(id, option) {
const dock = Data.get(id)
if (dock) {
removeConfig(option);
Expand All @@ -108,7 +121,7 @@ export function reset(id, option, invoke) {
})
dispose(id)

init(id, option, invoke)
init(id, option, dock.invoke)
}
}

Expand All @@ -122,6 +135,13 @@ export function dispose(id) {

dock.eventsData.clear()
dock.layout.destroy()

if (goldenLayout.bb_docks !== void 0) {
const index = goldenLayout.bb_docks.indexOf(dock);
if (index > 0) {
goldenLayout.bb_docks.splice(index, 1);
}
}
}

const lockDock = dock => {
Expand Down Expand Up @@ -291,21 +311,24 @@ const closeItem = (el, component) => {
}

const getConfig = option => {
let config = null
option = {
enableLocalStorage: false,
layoutConfig: null,
name: 'default',
...option
}
if (option.enableLocalStorage) {
const localConfig = localStorage.getItem(getLocalStorageKey(option));
if (localConfig) {
// 当tab全部关闭时,没有root节点
const configItem = JSON.parse(localConfig)
if (configItem.root) {
config = configItem
resetComponentId(config, option)
}

let config = null
let layoutConfig = option.layoutConfig;
if (layoutConfig === null && option.enableLocalStorage) {
layoutConfig = localStorage.getItem(getLocalStorageKey(option));
}
if (layoutConfig) {
// 当tab全部关闭时,没有root节点
const configItem = JSON.parse(layoutConfig)
if (configItem.root) {
config = configItem
resetComponentId(config, option)
}
}

Expand Down Expand Up @@ -474,7 +497,7 @@ const hackGoldenLayout = dock => {

this._closeButton.onClick = function (ev) {
// find own dock
const dock = goldenLayout.bb_docks.find(i => i.layout === this.layoutManager);
const dock = goldenLayout.bb_docks.find(i => i.layout === this._header.layoutManager);
const eventsData = dock.eventsData

const tabs = this._header.tabs.map(tab => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,9 @@ class DockViewConfig
[JsonPropertyName("content")]
[JsonConverter(typeof(DockContentRootConverter))]
public List<DockContent> Contents { get; set; } = new();

/// <summary>
/// 获得/设置 布局配置 默认 null 未设置
/// </summary>
public string? LayoutConfig { get; set; }
}