fix(fe/panels): replace rows built-in sorting with common sorting
This commit is contained in:
parent
4896fd47fc
commit
05d8adb6d5
13 changed files with 336 additions and 130 deletions
|
@ -1,6 +1,11 @@
|
||||||
import { List, Map } from "immutable";
|
import { List, Map } from "immutable";
|
||||||
|
|
||||||
import { Row } from "../components/layout/rows";
|
|
||||||
|
export interface Row {
|
||||||
|
// elem: React.ReactNode; // element to display
|
||||||
|
val: Object; // original object value
|
||||||
|
sortVals: List<string>; // sortable values in order
|
||||||
|
}
|
||||||
|
|
||||||
export function getItemPath(dirPath: string, itemName: string): string {
|
export function getItemPath(dirPath: string, itemName: string): string {
|
||||||
return dirPath.endsWith("/")
|
return dirPath.endsWith("/")
|
||||||
|
|
42
src/client/web/src/components/control/btn_list.tsx
Normal file
42
src/client/web/src/components/control/btn_list.tsx
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
import * as React from "react";
|
||||||
|
import { List } from "immutable";
|
||||||
|
|
||||||
|
import { Flexbox } from "../layout/flexbox";
|
||||||
|
import { getIconWithProps } from "../visual/icons";
|
||||||
|
|
||||||
|
export type BtnListCallBack = () => void;
|
||||||
|
export interface Props {
|
||||||
|
titleIcon?: string;
|
||||||
|
btnNames: List<string>;
|
||||||
|
btnCallbacks: List<BtnListCallBack>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const BtnList = (props: Props) => {
|
||||||
|
const titleIcon =
|
||||||
|
props.titleIcon != null ? (
|
||||||
|
getIconWithProps(props.titleIcon, {
|
||||||
|
size: "3rem",
|
||||||
|
className: "black-font margin-r-m",
|
||||||
|
})
|
||||||
|
) : (
|
||||||
|
<span></span>
|
||||||
|
);
|
||||||
|
|
||||||
|
const btns = props.btnNames.map((btnName: string, i: number) => {
|
||||||
|
const cb = props.btnCallbacks.get(i);
|
||||||
|
return (
|
||||||
|
<button key={`rows-${i}`} className="float" onClick={cb}>
|
||||||
|
{btnName}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="margin-b-l">
|
||||||
|
<Flexbox
|
||||||
|
children={List([titleIcon, <span>{btns}</span>])}
|
||||||
|
childrenStyles={List([{ flex: "0 0 auto" }, { flex: "0 0 auto" }])}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -1,14 +1,11 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { List, Map, update } from "immutable";
|
import { List, Map } from "immutable";
|
||||||
|
|
||||||
import { updater } from "../state_updater";
|
import { updater } from "../state_updater";
|
||||||
import { getIcon } from "../visual/icons";
|
|
||||||
import { Flexbox } from "../layout/flexbox";
|
import { Flexbox } from "../layout/flexbox";
|
||||||
import { ICoreState, MsgProps, UIProps } from "../core_state";
|
import { ICoreState, MsgProps, UIProps } from "../core_state";
|
||||||
import { AdminProps } from "../pane_admin";
|
|
||||||
import { LoginProps } from "../pane_login";
|
|
||||||
import { alertMsg } from "../../common/env";
|
import { alertMsg } from "../../common/env";
|
||||||
import { IconProps } from "../visual/icons";
|
import { IconProps, getIcon } from "../visual/icons";
|
||||||
import { colorClass } from "../visual/colors";
|
import { colorClass } from "../visual/colors";
|
||||||
|
|
||||||
const defaultIconProps: IconProps = {
|
const defaultIconProps: IconProps = {
|
||||||
|
@ -20,8 +17,7 @@ const defaultIconProps: IconProps = {
|
||||||
export interface Props {
|
export interface Props {
|
||||||
targetControl: string;
|
targetControl: string;
|
||||||
tabIcons: Map<string, IconProps>; // option name -> icon name
|
tabIcons: Map<string, IconProps>; // option name -> icon name
|
||||||
login: LoginProps;
|
titleIcon?: string;
|
||||||
admin: AdminProps;
|
|
||||||
ui: UIProps;
|
ui: UIProps;
|
||||||
msg: MsgProps;
|
msg: MsgProps;
|
||||||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||||
|
@ -45,6 +41,10 @@ export class Tabs extends React.Component<Props, State, {}> {
|
||||||
this.props.targetControl
|
this.props.targetControl
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const titleIcon =
|
||||||
|
this.props.titleIcon != null
|
||||||
|
? getIcon(this.props.titleIcon, "2rem", "black")
|
||||||
|
: null;
|
||||||
const options = this.props.ui.control.options.get(this.props.targetControl);
|
const options = this.props.ui.control.options.get(this.props.targetControl);
|
||||||
const tabs = options.map((option: string) => {
|
const tabs = options.map((option: string) => {
|
||||||
const iconProps = this.props.tabIcons.has(option)
|
const iconProps = this.props.tabIcons.has(option)
|
||||||
|
@ -66,6 +66,7 @@ export class Tabs extends React.Component<Props, State, {}> {
|
||||||
>
|
>
|
||||||
<Flexbox
|
<Flexbox
|
||||||
children={List([
|
children={List([
|
||||||
|
<span>{titleIcon}</span>,
|
||||||
<span className="margin-r-s">{icon}</span>,
|
<span className="margin-r-s">{icon}</span>,
|
||||||
<span className={fontColor}>
|
<span className={fontColor}>
|
||||||
{this.props.msg.pkg.get(
|
{this.props.msg.pkg.get(
|
||||||
|
|
|
@ -55,18 +55,29 @@ export function newState(): ICoreState {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initState(): ICoreState {
|
export function initState(): ICoreState {
|
||||||
|
const defaultLanPackage = MsgPackage.get("en_US")
|
||||||
|
const filesOrderBy = defaultLanPackage.get("item.name");
|
||||||
|
const uploadingsOrderBy = defaultLanPackage.get("item.path");
|
||||||
|
const sharingsOrderBy = defaultLanPackage.get("item.path");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
filesInfo: {
|
filesInfo: {
|
||||||
dirPath: List<string>([]),
|
dirPath: List<string>([]),
|
||||||
items: List<MetadataResp>([]),
|
items: List<MetadataResp>([]),
|
||||||
isSharing: false,
|
isSharing: false,
|
||||||
|
orderBy: filesOrderBy,
|
||||||
|
order: true,
|
||||||
},
|
},
|
||||||
uploadingsInfo: {
|
uploadingsInfo: {
|
||||||
uploadings: List<UploadEntry>([]),
|
uploadings: List<UploadEntry>([]),
|
||||||
uploadFiles: List<File>([]),
|
uploadFiles: List<File>([]),
|
||||||
|
orderBy: uploadingsOrderBy,
|
||||||
|
order: true,
|
||||||
},
|
},
|
||||||
sharingsInfo: {
|
sharingsInfo: {
|
||||||
sharings: Map<string, string>(),
|
sharings: Map<string, string>(),
|
||||||
|
orderBy: sharingsOrderBy,
|
||||||
|
order: true,
|
||||||
},
|
},
|
||||||
admin: {
|
admin: {
|
||||||
users: Map<string, User>(),
|
users: Map<string, User>(),
|
||||||
|
@ -100,7 +111,7 @@ export function initState(): ICoreState {
|
||||||
},
|
},
|
||||||
msg: {
|
msg: {
|
||||||
lan: "en_US",
|
lan: "en_US",
|
||||||
pkg: MsgPackage.get("en_US"),
|
pkg: defaultLanPackage,
|
||||||
},
|
},
|
||||||
ui: {
|
ui: {
|
||||||
isVertical: isVertical(),
|
isVertical: isVertical(),
|
||||||
|
|
|
@ -52,8 +52,6 @@ export class SettingsDialog extends React.Component<Props, State, {}> {
|
||||||
color: "cyan1",
|
color: "cyan1",
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
login={this.props.login}
|
|
||||||
admin={this.props.admin}
|
|
||||||
ui={this.props.ui}
|
ui={this.props.ui}
|
||||||
msg={this.props.msg}
|
msg={this.props.msg}
|
||||||
update={this.props.update}
|
update={this.props.update}
|
||||||
|
|
|
@ -13,86 +13,86 @@ export interface Row {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
sortKeys: List<string>; // display names in order for sorting
|
// sortKeys: List<string>; // display names in order for sorting
|
||||||
rows: List<Row>;
|
rows: List<React.ReactNode>;
|
||||||
id?: string;
|
id?: string;
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
className?: string;
|
className?: string;
|
||||||
updateRows?: (rows: Object) => void; // this is a callback which update state with re-sorted rows
|
// updateRows?: (rows: Object) => void; // this is a callback which update state with re-sorted rows
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface State {
|
export interface State {}
|
||||||
orders: List<boolean>; // asc = true, desc = false
|
// // orders: List<boolean>; // asc = true, desc = false
|
||||||
}
|
// }
|
||||||
|
|
||||||
export class Rows extends React.Component<Props, State, {}> {
|
export class Rows extends React.Component<Props, State, {}> {
|
||||||
constructor(p: Props) {
|
constructor(p: Props) {
|
||||||
super(p);
|
super(p);
|
||||||
this.state = {
|
// this.state = {
|
||||||
orders: p.sortKeys.map((_: string, i: number) => {
|
// orders: p.sortKeys.map((_: string, i: number) => {
|
||||||
return false;
|
// return false;
|
||||||
}),
|
// }),
|
||||||
};
|
// };
|
||||||
}
|
}
|
||||||
|
|
||||||
sortRows = (key: number) => {
|
// sortRows = (key: number) => {
|
||||||
if (this.props.updateRows == null) {
|
// if (this.props.updateRows == null) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
const sortOption = this.props.sortKeys.get(key);
|
// const sortOption = this.props.sortKeys.get(key);
|
||||||
if (sortOption == null) {
|
// if (sortOption == null) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
const currentOrder = this.state.orders.get(key);
|
// const currentOrder = this.state.orders.get(key);
|
||||||
if (currentOrder == null) {
|
// if (currentOrder == null) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
const expectedOrder = !currentOrder;
|
// const expectedOrder = !currentOrder;
|
||||||
|
|
||||||
const sortedRows = sortRows(this.props.rows, key, expectedOrder);
|
// const sortedRows = sortRows(this.props.rows, key, expectedOrder);
|
||||||
const sortedItems = sortedRows.map((row: Row): Object => {
|
// const sortedItems = sortedRows.map((row: Row): Object => {
|
||||||
return row.val;
|
// return row.val;
|
||||||
});
|
// });
|
||||||
const newOrders = this.state.orders.set(key, !currentOrder);
|
// const newOrders = this.state.orders.set(key, !currentOrder);
|
||||||
this.setState({ orders: newOrders });
|
// this.setState({ orders: newOrders });
|
||||||
this.props.updateRows(sortedItems);
|
// this.props.updateRows(sortedItems);
|
||||||
};
|
// };
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const sortBtns = this.props.sortKeys.map(
|
// const sortBtns = this.props.sortKeys.map(
|
||||||
(displayName: string, i: number): React.ReactNode => {
|
// (displayName: string, i: number): React.ReactNode => {
|
||||||
return (
|
// return (
|
||||||
<button
|
// <button
|
||||||
key={`rows-${i}`}
|
// key={`rows-${i}`}
|
||||||
className="float"
|
// className="float"
|
||||||
onClick={() => {
|
// onClick={() => {
|
||||||
this.sortRows(i);
|
// this.sortRows(i);
|
||||||
}}
|
// }}
|
||||||
>
|
// >
|
||||||
{displayName}
|
// {displayName}
|
||||||
</button>
|
// </button>
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
);
|
// );
|
||||||
|
|
||||||
const bodyRows = this.props.rows.map(
|
const bodyRows = this.props.rows.map(
|
||||||
(row: Row, i: number): React.ReactNode => {
|
(row: React.ReactNode, i: number): React.ReactNode => {
|
||||||
return <div key={`rows-r-${i}`}>{row.elem}</div>;
|
return <div key={`rows-r-${i}`}>{row}</div>;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const orderByList =
|
// const orderByList =
|
||||||
sortBtns.size > 0 ? (
|
// sortBtns.size > 0 ? (
|
||||||
<div className="margin-b-l">
|
// <div className="margin-b-l">
|
||||||
<Flexbox
|
// <Flexbox
|
||||||
children={List([
|
// children={List([
|
||||||
<BiSortUp size="3rem" className="black-font margin-r-m" />,
|
// <BiSortUp size="3rem" className="black-font margin-r-m" />,
|
||||||
<span>{sortBtns}</span>,
|
// <span>{sortBtns}</span>,
|
||||||
])}
|
// ])}
|
||||||
childrenStyles={List([{ flex: "0 0 auto" }, { flex: "0 0 auto" }])}
|
// childrenStyles={List([{ flex: "0 0 auto" }, { flex: "0 0 auto" }])}
|
||||||
/>
|
// />
|
||||||
</div>
|
// </div>
|
||||||
) : null;
|
// ) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -100,7 +100,7 @@ export class Rows extends React.Component<Props, State, {}> {
|
||||||
style={this.props.style}
|
style={this.props.style}
|
||||||
className={this.props.className}
|
className={this.props.className}
|
||||||
>
|
>
|
||||||
{orderByList}
|
{/* {orderByList} */}
|
||||||
{bodyRows}
|
{bodyRows}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -168,8 +168,8 @@ export class PaneSettings extends React.Component<Props, State, {}> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
prepareErrorRows = (): List<Row> => {
|
prepareErrorRows = (): List<React.ReactNode> => {
|
||||||
let errRows = List<Row>();
|
let errRows = List<React.ReactNode>();
|
||||||
|
|
||||||
ErrorLogger()
|
ErrorLogger()
|
||||||
.readErrs()
|
.readErrs()
|
||||||
|
@ -180,14 +180,10 @@ export class PaneSettings extends React.Component<Props, State, {}> {
|
||||||
<div className="hr"></div>
|
<div className="hr"></div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
const val = clientErr;
|
// const val = clientErr;
|
||||||
const sortVals = List<string>([]);
|
// const sortVals = List<string>([]);
|
||||||
|
|
||||||
errRows = errRows.push({
|
errRows = errRows.push(elem);
|
||||||
elem,
|
|
||||||
val,
|
|
||||||
sortVals,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return errRows;
|
return errRows;
|
||||||
|
@ -218,7 +214,7 @@ export class PaneSettings extends React.Component<Props, State, {}> {
|
||||||
|
|
||||||
<div className="hr"></div>
|
<div className="hr"></div>
|
||||||
|
|
||||||
<Rows rows={errRows} sortKeys={List([])} />
|
<Rows rows={errRows}/>
|
||||||
</Container>
|
</Container>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,9 @@ import { MetadataResp, roleVisitor, roleAdmin } from "../client";
|
||||||
import { Flexbox } from "./layout/flexbox";
|
import { Flexbox } from "./layout/flexbox";
|
||||||
import { Container } from "./layout/container";
|
import { Container } from "./layout/container";
|
||||||
import { Table, Cell, Head } from "./layout/table";
|
import { Table, Cell, Head } from "./layout/table";
|
||||||
|
import { BtnList } from "./control/btn_list";
|
||||||
import { Segments } from "./layout/segments";
|
import { Segments } from "./layout/segments";
|
||||||
import { Rows, Row } from "./layout/rows";
|
import { Rows } from "./layout/rows";
|
||||||
import { Up } from "../worker/upload_mgr";
|
import { Up } from "../worker/upload_mgr";
|
||||||
import { UploadEntry, UploadState } from "../worker/interface";
|
import { UploadEntry, UploadState } from "../worker/interface";
|
||||||
import { getIcon } from "./visual/icons";
|
import { getIcon } from "./visual/icons";
|
||||||
|
@ -51,6 +52,8 @@ export interface FilesProps {
|
||||||
dirPath: List<string>;
|
dirPath: List<string>;
|
||||||
isSharing: boolean;
|
isSharing: boolean;
|
||||||
items: List<MetadataResp>;
|
items: List<MetadataResp>;
|
||||||
|
orderBy: string;
|
||||||
|
order: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
@ -602,12 +605,7 @@ export class FilesPanel extends React.Component<Props, State, {}> {
|
||||||
? "hidden"
|
? "hidden"
|
||||||
: "";
|
: "";
|
||||||
|
|
||||||
const sortKeys = List<string>([
|
const rows = sortedItems.map((item: MetadataResp): React.ReactNode => {
|
||||||
this.props.msg.pkg.get("item.type"),
|
|
||||||
this.props.msg.pkg.get("item.name"),
|
|
||||||
]);
|
|
||||||
|
|
||||||
const rows = sortedItems.map((item: MetadataResp): Row => {
|
|
||||||
const isSelected = this.state.selectedItems.has(item.name);
|
const isSelected = this.state.selectedItems.has(item.name);
|
||||||
const dirPath = this.props.filesInfo.dirPath.join("/");
|
const dirPath = this.props.filesInfo.dirPath.join("/");
|
||||||
const itemPath = dirPath.endsWith("/")
|
const itemPath = dirPath.endsWith("/")
|
||||||
|
@ -753,21 +751,16 @@ export class FilesPanel extends React.Component<Props, State, {}> {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const sortVals = List<string>([item.isDir ? "d" : "f", itemPath]);
|
// const sortVals = List<string>([item.isDir ? "d" : "f", itemPath]);
|
||||||
return {
|
return elem;
|
||||||
elem,
|
// return {
|
||||||
sortVals,
|
// elem,
|
||||||
val: item,
|
// sortVals,
|
||||||
};
|
// val: item,
|
||||||
|
// };
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return <Rows rows={List(rows)} />;
|
||||||
<Rows
|
|
||||||
sortKeys={sortKeys}
|
|
||||||
rows={List(rows)}
|
|
||||||
updateRows={this.updateItems}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
setView = (opt: string) => {
|
setView = (opt: string) => {
|
||||||
|
@ -779,6 +772,11 @@ export class FilesPanel extends React.Component<Props, State, {}> {
|
||||||
this.props.update(updater().updateUI);
|
this.props.update(updater().updateUI);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
orderBy = (columnName: string) => {
|
||||||
|
updater().sortFiles(columnName);
|
||||||
|
this.props.update(updater().updateFilesInfo);
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const showEndpoints =
|
const showEndpoints =
|
||||||
this.props.login.userRole === roleAdmin ? "" : "hidden";
|
this.props.login.userRole === roleAdmin ? "" : "hidden";
|
||||||
|
@ -867,6 +865,28 @@ export class FilesPanel extends React.Component<Props, State, {}> {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const orderByCallbacks = List([
|
||||||
|
() => {
|
||||||
|
this.orderBy(this.props.msg.pkg.get("item.name"));
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
this.orderBy(this.props.msg.pkg.get("item.type"));
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
this.orderBy(this.props.msg.pkg.get("item.modTime"));
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const orderByButtons = (
|
||||||
|
<BtnList
|
||||||
|
titleIcon="BiSortUp"
|
||||||
|
btnNames={List([
|
||||||
|
this.props.msg.pkg.get("item.name"),
|
||||||
|
this.props.msg.pkg.get("item.type"),
|
||||||
|
this.props.msg.pkg.get("item.modTime"),
|
||||||
|
])}
|
||||||
|
btnCallbacks={orderByCallbacks}
|
||||||
|
/>
|
||||||
|
);
|
||||||
const viewType = this.props.ui.control.controls.get(filesViewCtrl);
|
const viewType = this.props.ui.control.controls.get(filesViewCtrl);
|
||||||
const view =
|
const view =
|
||||||
viewType === "rows" ? (
|
viewType === "rows" ? (
|
||||||
|
@ -1012,7 +1032,7 @@ export class FilesPanel extends React.Component<Props, State, {}> {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="hr grey0-bg"></div>
|
<div className="hr grey0-bg"></div>
|
||||||
|
{orderByButtons}
|
||||||
{view}
|
{view}
|
||||||
</Container>
|
</Container>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { List, Map } from "immutable";
|
||||||
import { RiShareBoxLine } from "@react-icons/all-files/ri/RiShareBoxLine";
|
import { RiShareBoxLine } from "@react-icons/all-files/ri/RiShareBoxLine";
|
||||||
import { RiCloudOffFill } from "@react-icons/all-files/ri/RiCloudOffFill";
|
import { RiCloudOffFill } from "@react-icons/all-files/ri/RiCloudOffFill";
|
||||||
|
|
||||||
|
import { BtnList } from "./control/btn_list";
|
||||||
import { QRCodeIcon } from "./visual/qrcode";
|
import { QRCodeIcon } from "./visual/qrcode";
|
||||||
import { getErrMsg } from "../common/utils";
|
import { getErrMsg } from "../common/utils";
|
||||||
import { alertMsg, confirmMsg } from "../common/env";
|
import { alertMsg, confirmMsg } from "../common/env";
|
||||||
|
@ -19,6 +20,8 @@ import { CronTable } from "../common/cron";
|
||||||
|
|
||||||
export interface SharingsProps {
|
export interface SharingsProps {
|
||||||
sharings: Map<string, string>;
|
sharings: Map<string, string>;
|
||||||
|
orderBy: string;
|
||||||
|
order: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
@ -86,8 +89,8 @@ export class SharingsPanel extends React.Component<Props, State, {}> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
makeRows = (sharings: Map<string, string>): List<Row> => {
|
makeRows = (sharings: Map<string, string>): List<React.ReactNode> => {
|
||||||
const sharingRows = sharings.keySeq().map((dirPath: string) => {
|
const sharingRows = sharings.keySeq().map((dirPath: string):React.ReactNode => {
|
||||||
const shareID = sharings.get(dirPath);
|
const shareID = sharings.get(dirPath);
|
||||||
const sharingURL = `${
|
const sharingURL = `${
|
||||||
document.location.href.split("?")[0]
|
document.location.href.split("?")[0]
|
||||||
|
@ -130,11 +133,12 @@ export class SharingsPanel extends React.Component<Props, State, {}> {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return elem;
|
||||||
elem,
|
// return {
|
||||||
sortVals: List([dirPath]),
|
// elem,
|
||||||
val: dirPath,
|
// sortVals: List([dirPath]),
|
||||||
};
|
// val: dirPath,
|
||||||
|
// };
|
||||||
});
|
});
|
||||||
|
|
||||||
return sharingRows.toList();
|
return sharingRows.toList();
|
||||||
|
@ -151,13 +155,31 @@ export class SharingsPanel extends React.Component<Props, State, {}> {
|
||||||
this.props.update(updater().updateSharingsInfo);
|
this.props.update(updater().updateSharingsInfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
orderBy = (columnName: string) => {
|
||||||
|
updater().sortSharings(columnName);
|
||||||
|
this.props.update(updater().updateSharingsInfo);
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const orderByCallbacks = List([
|
||||||
|
() => {
|
||||||
|
this.orderBy(this.props.msg.pkg.get("item.path"));
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const orderByButtons = (
|
||||||
|
<BtnList
|
||||||
|
titleIcon="BiSortUp"
|
||||||
|
btnNames={List([this.props.msg.pkg.get("item.path")])}
|
||||||
|
btnCallbacks={orderByCallbacks}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
const sharingRows = this.makeRows(this.props.sharingsInfo.sharings);
|
const sharingRows = this.makeRows(this.props.sharingsInfo.sharings);
|
||||||
const view = (
|
const view = (
|
||||||
<Rows
|
<Rows
|
||||||
rows={sharingRows}
|
rows={sharingRows}
|
||||||
sortKeys={List([this.props.msg.pkg.get("item.path")])}
|
// sortKeys={List([this.props.msg.pkg.get("item.path")])}
|
||||||
updateRows={this.updateSharings}
|
// updateRows={this.updateSharings}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
const noSharingView = (
|
const noSharingView = (
|
||||||
|
@ -212,6 +234,7 @@ export class SharingsPanel extends React.Component<Props, State, {}> {
|
||||||
className="margin-b-l"
|
className="margin-b-l"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{orderByButtons}
|
||||||
{view}
|
{view}
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,6 +5,7 @@ import FileSize from "filesize";
|
||||||
import { RiUploadCloudFill } from "@react-icons/all-files/ri/RiUploadCloudFill";
|
import { RiUploadCloudFill } from "@react-icons/all-files/ri/RiUploadCloudFill";
|
||||||
import { RiCloudOffFill } from "@react-icons/all-files/ri/RiCloudOffFill";
|
import { RiCloudOffFill } from "@react-icons/all-files/ri/RiCloudOffFill";
|
||||||
|
|
||||||
|
import { BtnList } from "./control/btn_list";
|
||||||
import { alertMsg } from "../common/env";
|
import { alertMsg } from "../common/env";
|
||||||
import { getErrMsg } from "../common/utils";
|
import { getErrMsg } from "../common/utils";
|
||||||
import { updater } from "./state_updater";
|
import { updater } from "./state_updater";
|
||||||
|
@ -20,6 +21,8 @@ import { HotkeyHandler } from "../common/hotkeys";
|
||||||
export interface UploadingsProps {
|
export interface UploadingsProps {
|
||||||
uploadings: List<UploadEntry>;
|
uploadings: List<UploadEntry>;
|
||||||
uploadFiles: List<File>;
|
uploadFiles: List<File>;
|
||||||
|
orderBy: string;
|
||||||
|
order: boolean;
|
||||||
}
|
}
|
||||||
export interface Props {
|
export interface Props {
|
||||||
uploadingsInfo: UploadingsProps;
|
uploadingsInfo: UploadingsProps;
|
||||||
|
@ -85,8 +88,8 @@ export class UploadingsPanel extends React.Component<Props, State, {}> {
|
||||||
this.props.update(updater().updateUploadingsInfo);
|
this.props.update(updater().updateUploadingsInfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
makeRowsInputs = (uploadings: List<UploadEntry>): List<Row> => {
|
makeRowsInputs = (uploadings: List<UploadEntry>): List<React.ReactNode> => {
|
||||||
const uploadingRows = uploadings.map((uploading: UploadEntry) => {
|
return uploadings.map((uploading: UploadEntry) => {
|
||||||
const pathParts = uploading.filePath.split("/");
|
const pathParts = uploading.filePath.split("/");
|
||||||
const fileName = pathParts[pathParts.length - 1];
|
const fileName = pathParts[pathParts.length - 1];
|
||||||
const progress =
|
const progress =
|
||||||
|
@ -171,15 +174,9 @@ export class UploadingsPanel extends React.Component<Props, State, {}> {
|
||||||
);
|
);
|
||||||
|
|
||||||
// file path
|
// file path
|
||||||
const sortVals = List<string>([uploading.filePath]);
|
// const sortVals = List<string>([uploading.filePath]);
|
||||||
return {
|
return elem;
|
||||||
elem,
|
|
||||||
sortVals,
|
|
||||||
val: uploading,
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return uploadingRows;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
updateUploadings = (uploadings: Object) => {
|
updateUploadings = (uploadings: Object) => {
|
||||||
|
@ -188,16 +185,34 @@ export class UploadingsPanel extends React.Component<Props, State, {}> {
|
||||||
this.props.update(updater().updateUploadingsInfo);
|
this.props.update(updater().updateUploadingsInfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
orderBy = (columnName: string) => {
|
||||||
|
updater().sortUploadings(columnName);
|
||||||
|
this.props.update(updater().updateUploadingsInfo);
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const orderByCallbacks = List([
|
||||||
|
() => {
|
||||||
|
this.orderBy(this.props.msg.pkg.get("item.path"));
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const orderByButtons = (
|
||||||
|
<BtnList
|
||||||
|
titleIcon="BiSortUp"
|
||||||
|
btnNames={List([this.props.msg.pkg.get("item.path")])}
|
||||||
|
btnCallbacks={orderByCallbacks}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
const uploadingRows = this.makeRowsInputs(
|
const uploadingRows = this.makeRowsInputs(
|
||||||
this.props.uploadingsInfo.uploadings
|
this.props.uploadingsInfo.uploadings
|
||||||
);
|
);
|
||||||
const sortKeys = List([this.props.msg.pkg.get("item.path")]);
|
// const sortKeys = List([this.props.msg.pkg.get("item.path")]);
|
||||||
const view = (
|
const view = (
|
||||||
<Rows
|
<Rows
|
||||||
sortKeys={sortKeys}
|
// sortKeys={sortKeys}
|
||||||
rows={uploadingRows}
|
rows={uploadingRows}
|
||||||
updateRows={this.updateUploadings}
|
// updateRows={this.updateUploadings}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -254,6 +269,7 @@ export class UploadingsPanel extends React.Component<Props, State, {}> {
|
||||||
])}
|
])}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{orderByButtons}
|
||||||
{view}
|
{view}
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
|
|
|
@ -101,8 +101,6 @@ export class RootFrame extends React.Component<Props, State, {}> {
|
||||||
color: "cyan1",
|
color: "cyan1",
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
login={this.props.login}
|
|
||||||
admin={this.props.admin}
|
|
||||||
ui={this.props.ui}
|
ui={this.props.ui}
|
||||||
msg={this.props.msg}
|
msg={this.props.msg}
|
||||||
update={this.props.update}
|
update={this.props.update}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { List, Map, Set } from "immutable";
|
import { List, Map, Set } from "immutable";
|
||||||
|
|
||||||
import { ICoreState } from "./core_state";
|
import { ICoreState } from "./core_state";
|
||||||
import { getItemPath, sortRows } from "../common/utils";
|
import { getItemPath, sortRows, Row } from "../common/utils";
|
||||||
import {
|
import {
|
||||||
User,
|
User,
|
||||||
ListUsersResp,
|
ListUsersResp,
|
||||||
|
@ -241,7 +241,7 @@ export class Updater {
|
||||||
const status = await this.setItems(this.props.filesInfo.dirPath);
|
const status = await this.setItems(this.props.filesInfo.dirPath);
|
||||||
if (status !== "") {
|
if (status !== "") {
|
||||||
return status;
|
return status;
|
||||||
};
|
}
|
||||||
|
|
||||||
// TODO: this part is duplicated in the panel_files.tsx
|
// TODO: this part is duplicated in the panel_files.tsx
|
||||||
const sortKeys = List<string>([
|
const sortKeys = List<string>([
|
||||||
|
@ -865,6 +865,100 @@ export class Updater {
|
||||||
return "";
|
return "";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
setFilesOrderBy = (orderBy: string, order: boolean) => {
|
||||||
|
this.props.filesInfo.orderBy = orderBy;
|
||||||
|
this.props.filesInfo.order = order;
|
||||||
|
};
|
||||||
|
|
||||||
|
setUploadingsOrderBy = (orderBy: string, order: boolean) => {
|
||||||
|
this.props.uploadingsInfo.orderBy = orderBy;
|
||||||
|
this.props.uploadingsInfo.order = order;
|
||||||
|
};
|
||||||
|
|
||||||
|
setSharingsOrderBy = (orderBy: string, order: boolean) => {
|
||||||
|
this.props.sharingsInfo.orderBy = orderBy;
|
||||||
|
this.props.sharingsInfo.order = order;
|
||||||
|
};
|
||||||
|
|
||||||
|
sortFiles = (columnName: string) => {
|
||||||
|
let orderByKey = 0;
|
||||||
|
switch (columnName) {
|
||||||
|
case this.props.msg.pkg.get("item.name"):
|
||||||
|
orderByKey = 0;
|
||||||
|
break;
|
||||||
|
case this.props.msg.pkg.get("item.type"):
|
||||||
|
orderByKey = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
orderByKey = 2;
|
||||||
|
}
|
||||||
|
const order =
|
||||||
|
this.props.filesInfo.orderBy === columnName
|
||||||
|
? !this.props.filesInfo.order
|
||||||
|
: true;
|
||||||
|
const rows = this.props.filesInfo.items.map((item: MetadataResp): Row => {
|
||||||
|
return {
|
||||||
|
val: item,
|
||||||
|
sortVals: List([item.name, item.isDir ? "d" : "f", item.modTime]),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const sortedFiles = sortRows(rows, orderByKey, order).map(
|
||||||
|
(row): MetadataResp => {
|
||||||
|
return row.val as MetadataResp;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
this.setFilesOrderBy(columnName, order);
|
||||||
|
this.updateItems(sortedFiles);
|
||||||
|
};
|
||||||
|
|
||||||
|
sortUploadings = (columnName: string) => {
|
||||||
|
const orderByKey = 0;
|
||||||
|
const order = !this.props.uploadingsInfo.order;
|
||||||
|
const rows = this.props.uploadingsInfo.uploadings.map(
|
||||||
|
(uploading: UploadEntry): Row => {
|
||||||
|
return {
|
||||||
|
val: uploading,
|
||||||
|
sortVals: List([uploading.filePath]),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const sorted = sortRows(rows, orderByKey, order).map((row) => {
|
||||||
|
return row.val as UploadEntry;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setUploadingsOrderBy(columnName, order);
|
||||||
|
this.updateUploadings(sorted);
|
||||||
|
};
|
||||||
|
|
||||||
|
sortSharings = (columnName: string) => {
|
||||||
|
const orderByKey = 0;
|
||||||
|
const order = !this.props.sharingsInfo.order;
|
||||||
|
const rows = this.props.sharingsInfo.sharings
|
||||||
|
.keySeq()
|
||||||
|
.map((sharingPath: string): Row => {
|
||||||
|
return {
|
||||||
|
val: sharingPath,
|
||||||
|
sortVals: List([sharingPath]),
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
let sorted = Map<string, string>();
|
||||||
|
sortRows(rows, orderByKey, order).forEach((row) => {
|
||||||
|
const sharingPath = row.val as string;
|
||||||
|
sorted = sorted.set(
|
||||||
|
sharingPath,
|
||||||
|
this.props.sharingsInfo.sharings.get(sharingPath)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setSharingsOrderBy(columnName, order);
|
||||||
|
this.updateSharings(sorted);
|
||||||
|
};
|
||||||
|
|
||||||
updateAll = (prevState: ICoreState): ICoreState => {
|
updateAll = (prevState: ICoreState): ICoreState => {
|
||||||
return {
|
return {
|
||||||
filesInfo: { ...prevState.filesInfo, ...this.props.filesInfo },
|
filesInfo: { ...prevState.filesInfo, ...this.props.filesInfo },
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { BiTable } from "@react-icons/all-files/bi/BiTable";
|
||||||
import { BiListUl } from "@react-icons/all-files/bi/BiListUl";
|
import { BiListUl } from "@react-icons/all-files/bi/BiListUl";
|
||||||
import { RiMore2Fill } from "@react-icons/all-files/ri/RiMore2Fill";
|
import { RiMore2Fill } from "@react-icons/all-files/ri/RiMore2Fill";
|
||||||
import { RiCheckboxBlankLine } from "@react-icons/all-files/ri/RiCheckboxBlankLine";
|
import { RiCheckboxBlankLine } from "@react-icons/all-files/ri/RiCheckboxBlankLine";
|
||||||
|
import { BiSortUp } from "@react-icons/all-files/bi/BiSortUp";
|
||||||
|
|
||||||
import { colorClass } from "./colors";
|
import { colorClass } from "./colors";
|
||||||
|
|
||||||
|
@ -46,6 +47,7 @@ const icons = Map<string, IconType>({
|
||||||
BiListUl: BiListUl,
|
BiListUl: BiListUl,
|
||||||
RiMore2Fill: RiMore2Fill,
|
RiMore2Fill: RiMore2Fill,
|
||||||
RiCheckboxBlankLine: RiCheckboxBlankLine,
|
RiCheckboxBlankLine: RiCheckboxBlankLine,
|
||||||
|
BiSortUp: BiSortUp,
|
||||||
});
|
});
|
||||||
|
|
||||||
export function getIconWithProps(
|
export function getIconWithProps(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue