mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-16 07:24:53 +09:00
Fix plugin list and header layout on mobile
This commit is contained in:
6 files changed
+101
-29
No files matched your search
@@ -31,6 +31,13 @@ Many thanks to the following for contributing to this release:
|
||||
[@username](https://github.com/username)
|
||||
-->
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Fixes
|
||||
|
||||
- Fixed cramped plugin rows and wrapping header branding on mobile screens.
|
||||
|
||||
|
||||
## Version 2.1.0
|
||||
|
||||
### Features
|
||||
|
||||
@@ -172,10 +172,12 @@ export function PluginVersions(props: { status: PluginStatus, latest?: string })
|
||||
{versions.map(version => {
|
||||
const now = count(machine => machine.running === version);
|
||||
const after = count(machine => machine.afterRestart === version);
|
||||
return <div key={version}>
|
||||
<Text>{version}</Text>
|
||||
{props.latest === version && <Tag color="success" style={{ marginLeft: 6 }}>latest</Tag>}
|
||||
<Text type="secondary" style={{ marginLeft: 12 }}>
|
||||
return <div key={version} className="plugin-version">
|
||||
<span>
|
||||
<Text>{version}</Text>
|
||||
{props.latest === version && <Tag color="success" style={{ marginLeft: 6 }}>latest</Tag>}
|
||||
</span>
|
||||
<Text type="secondary">
|
||||
{plural(now, "machine")}{now !== after && ` → ${after} after restart`}
|
||||
</Text>
|
||||
</div>;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { Space, Table, Tooltip, Typography } from "antd";
|
||||
import { Grid, Space, Table, Tooltip, Typography } from "antd";
|
||||
import CloseCircleFilled from "@ant-design/icons/CloseCircleFilled";
|
||||
|
||||
import type { PluginWebApi } from "@clusterio/lib";
|
||||
@@ -48,6 +48,8 @@ function WebError(props: { error: string }) {
|
||||
export default function PluginsPage() {
|
||||
const control = useContext(ControlContext);
|
||||
const account = useAccount();
|
||||
const screens = Grid.useBreakpoint();
|
||||
const isMobile = screens.md === false;
|
||||
let [pluginList, setPluginList] = useState<PluginWebApi[]>([]);
|
||||
const tableState = useTableQueryState<PluginRow>({
|
||||
namespace: "plugin", defaultSortKey: "name",
|
||||
@@ -96,6 +98,24 @@ export default function PluginsPage() {
|
||||
const latestOf = (plugin: PluginRow) => (
|
||||
plugin.status?.npmPackage ? latestVersions[plugin.status.npmPackage] : undefined
|
||||
);
|
||||
const versions = (plugin: PluginRow) => <>
|
||||
{plugin.status
|
||||
? <PluginVersions status={plugin.status} latest={latestOf(plugin)} />
|
||||
: plugin.meta?.version}
|
||||
{plugin.webError && <WebError error={plugin.webError} />}
|
||||
</>;
|
||||
const updateAction = (plugin: PluginRow) => (plugin.status
|
||||
// Keep clicks on the update action from opening the plugin.
|
||||
? <span onClick={event => { event.stopPropagation(); }}>
|
||||
<PluginUpdateButton
|
||||
status={plugin.status}
|
||||
title={plugin.title}
|
||||
latest={latestOf(plugin)}
|
||||
installer={installer}
|
||||
/>
|
||||
</span>
|
||||
: null
|
||||
);
|
||||
|
||||
return <PageLayout nav={[{ name: "Plugins" }]}>
|
||||
<PageHeader
|
||||
@@ -115,14 +135,22 @@ export default function PluginsPage() {
|
||||
</Space>}
|
||||
/>
|
||||
<Table
|
||||
className="plugins-table"
|
||||
tableLayout={isMobile ? "fixed" : "auto"}
|
||||
columns={[
|
||||
{
|
||||
title: "Name",
|
||||
key: "name",
|
||||
className: "table-link-cell",
|
||||
render: (_, plugin) => <Link to={pluginPath(plugin)} style={{ color: "inherit" }}>
|
||||
{plugin.title}
|
||||
</Link>,
|
||||
render: (_, plugin) => <>
|
||||
<Link to={pluginPath(plugin)} style={{ color: "inherit" }}>
|
||||
{plugin.title}
|
||||
</Link>
|
||||
{isMobile && <div className="plugin-mobile-details">
|
||||
<div>{versions(plugin)}</div>
|
||||
{updateAction(plugin)}
|
||||
</div>}
|
||||
</>,
|
||||
sorter: (a, b) => strcmp(a.title, b.title),
|
||||
sortOrder: tableState.sortOrder("name"),
|
||||
filteredValue: tableState.filteredValue("name"),
|
||||
@@ -131,28 +159,14 @@ export default function PluginsPage() {
|
||||
{
|
||||
title: "Versions",
|
||||
key: "versions",
|
||||
render: (_, plugin) => <>
|
||||
{plugin.status
|
||||
? <PluginVersions status={plugin.status} latest={latestOf(plugin)} />
|
||||
: plugin.meta?.version}
|
||||
{plugin.webError && <WebError error={plugin.webError} />}
|
||||
</>,
|
||||
responsive: ["md"],
|
||||
render: (_, plugin) => versions(plugin),
|
||||
},
|
||||
{
|
||||
key: "actions",
|
||||
align: "right",
|
||||
render: (_, plugin) => (plugin.status
|
||||
// Keep clicks on the update action from opening the plugin
|
||||
? <span onClick={event => { event.stopPropagation(); }}>
|
||||
<PluginUpdateButton
|
||||
status={plugin.status}
|
||||
title={plugin.title}
|
||||
latest={latestOf(plugin)}
|
||||
installer={installer}
|
||||
/>
|
||||
</span>
|
||||
: null
|
||||
),
|
||||
responsive: ["md"],
|
||||
render: (_, plugin) => updateAction(plugin),
|
||||
},
|
||||
]}
|
||||
dataSource={tableContents}
|
||||
|
||||
@@ -169,8 +169,10 @@ export default function SiteLayout() {
|
||||
/>;
|
||||
|
||||
let accountMenu = <Dropdown menu={accountMenuProps} trigger={["click"]} placement="bottomRight">
|
||||
<Button type="text" icon={<UserOutlined />} style={{ marginInlineStart: "auto" }}>
|
||||
{account.name}
|
||||
<Button type="text" icon={<UserOutlined />} style={{ marginInlineStart: "auto" }}
|
||||
aria-label={`Account menu for ${account.name}`}
|
||||
>
|
||||
<span className="site-layout-account-name">{account.name}</span>
|
||||
</Button>
|
||||
</Dropdown>;
|
||||
|
||||
@@ -228,7 +230,7 @@ export default function SiteLayout() {
|
||||
<Link to="/" style={{ display: "flex", alignItems: "center" }}>
|
||||
<img src={logo} width={56} height={56} alt="Clusterio logo" />
|
||||
</Link>
|
||||
<Flex vertical justify="center">
|
||||
<Flex vertical justify="center" className="site-layout-brand">
|
||||
<Typography.Title level={4} style={{ margin: 0, lineHeight: 1.2 }}>Clusterio</Typography.Title>
|
||||
<Tooltip title="View changelog" placement="right">
|
||||
<Typography.Text
|
||||
|
||||
@@ -72,6 +72,38 @@ body {
|
||||
background: #001529;
|
||||
}
|
||||
|
||||
.site-layout-brand {
|
||||
flex-shrink: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.site-layout-account-name {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.plugins-table .table-link-cell > a {
|
||||
font-weight: 600;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
}
|
||||
|
||||
.plugin-mobile-details {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
margin-top: 8px;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.plugin-version {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: baseline;
|
||||
column-gap: 12px;
|
||||
}
|
||||
|
||||
/* Keep the sidebar fixed in place (below the header) while content scrolls. */
|
||||
.site-layout-sider {
|
||||
position: sticky;
|
||||
|
||||
@@ -2,6 +2,21 @@
|
||||
|
||||
This folder contains files used for performing manual tests that are non-trivial to automate.
|
||||
|
||||
|
||||
## Plugins page on small screens
|
||||
|
||||
Use a cluster with several plugins, including one with different running and installed versions and one with a web load error.
|
||||
Compare the Plugins page at 390px and 1440px viewport widths, and check the 768px breakpoint.
|
||||
|
||||
1. On phones, check that each row shows its name, versions, machine counts, status and update action vertically, without clipping or breaking ordinary words.
|
||||
2. Check that a long plugin name wraps and the header branding stays on one line.
|
||||
3. Search and sort by name, reload, and check that the selected filter and sort order remain applied.
|
||||
4. Open an update or restart checklist, then cancel it; update actions must not navigate to the plugin page.
|
||||
5. Open a plugin by its name and by clicking elsewhere in its row.
|
||||
6. Open the account menu using the user icon on mobile; the full account name should appear in the menu.
|
||||
7. On desktop, check that the name, versions and update action remain separate columns.
|
||||
|
||||
|
||||
## Setup test mod
|
||||
|
||||
Run `node packages/lib/dist/node/build_mod.js --source-dir test/manual/test_mod/ --output-dir mods/` to create the test mod.
|
||||
|
||||
Reference in new issue
Block a user