mirror of
https://github.com/filecoin-project/slate.git
synced 2024-12-23 17:12:53 +03:00
finished data view edit for list view
This commit is contained in:
parent
b140a10013
commit
2d513572f2
@ -133,6 +133,13 @@ export const processPendingFiles = async (data) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const addFileToSlate = async (data) => {
|
||||||
|
return await returnJSON(`/api/slates/add-url`, {
|
||||||
|
...DEFAULT_OPTIONS,
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const updateViewer = async (data) => {
|
export const updateViewer = async (data) => {
|
||||||
return await returnJSON(`/api/users/update`, {
|
return await returnJSON(`/api/users/update`, {
|
||||||
...DEFAULT_OPTIONS,
|
...DEFAULT_OPTIONS,
|
||||||
|
@ -29,6 +29,7 @@ export const system = {
|
|||||||
slate: "#27292e",
|
slate: "#27292e",
|
||||||
moonstone: "#807d78",
|
moonstone: "#807d78",
|
||||||
wall: "#cfced3",
|
wall: "#cfced3",
|
||||||
|
shadow: "rgba(15, 14, 18, 0.03)",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const zindex = {
|
export const zindex = {
|
||||||
|
@ -37,6 +37,26 @@ export const Directory = (props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const PlusCircle = (props) => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
height={props.height}
|
||||||
|
style={props.style}
|
||||||
|
>
|
||||||
|
<path d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z" />
|
||||||
|
<path d="M12 8V16" />
|
||||||
|
<path d="M8 12H16" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const Users = (props) => {
|
export const Users = (props) => {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
@ -915,6 +935,21 @@ export const Plus = (props) => (
|
|||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const Minus = (props) => (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<path d="M5 12H19" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
export const FilecoinLogo = (props) => (
|
export const FilecoinLogo = (props) => (
|
||||||
<svg
|
<svg
|
||||||
viewBox="0 0 127 127"
|
viewBox="0 0 127 127"
|
||||||
|
@ -75,16 +75,6 @@ export const slatename = (text) => {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const email = (text) => {
|
|
||||||
if (!text || !text.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!EMAIL_REGEX.test(text)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const username = (text) => {
|
export const username = (text) => {
|
||||||
if (Strings.isEmpty(text)) {
|
if (Strings.isEmpty(text)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -39,6 +39,7 @@ import SidebarCreateWalletAddress from "~/components/sidebars/SidebarCreateWalle
|
|||||||
import SidebarWalletSendFunds from "~/components/sidebars/SidebarWalletSendFunds";
|
import SidebarWalletSendFunds from "~/components/sidebars/SidebarWalletSendFunds";
|
||||||
import SidebarFileStorageDeal from "~/components/sidebars/SidebarFileStorageDeal";
|
import SidebarFileStorageDeal from "~/components/sidebars/SidebarFileStorageDeal";
|
||||||
import SidebarAddFileToBucket from "~/components/sidebars/SidebarAddFileToBucket";
|
import SidebarAddFileToBucket from "~/components/sidebars/SidebarAddFileToBucket";
|
||||||
|
import SidebarAddFileToSlate from "~/components/sidebars/SidebarAddFileToSlate";
|
||||||
import SidebarDragDropNotice from "~/components/sidebars/SidebarDragDropNotice";
|
import SidebarDragDropNotice from "~/components/sidebars/SidebarDragDropNotice";
|
||||||
import SidebarSingleSlateSettings from "~/components/sidebars/SidebarSingleSlateSettings";
|
import SidebarSingleSlateSettings from "~/components/sidebars/SidebarSingleSlateSettings";
|
||||||
import SidebarFilecoinArchive from "~/components/sidebars/SidebarFilecoinArchive";
|
import SidebarFilecoinArchive from "~/components/sidebars/SidebarFilecoinArchive";
|
||||||
@ -64,6 +65,7 @@ const SIDEBARS = {
|
|||||||
SIDEBAR_WALLET_SEND_FUNDS: <SidebarWalletSendFunds />,
|
SIDEBAR_WALLET_SEND_FUNDS: <SidebarWalletSendFunds />,
|
||||||
SIDEBAR_CREATE_WALLET_ADDRESS: <SidebarCreateWalletAddress />,
|
SIDEBAR_CREATE_WALLET_ADDRESS: <SidebarCreateWalletAddress />,
|
||||||
SIDEBAR_ADD_FILE_TO_BUCKET: <SidebarAddFileToBucket />,
|
SIDEBAR_ADD_FILE_TO_BUCKET: <SidebarAddFileToBucket />,
|
||||||
|
SIDEBAR_ADD_FILE_TO_SLATE: <SidebarAddFileToSlate />,
|
||||||
SIDEBAR_CREATE_SLATE: <SidebarCreateSlate />,
|
SIDEBAR_CREATE_SLATE: <SidebarCreateSlate />,
|
||||||
SIDEBAR_DRAG_DROP_NOTICE: <SidebarDragDropNotice />,
|
SIDEBAR_DRAG_DROP_NOTICE: <SidebarDragDropNotice />,
|
||||||
SIDEBAR_SINGLE_SLATE_SETTINGS: <SidebarSingleSlateSettings />,
|
SIDEBAR_SINGLE_SLATE_SETTINGS: <SidebarSingleSlateSettings />,
|
||||||
@ -104,6 +106,7 @@ export default class ApplicationPage extends React.Component {
|
|||||||
sidebar: null,
|
sidebar: null,
|
||||||
sidebarLoading: false,
|
sidebarLoading: false,
|
||||||
online: null,
|
online: null,
|
||||||
|
sidebar: <SidebarAddFileToSlate />, //remove this
|
||||||
};
|
};
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
@ -743,6 +746,7 @@ export default class ApplicationPage extends React.Component {
|
|||||||
selected: this.state.selected,
|
selected: this.state.selected,
|
||||||
viewer: this.state.viewer,
|
viewer: this.state.viewer,
|
||||||
data: this.state.data,
|
data: this.state.data,
|
||||||
|
sidebarData: this.state.sidebarData,
|
||||||
fileLoading: this.state.fileLoading,
|
fileLoading: this.state.fileLoading,
|
||||||
sidebarLoading: this.state.sidebarLoading,
|
sidebarLoading: this.state.sidebarLoading,
|
||||||
onSelectedChange: this._handleSelectedChange,
|
onSelectedChange: this._handleSelectedChange,
|
||||||
|
@ -164,7 +164,7 @@ export default class ApplicationUserControls extends React.Component {
|
|||||||
<Boundary
|
<Boundary
|
||||||
captureResize={true}
|
captureResize={true}
|
||||||
captureScroll={false}
|
captureScroll={false}
|
||||||
enabled={this.state.visible}
|
enabled
|
||||||
onOutsideRectEvent={this._handleHide}
|
onOutsideRectEvent={this._handleHide}
|
||||||
style={this.props.style}
|
style={this.props.style}
|
||||||
>
|
>
|
||||||
|
@ -10,7 +10,8 @@ const MAX_IN_BYTES = 10737418240 * 4;
|
|||||||
|
|
||||||
const STYLES_CONTAINER = css`
|
const STYLES_CONTAINER = css`
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border: 1px solid ${Constants.system.border};
|
box-shadow: 0 0 0 1px rgba(229, 229, 229, 0.75) inset,
|
||||||
|
0 0 40px 0 ${Constants.system.shadow};
|
||||||
padding: 32px;
|
padding: 32px;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -14,7 +14,10 @@ import { generateLayout } from "~/components/core/Slate";
|
|||||||
import { CheckBox } from "~/components/system/components/CheckBox";
|
import { CheckBox } from "~/components/system/components/CheckBox";
|
||||||
import { Table } from "~/components/core/Table";
|
import { Table } from "~/components/core/Table";
|
||||||
import { FileTypeIcon } from "~/components/core/FileTypeIcon";
|
import { FileTypeIcon } from "~/components/core/FileTypeIcon";
|
||||||
import { ButtonWarning } from "~/components/system/components/Buttons";
|
import {
|
||||||
|
ButtonPrimary,
|
||||||
|
ButtonWarning,
|
||||||
|
} from "~/components/system/components/Buttons";
|
||||||
import { TabGroup } from "~/components/core/TabGroup";
|
import { TabGroup } from "~/components/core/TabGroup";
|
||||||
|
|
||||||
import SlateMediaObject from "~/components/core/SlateMediaObject";
|
import SlateMediaObject from "~/components/core/SlateMediaObject";
|
||||||
@ -40,11 +43,22 @@ const STYLES_ICON_BOX = css`
|
|||||||
margin-left: 16px;
|
margin-left: 16px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const STYLES_CANCEL_BOX = css`
|
||||||
|
height: 16px;
|
||||||
|
width: 16px;
|
||||||
|
background-color: ${Constants.system.brand};
|
||||||
|
border-radius: 3px;
|
||||||
|
position: relative;
|
||||||
|
right: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 0 0 0 1px ${Constants.system.brand};
|
||||||
|
`;
|
||||||
|
|
||||||
const STYLES_HEADER_LINE = css`
|
const STYLES_HEADER_LINE = css`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-top: 80px;
|
margin-top: 80px;
|
||||||
margin-bottom: 42px;
|
margin-bottom: 30px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_LINK = css`
|
const STYLES_LINK = css`
|
||||||
@ -77,7 +91,25 @@ const STYLES_ICON_BOX_HOVER = css`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_ACTION_ROW = css`
|
const STYLES_ARROWS = css`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const STYLES_ACTION_BAR = css`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
box-shadow: 0 0 0 1px rgba(229, 229, 229, 0.75) inset,
|
||||||
|
0 0 40px 0 ${Constants.system.shadow};
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 12px 32px;
|
||||||
|
background-color: rgba(248, 248, 248, 0.75);
|
||||||
|
`;
|
||||||
|
|
||||||
|
const STYLES_RIGHT = css`
|
||||||
|
flex-shrink: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
`;
|
`;
|
||||||
@ -87,8 +119,8 @@ const STYLES_LEFT = css`
|
|||||||
min-width: 10%;
|
min-width: 10%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_RIGHT = css`
|
const STYLES_FILES_SELECTED = css`
|
||||||
flex-shrink: 0;
|
font-family: ${Constants.font.semiBold};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_ICON_ELEMENT = css`
|
const STYLES_ICON_ELEMENT = css`
|
||||||
@ -120,10 +152,8 @@ const STYLES_COPY_INPUT = css`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_IMAGE_GRID = css`
|
const STYLES_IMAGE_GRID = css`
|
||||||
display: flex;
|
display: grid;
|
||||||
flex-direction: row;
|
grid-template-columns: repeat(auto-fit, minmax(214px, 1fr));
|
||||||
justify-content: space-between;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin: 0 -27px;
|
margin: 0 -27px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -134,7 +164,8 @@ const STYLES_IMAGE_BOX = css`
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
box-shadow: 0px 0px 0px 1px rgba(229, 229, 229, 0.5) inset;
|
box-shadow: 0px 0px 0px 1px rgba(229, 229, 229, 0.75) inset,
|
||||||
|
0 0 40px 0 ${Constants.system.shadow};
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -165,6 +196,7 @@ export default class DataView extends React.Component {
|
|||||||
"remote-slate-object-add",
|
"remote-slate-object-add",
|
||||||
this._handleRemoteSlateObjectAdd
|
this._handleRemoteSlateObjectAdd
|
||||||
);
|
);
|
||||||
|
window.addEventListener("remote-update-carousel", this._handleUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
await this._handleUpdate();
|
await this._handleUpdate();
|
||||||
@ -185,6 +217,7 @@ export default class DataView extends React.Component {
|
|||||||
"remote-slate-object-add",
|
"remote-slate-object-add",
|
||||||
this._handleRemoteSlateObjectAdd
|
this._handleRemoteSlateObjectAdd
|
||||||
);
|
);
|
||||||
|
window.removeEventListener("remote-update-carousel", this._handleUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
_increment = (direction) => {
|
_increment = (direction) => {
|
||||||
@ -218,9 +251,8 @@ export default class DataView extends React.Component {
|
|||||||
if (!window.confirm(message)) {
|
if (!window.confirm(message)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log(this.state.checked);
|
|
||||||
let cids = Object.keys(this.state.checked).map((id) => {
|
let cids = Object.keys(this.state.checked).map((id) => {
|
||||||
let index = parseInt(id.replace("checkbox-", ""));
|
let index = parseInt(id);
|
||||||
return this.props.viewer.library[0].children[index].ipfs.replace(
|
return this.props.viewer.library[0].children[index].ipfs.replace(
|
||||||
"/ipfs/",
|
"/ipfs/",
|
||||||
""
|
""
|
||||||
@ -372,13 +404,9 @@ export default class DataView extends React.Component {
|
|||||||
detail: { loading: { id: slate.id } },
|
detail: { loading: { id: slate.id } },
|
||||||
});
|
});
|
||||||
|
|
||||||
const addResponse = await fetch(`/api/slates/add-url`, {
|
const addResponse = await Actions.addFileToSlate({
|
||||||
method: "POST",
|
slate,
|
||||||
headers: {
|
data: [{ title: data.name, ...data }],
|
||||||
Accept: "application/json",
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({ slate, data: [{ title: data.name, ...data }] }),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!addResponse) {
|
if (!addResponse) {
|
||||||
@ -491,10 +519,6 @@ export default class DataView extends React.Component {
|
|||||||
this.setState({ menu: null });
|
this.setState({ menu: null });
|
||||||
};
|
};
|
||||||
|
|
||||||
_handleRemoteDeletion = async (e) => {
|
|
||||||
await this._handleDelete(e.detail.cid);
|
|
||||||
};
|
|
||||||
|
|
||||||
_handleLoading = ({ cids }) => {
|
_handleLoading = ({ cids }) => {
|
||||||
let loading = this.state.loading;
|
let loading = this.state.loading;
|
||||||
for (let cid of cids) {
|
for (let cid of cids) {
|
||||||
@ -511,6 +535,23 @@ export default class DataView extends React.Component {
|
|||||||
this.setState({ [e.target.name]: e.target.value });
|
this.setState({ [e.target.name]: e.target.value });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_handleAddToSlate = (e) => {
|
||||||
|
let userFiles = this.props.viewer.library[0].children;
|
||||||
|
let files = Object.keys(this.state.checked).map(
|
||||||
|
(index) => userFiles[index]
|
||||||
|
);
|
||||||
|
this.props.onAction({
|
||||||
|
type: "SIDEBAR",
|
||||||
|
value: "SIDEBAR_ADD_FILE_TO_SLATE",
|
||||||
|
data: { files },
|
||||||
|
});
|
||||||
|
this._handleUncheckAll();
|
||||||
|
};
|
||||||
|
|
||||||
|
_handleUncheckAll = () => {
|
||||||
|
this.setState({ checked: {} });
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const header = (
|
const header = (
|
||||||
<div css={STYLES_HEADER_LINE}>
|
<div css={STYLES_HEADER_LINE}>
|
||||||
@ -552,25 +593,8 @@ export default class DataView extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
const footer = (
|
const footer = (
|
||||||
<div css={STYLES_ACTION_ROW}>
|
<React.Fragment>
|
||||||
<div css={STYLES_LEFT}>
|
<div css={STYLES_ARROWS}>
|
||||||
{Object.keys(this.state.checked).length ? (
|
|
||||||
<ButtonWarning
|
|
||||||
style={{ width: 160 }}
|
|
||||||
onClick={this._handleDeleteFiles}
|
|
||||||
loading={
|
|
||||||
this.state.loading &&
|
|
||||||
Object.values(this.state.loading).some((elem) => {
|
|
||||||
return !!elem;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Delete {Object.keys(this.state.checked).length} file
|
|
||||||
{Object.keys(this.state.checked).length > 1 ? "s" : ""}
|
|
||||||
</ButtonWarning>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
<div css={STYLES_RIGHT}>
|
|
||||||
<span
|
<span
|
||||||
css={STYLES_ICON_ELEMENT}
|
css={STYLES_ICON_ELEMENT}
|
||||||
style={
|
style={
|
||||||
@ -604,7 +628,33 @@ export default class DataView extends React.Component {
|
|||||||
<SVG.NavigationArrow height="24px" />
|
<SVG.NavigationArrow height="24px" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{Object.keys(this.state.checked).length ? (
|
||||||
|
<div css={STYLES_ACTION_BAR}>
|
||||||
|
<div css={STYLES_LEFT}>
|
||||||
|
<span css={STYLES_FILES_SELECTED}>
|
||||||
|
{Object.keys(this.state.checked).length} files selected
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div css={STYLES_RIGHT}>
|
||||||
|
<ButtonPrimary transparent onClick={this._handleAddToSlate}>
|
||||||
|
Add to slate
|
||||||
|
</ButtonPrimary>
|
||||||
|
<ButtonWarning
|
||||||
|
transparent
|
||||||
|
onClick={this._handleDeleteFiles}
|
||||||
|
loading={
|
||||||
|
this.state.loading &&
|
||||||
|
Object.values(this.state.loading).some((elem) => {
|
||||||
|
return !!elem;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Delete files
|
||||||
|
</ButtonWarning>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
if (this.state.view === "grid") {
|
if (this.state.view === "grid") {
|
||||||
return (
|
return (
|
||||||
@ -640,7 +690,19 @@ export default class DataView extends React.Component {
|
|||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
key: "checkbox",
|
key: "checkbox",
|
||||||
name: <span />,
|
name: Object.keys(this.state.checked).length ? (
|
||||||
|
<div
|
||||||
|
css={STYLES_CANCEL_BOX}
|
||||||
|
onClick={() => this.setState({ checked: {} })}
|
||||||
|
>
|
||||||
|
<SVG.Minus
|
||||||
|
height="16px"
|
||||||
|
style={{ color: Constants.system.white }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<span />
|
||||||
|
),
|
||||||
width: "24px",
|
width: "24px",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -667,7 +729,7 @@ export default class DataView extends React.Component {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...each,
|
...each,
|
||||||
checkbox: this._handleCheckBox ? (
|
checkbox: (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
margin: "12px 0",
|
margin: "12px 0",
|
||||||
@ -680,19 +742,13 @@ export default class DataView extends React.Component {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CheckBox
|
<CheckBox
|
||||||
name={`checkbox-${this.state.startIndex + index}`}
|
name={this.state.startIndex + index}
|
||||||
value={
|
value={!!this.state.checked[this.state.startIndex + index]}
|
||||||
!!this.state.checked[
|
|
||||||
`checkbox-${this.state.startIndex + index}`
|
|
||||||
]
|
|
||||||
}
|
|
||||||
onChange={this._handleCheckBox}
|
onChange={this._handleCheckBox}
|
||||||
boxStyle={{ height: 16, width: 16 }}
|
boxStyle={{ height: 16, width: 16 }}
|
||||||
style={{ position: "relative", right: 3 }}
|
style={{ position: "relative", right: 3 }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
|
||||||
<div />
|
|
||||||
),
|
),
|
||||||
name: (
|
name: (
|
||||||
<div
|
<div
|
||||||
|
@ -8,7 +8,7 @@ import { css } from "@emotion/react";
|
|||||||
const STYLES_EMPTY_STATE = css`
|
const STYLES_EMPTY_STATE = css`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 328px;
|
height: 328px;
|
||||||
border: 1px solid ${Constants.system.border};
|
border: 1px solid rgba(229, 229, 229, 0.75);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -37,7 +37,7 @@ const STYLES_DROPDOWN_ITEM = css`
|
|||||||
margin-bottom: -1px;
|
margin-bottom: -1px;
|
||||||
|
|
||||||
:hover {
|
:hover {
|
||||||
border-color: ${Constants.system.border} !important;
|
border-color: rgba(229, 229, 229, 0.75) !important;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -205,7 +205,7 @@ export class SearchDropdown extends React.Component {
|
|||||||
style={{
|
style={{
|
||||||
borderColor:
|
borderColor:
|
||||||
this.state.selectedIndex === i
|
this.state.selectedIndex === i
|
||||||
? Constants.system.border
|
? "rgba(229, 229, 229, 0.75)"
|
||||||
: "transparent",
|
: "transparent",
|
||||||
...this.props.itemStyle,
|
...this.props.itemStyle,
|
||||||
}}
|
}}
|
||||||
|
@ -11,6 +11,22 @@ import { dispatchCustomEvent } from "~/common/custom-events";
|
|||||||
|
|
||||||
import SlateMediaObjectPreview from "~/components/core/SlateMediaObjectPreview";
|
import SlateMediaObjectPreview from "~/components/core/SlateMediaObjectPreview";
|
||||||
|
|
||||||
|
const STYLES_CREATE_NEW = css`
|
||||||
|
color: ${Constants.system.darkGray};
|
||||||
|
box-shadow: 0px 0px 0px 1px rgba(229, 229, 229, 0.5) inset;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 160px;
|
||||||
|
height: 160px;
|
||||||
|
margin: 0px 12px;
|
||||||
|
|
||||||
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
|
margin: 0 8px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const STYLES_IMAGE_ROW = css`
|
const STYLES_IMAGE_ROW = css`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@ -18,9 +34,11 @@ const STYLES_IMAGE_ROW = css`
|
|||||||
height: 160px;
|
height: 160px;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
margin: 0 -12px;
|
||||||
|
|
||||||
@media (max-width: ${Constants.sizes.mobile}px) {
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
margin: 0 -8px;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -35,19 +53,21 @@ const STYLES_ITEM_BOX = css`
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
@media (max-width: ${Constants.sizes.mobile}px) {
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
margin: 0 auto;
|
margin: 0 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:hover {
|
:hover {
|
||||||
color: ${Constants.system.brand};
|
color: ${Constants.system.brand};
|
||||||
}
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
:first-of-type {
|
const STYLES_EMPTY_BOX = css`
|
||||||
margin-left: 0px;
|
width: 160px;
|
||||||
}
|
height: 160px;
|
||||||
|
margin: 0px 12px;
|
||||||
|
|
||||||
:last-of-type {
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
margin-right: 0px;
|
margin: 0 8px;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -57,6 +77,7 @@ const STYLES_IMAGE_ROW_SMALL = css`
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
height: 56px;
|
height: 56px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
margin: 0 -8px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_ITEM_BOX_SMALL = css`
|
const STYLES_ITEM_BOX_SMALL = css`
|
||||||
@ -67,49 +88,72 @@ const STYLES_ITEM_BOX_SMALL = css`
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
box-shadow: 0px 0px 0px 1px rgba(229, 229, 229, 0.5) inset;
|
box-shadow: 0px 0px 0px 1px rgba(229, 229, 229, 0.5) inset;
|
||||||
|
`;
|
||||||
|
|
||||||
:first-of-type {
|
const STYLES_EMPTY_BOX_SMALL = css`
|
||||||
margin-left: 0px;
|
width: 56px;
|
||||||
}
|
height: 56px;
|
||||||
|
margin: 0px 8px;
|
||||||
:last-of-type {
|
|
||||||
margin-right: 0px;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export function SlatePreviewRow(props) {
|
export function SlatePreviewRow(props) {
|
||||||
let numItems = props.numItems || 5;
|
let numItems = props.numItems || 5;
|
||||||
let objects =
|
let objects;
|
||||||
props.slate.data.objects.length > numItems
|
if (props.slate.data.objects.length === 0) {
|
||||||
? props.slate.data.objects.slice(0, numItems)
|
objects = [
|
||||||
: props.slate.data.objects;
|
<div css={STYLES_CREATE_NEW} key="add-files">
|
||||||
|
<SVG.Plus height="24px" />
|
||||||
|
<div>Add Files</div>
|
||||||
|
</div>,
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
let trimmed =
|
||||||
|
props.slate.data.objects.length > numItems
|
||||||
|
? props.slate.data.objects.slice(0, numItems)
|
||||||
|
: props.slate.data.objects;
|
||||||
|
objects = trimmed.map((each) => (
|
||||||
|
<div
|
||||||
|
key={each.id}
|
||||||
|
css={props.small ? STYLES_ITEM_BOX_SMALL : STYLES_ITEM_BOX}
|
||||||
|
style={props.style}
|
||||||
|
>
|
||||||
|
<SlateMediaObjectPreview
|
||||||
|
charCap={30}
|
||||||
|
type={each.type}
|
||||||
|
url={each.url}
|
||||||
|
style={{ border: "none", ...props.previewStyle }}
|
||||||
|
title={each.title || each.name}
|
||||||
|
small={props.small}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let numExtra = props.numItems
|
||||||
|
? props.numItems - objects.length
|
||||||
|
: 5 - objects.length;
|
||||||
|
let extra = [];
|
||||||
|
for (let i = 0; i < numExtra; i++) {
|
||||||
|
extra.push(
|
||||||
|
<div
|
||||||
|
key={`extra-${i}`}
|
||||||
|
css={props.small ? STYLES_EMPTY_BOX_SMALL : STYLES_EMPTY_BOX}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
css={props.small ? STYLES_IMAGE_ROW_SMALL : STYLES_IMAGE_ROW}
|
css={props.small ? STYLES_IMAGE_ROW_SMALL : STYLES_IMAGE_ROW}
|
||||||
style={props.containerStyle}
|
style={props.containerStyle}
|
||||||
>
|
>
|
||||||
{objects.map((each) => (
|
{objects}
|
||||||
<div
|
{extra}
|
||||||
key={each.id}
|
|
||||||
css={props.small ? STYLES_ITEM_BOX_SMALL : STYLES_ITEM_BOX}
|
|
||||||
style={props.style}
|
|
||||||
>
|
|
||||||
<SlateMediaObjectPreview
|
|
||||||
charCap={30}
|
|
||||||
type={each.type}
|
|
||||||
url={each.url}
|
|
||||||
style={{ border: "none", ...props.previewStyle }}
|
|
||||||
title={each.title || each.name}
|
|
||||||
small={props.small}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const STYLES_BLOCK = css`
|
const STYLES_BLOCK = css`
|
||||||
box-shadow: 0 0 0 1px ${Constants.system.border} inset;
|
box-shadow: 0 0 0 1px rgba(229, 229, 229, 0.75) inset,
|
||||||
|
0 0 40px 0 ${Constants.system.shadow};
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: 32px 40px;
|
padding: 32px 40px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@ -153,17 +197,6 @@ const STYLES_BODY = css`
|
|||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_CREATE_NEW = css`
|
|
||||||
color: ${Constants.system.darkGray};
|
|
||||||
box-shadow: 0px 0px 0px 1px rgba(229, 229, 229, 0.5) inset;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 160px;
|
|
||||||
height: 160px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const STYLES_ICON_BOX = css`
|
const STYLES_ICON_BOX = css`
|
||||||
height: 32px;
|
height: 32px;
|
||||||
width: 32px;
|
width: 32px;
|
||||||
@ -354,20 +387,10 @@ export default class SlatePreviewBlock extends React.Component {
|
|||||||
) : (
|
) : (
|
||||||
<div style={{ height: "8px" }} />
|
<div style={{ height: "8px" }} />
|
||||||
)}
|
)}
|
||||||
{this.props.slate.data.objects &&
|
<SlatePreviewRow
|
||||||
this.props.slate.data.objects.length ? (
|
{...this.props}
|
||||||
<SlatePreviewRow
|
previewStyle={this.props.previewStyle}
|
||||||
{...this.props}
|
/>
|
||||||
previewStyle={this.props.previewStyle}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div css={STYLES_IMAGE_ROW}>
|
|
||||||
<div css={STYLES_CREATE_NEW}>
|
|
||||||
<SVG.Plus height="24px" />
|
|
||||||
<div>Add Files</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ const TABLE_COLUMN_WIDTH_DEFAULTS = {
|
|||||||
|
|
||||||
const STYLES_CONTAINER = css`
|
const STYLES_CONTAINER = css`
|
||||||
border: 1px solid rgba(229, 229, 229, 0.75);
|
border: 1px solid rgba(229, 229, 229, 0.75);
|
||||||
|
box-shadow: 0 0 40px 0 ${Constants.system.shadow};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_TABLE_ROW = css`
|
const STYLES_TABLE_ROW = css`
|
||||||
|
180
components/sidebars/SidebarAddFileToSlate.js
Normal file
180
components/sidebars/SidebarAddFileToSlate.js
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import * as Strings from "~/common/strings";
|
||||||
|
import * as Constants from "~/common/constants";
|
||||||
|
import * as System from "~/components/system";
|
||||||
|
import * as Validations from "~/common/validations";
|
||||||
|
import * as SVG from "~/common/svg";
|
||||||
|
import * as Actions from "~/common/actions";
|
||||||
|
|
||||||
|
import { dispatchCustomEvent } from "~/common/custom-events";
|
||||||
|
import { css } from "@emotion/react";
|
||||||
|
import { ButtonPrimary } from "~/components/system/components/Buttons";
|
||||||
|
|
||||||
|
const STYLES_SLATE_NAME = css`
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
font-family: ${Constants.font.medium};
|
||||||
|
`;
|
||||||
|
|
||||||
|
const STYLES_HEADER = css`
|
||||||
|
font-family: ${Constants.font.semiBold};
|
||||||
|
font-size: 18px;
|
||||||
|
margin-top: 32px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const STYLES_SLATE_LIST = css`
|
||||||
|
max-height: 400px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const STYLES_SLATE_LINE = css`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px 16px;
|
||||||
|
background-color: ${Constants.system.white};
|
||||||
|
margin-bottom: 1px;
|
||||||
|
cursor: pointer;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const STYLES_ICON_BOX = css`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default class SidebarAddFileToSlate extends React.Component {
|
||||||
|
state = {
|
||||||
|
selected: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
_handleCreateSlate = async () => {
|
||||||
|
if (
|
||||||
|
Object.values(this.state.selected).some((value) => {
|
||||||
|
return !!value;
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
await this._handleSubmit();
|
||||||
|
}
|
||||||
|
await this.props.onCancel();
|
||||||
|
this.props.onAction({
|
||||||
|
type: "SIDEBAR",
|
||||||
|
value: "SIDEBAR_CREATE_SLATE",
|
||||||
|
data: this.props.sidebarData,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
_handleAdd = (slate) => {
|
||||||
|
if (this.state.selected[slate.id]) {
|
||||||
|
this.setState({
|
||||||
|
selected: { ...this.state.selected, [slate.id]: false },
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
selected: { ...this.state.selected, [slate.id]: slate },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_handleSubmit = async () => {
|
||||||
|
let data = this.props.sidebarData.files.map((file) => {
|
||||||
|
return { title: file.name, ...file };
|
||||||
|
});
|
||||||
|
for (let slate of Object.values(this.state.selected)) {
|
||||||
|
if (!slate) continue;
|
||||||
|
const addResponse = await Actions.addFileToSlate({ slate, data });
|
||||||
|
|
||||||
|
if (!addResponse) {
|
||||||
|
dispatchCustomEvent({
|
||||||
|
name: "create-alert",
|
||||||
|
detail: {
|
||||||
|
alert: {
|
||||||
|
message:
|
||||||
|
"We're having trouble connecting right now. Please try again later",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
} else if (addResponse.error) {
|
||||||
|
dispatchCustomEvent({
|
||||||
|
name: "create-alert",
|
||||||
|
detail: { alert: { decorator: addResponse.decorator } },
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await this.props.onRehydrate();
|
||||||
|
dispatchCustomEvent({
|
||||||
|
name: "remote-update-carousel",
|
||||||
|
detail: null,
|
||||||
|
});
|
||||||
|
this.props.onCancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<System.P
|
||||||
|
style={{
|
||||||
|
fontFamily: Constants.font.semiBold,
|
||||||
|
fontSize: Constants.typescale.lvl3,
|
||||||
|
marginBottom: "64px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Add files to slate
|
||||||
|
</System.P>
|
||||||
|
|
||||||
|
<System.P css={STYLES_HEADER}>Slates</System.P>
|
||||||
|
<div
|
||||||
|
css={STYLES_SLATE_LINE}
|
||||||
|
style={{ marginBottom: 32 }}
|
||||||
|
onClick={this._handleCreateSlate}
|
||||||
|
>
|
||||||
|
<SVG.Plus
|
||||||
|
height="24px"
|
||||||
|
style={{ color: Constants.system.brand, marginRight: 8 }}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
css={STYLES_SLATE_NAME}
|
||||||
|
style={{ color: Constants.system.brand }}
|
||||||
|
>
|
||||||
|
Create new slate
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div css={STYLES_SLATE_LIST}>
|
||||||
|
{this.props.viewer.slates.map((slate) => (
|
||||||
|
<div css={STYLES_SLATE_LINE} onClick={() => this._handleAdd(slate)}>
|
||||||
|
<div css={STYLES_ICON_BOX}>
|
||||||
|
{this.state.selected[slate.id] ? (
|
||||||
|
<SVG.Slate height="24px" style={{ marginRight: 8 }} />
|
||||||
|
) : (
|
||||||
|
<SVG.PlusCircle
|
||||||
|
height="24px"
|
||||||
|
style={{ color: Constants.system.darkGray, marginRight: 8 }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
css={STYLES_SLATE_NAME}
|
||||||
|
style={
|
||||||
|
this.state.selected[slate.id]
|
||||||
|
? null
|
||||||
|
: { color: Constants.system.darkGray }
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{slate.data.name || slate.slatename}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<ButtonPrimary
|
||||||
|
full
|
||||||
|
onClick={this._handleSubmit}
|
||||||
|
style={{ marginTop: 32 }}
|
||||||
|
>
|
||||||
|
Add to slates
|
||||||
|
</ButtonPrimary>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@ import * as Strings from "~/common/strings";
|
|||||||
import * as Constants from "~/common/constants";
|
import * as Constants from "~/common/constants";
|
||||||
import * as System from "~/components/system";
|
import * as System from "~/components/system";
|
||||||
import * as Validations from "~/common/validations";
|
import * as Validations from "~/common/validations";
|
||||||
|
import * as Actions from "~/common/actions";
|
||||||
|
|
||||||
import { dispatchCustomEvent } from "~/common/custom-events";
|
import { dispatchCustomEvent } from "~/common/custom-events";
|
||||||
import { css } from "@emotion/react";
|
import { css } from "@emotion/react";
|
||||||
@ -87,6 +88,48 @@ export default class SidebarCreateSlate extends React.Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.props.sidebarData &&
|
||||||
|
this.props.sidebarData.files &&
|
||||||
|
this.props.sidebarData.files[0].decorator === "FILE"
|
||||||
|
) {
|
||||||
|
let data = this.props.sidebarData.files.map((file) => {
|
||||||
|
return { title: file.name, ...file };
|
||||||
|
});
|
||||||
|
const addResponse = await Actions.addFileToSlate({
|
||||||
|
slate: response.slate,
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!addResponse) {
|
||||||
|
dispatchCustomEvent({
|
||||||
|
name: "create-alert",
|
||||||
|
detail: {
|
||||||
|
alert: {
|
||||||
|
message:
|
||||||
|
"We're having trouble connecting right now. Please try again later",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addResponse.error) {
|
||||||
|
dispatchCustomEvent({
|
||||||
|
name: "create-alert",
|
||||||
|
detail: { alert: { decorator: response.decorator } },
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.props.onRehydrate();
|
||||||
|
|
||||||
|
dispatchCustomEvent({
|
||||||
|
name: "remote-update-carousel",
|
||||||
|
detail: null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({ loading: false });
|
this.setState({ loading: false });
|
||||||
this.props.onAction({
|
this.props.onAction({
|
||||||
type: "NAVIGATE",
|
type: "NAVIGATE",
|
||||||
|
@ -28,7 +28,7 @@ export default class SidebarCreateSlate extends React.Component {
|
|||||||
|
|
||||||
_handleSubmit = async () => {
|
_handleSubmit = async () => {
|
||||||
this.setState({ loading: true });
|
this.setState({ loading: true });
|
||||||
if (!this.state.email || !this.state.email.length) {
|
if (Strings.isEmpty(this.state.email)) {
|
||||||
dispatchCustomEvent({
|
dispatchCustomEvent({
|
||||||
name: "create-alert",
|
name: "create-alert",
|
||||||
detail: {
|
detail: {
|
||||||
@ -54,17 +54,6 @@ export default class SidebarCreateSlate extends React.Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Validations.email(this.state.email)) {
|
|
||||||
dispatchCustomEvent({
|
|
||||||
name: "create-alert",
|
|
||||||
detail: {
|
|
||||||
alert: { message: "Please check that your email address is valid" },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
this.setState({ loading: false });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await Actions.createSupportMessage({
|
const response = await Actions.createSupportMessage({
|
||||||
username: this.props.viewer.username,
|
username: this.props.viewer.username,
|
||||||
name: this.state.name,
|
name: this.state.name,
|
||||||
|
@ -11,32 +11,13 @@ const STYLES_BUTTON = `
|
|||||||
outline: 0;
|
outline: 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
min-height: 40px;
|
min-height: 40px;
|
||||||
padding: 6px 24px 6px 24px;
|
padding: 4px 16px;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
font-size: 12px;
|
font-size: 14px;
|
||||||
letter-spacing: 0.2px;
|
letter-spacing: 0.2px;
|
||||||
font-family: ${Constants.font.semiBold};
|
font-family: ${Constants.font.medium};
|
||||||
transition: 200ms ease all;
|
|
||||||
overflow-wrap: break-word;
|
|
||||||
user-select: none;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const STYLES_BUTTON_FULL = `
|
|
||||||
box-sizing: border-box;
|
|
||||||
border-radius: 4px;
|
|
||||||
outline: 0;
|
|
||||||
border: 0;
|
|
||||||
min-height: 40px;
|
|
||||||
padding: 6px 24px 6px 24px;
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
font-size: 12px;
|
|
||||||
letter-spacing: 0.2px;
|
|
||||||
font-family: ${Constants.font.semiBold};
|
|
||||||
transition: 200ms ease all;
|
transition: 200ms ease all;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
@ -60,30 +41,25 @@ const STYLES_BUTTON_PRIMARY = css`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_BUTTON_PRIMARY_FULL = css`
|
const STYLES_BUTTON_PRIMARY_TRANSPARENT = css`
|
||||||
${STYLES_BUTTON_FULL}
|
${STYLES_BUTTON}
|
||||||
|
${"" /* font-size: 16px;
|
||||||
|
font-family: ${Constants.font.medium}; */}
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: ${Constants.system.brand};
|
background-color: transparent;
|
||||||
color: ${Constants.system.white};
|
color: ${Constants.system.brand};
|
||||||
|
|
||||||
:hover {
|
|
||||||
background-color: #065ca8;
|
|
||||||
}
|
|
||||||
|
|
||||||
:focus {
|
|
||||||
box-shadow: inset 0 0 5px 2px rgba(0, 0, 0, 0.3);
|
|
||||||
background-color: #065ca8;
|
|
||||||
outline: 0;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const ButtonPrimary = (props) => {
|
export const ButtonPrimary = (props) => {
|
||||||
if (props.loading) {
|
if (props.loading) {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
css={props.full ? STYLES_BUTTON_PRIMARY_FULL : STYLES_BUTTON_PRIMARY}
|
css={
|
||||||
style={props.style}
|
props.transparent
|
||||||
|
? STYLES_BUTTON_PRIMARY_TRANSPARENT
|
||||||
|
: STYLES_BUTTON_PRIMARY
|
||||||
|
}
|
||||||
|
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
||||||
>
|
>
|
||||||
<LoaderSpinner style={{ height: 16, width: 16 }} />
|
<LoaderSpinner style={{ height: 16, width: 16 }} />
|
||||||
</button>
|
</button>
|
||||||
@ -93,8 +69,12 @@ export const ButtonPrimary = (props) => {
|
|||||||
if (props.type === "label") {
|
if (props.type === "label") {
|
||||||
return (
|
return (
|
||||||
<label
|
<label
|
||||||
css={props.full ? STYLES_BUTTON_PRIMARY_FULL : STYLES_BUTTON_PRIMARY}
|
css={
|
||||||
style={props.style}
|
props.transparent
|
||||||
|
? STYLES_BUTTON_PRIMARY_TRANSPARENT
|
||||||
|
: STYLES_BUTTON_PRIMARY
|
||||||
|
}
|
||||||
|
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
||||||
children={props.children}
|
children={props.children}
|
||||||
type={props.label}
|
type={props.label}
|
||||||
htmlFor={props.htmlFor}
|
htmlFor={props.htmlFor}
|
||||||
@ -106,8 +86,12 @@ export const ButtonPrimary = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
css={props.full ? STYLES_BUTTON_PRIMARY_FULL : STYLES_BUTTON_PRIMARY}
|
css={
|
||||||
style={props.style}
|
props.transparent
|
||||||
|
? STYLES_BUTTON_PRIMARY_TRANSPARENT
|
||||||
|
: STYLES_BUTTON_PRIMARY
|
||||||
|
}
|
||||||
|
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
||||||
onMouseUp={props.onClick}
|
onMouseUp={props.onClick}
|
||||||
onTouchEnd={props.onClick}
|
onTouchEnd={props.onClick}
|
||||||
children={props.children}
|
children={props.children}
|
||||||
@ -137,22 +121,11 @@ const STYLES_BUTTON_SECONDARY = css`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_BUTTON_SECONDARY_FULL = css`
|
const STYLES_BUTTON_SECONDARY_TRANSPARENT = css`
|
||||||
${STYLES_BUTTON_FULL}
|
${STYLES_BUTTON}
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: ${Constants.system.white};
|
background-color: transparent;
|
||||||
box-shadow: 0 0 0 1px ${Constants.system.border} inset;
|
color: ${Constants.system.darkGray};
|
||||||
color: ${Constants.system.brand};
|
|
||||||
|
|
||||||
:hover {
|
|
||||||
${"" /* box-shadow: 0 0 0 1px #065ca8 inset;
|
|
||||||
color: #065ca8; */}
|
|
||||||
}
|
|
||||||
|
|
||||||
:focus {
|
|
||||||
outline: 0;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const ButtonSecondary = (props) => {
|
export const ButtonSecondary = (props) => {
|
||||||
@ -160,9 +133,11 @@ export const ButtonSecondary = (props) => {
|
|||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
css={
|
css={
|
||||||
props.full ? STYLES_BUTTON_SECONDARY_FULL : STYLES_BUTTON_SECONDARY
|
props.transparent
|
||||||
|
? STYLES_BUTTON_SECONDARY_TRANSPARENT
|
||||||
|
: STYLES_BUTTON_SECONDARY
|
||||||
}
|
}
|
||||||
style={props.style}
|
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
||||||
>
|
>
|
||||||
<LoaderSpinner style={{ height: 16, width: 16 }} />
|
<LoaderSpinner style={{ height: 16, width: 16 }} />
|
||||||
</button>
|
</button>
|
||||||
@ -173,9 +148,11 @@ export const ButtonSecondary = (props) => {
|
|||||||
return (
|
return (
|
||||||
<label
|
<label
|
||||||
css={
|
css={
|
||||||
props.full ? STYLES_BUTTON_SECONDARY_FULL : STYLES_BUTTON_SECONDARY
|
props.transparent
|
||||||
|
? STYLES_BUTTON_SECONDARY_TRANSPARENT
|
||||||
|
: STYLES_BUTTON_SECONDARY
|
||||||
}
|
}
|
||||||
style={props.style}
|
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
||||||
onMouseUp={props.onClick}
|
onMouseUp={props.onClick}
|
||||||
onTouchEnd={props.onClick}
|
onTouchEnd={props.onClick}
|
||||||
children={props.children}
|
children={props.children}
|
||||||
@ -187,8 +164,13 @@ export const ButtonSecondary = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
css={props.full ? STYLES_BUTTON_SECONDARY_FULL : STYLES_BUTTON_SECONDARY}
|
css={
|
||||||
|
props.transparent
|
||||||
|
? STYLES_BUTTON_SECONDARY_TRANSPARENT
|
||||||
|
: STYLES_BUTTON_SECONDARY
|
||||||
|
}
|
||||||
{...props}
|
{...props}
|
||||||
|
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -209,23 +191,23 @@ const STYLES_BUTTON_DISABLED = css`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_BUTTON_DISABLED_FULL = css`
|
const STYLES_BUTTON_DISABLED_TRANSPARENT = css`
|
||||||
${STYLES_BUTTON_FULL}
|
${STYLES_BUTTON}
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
background-color: ${Constants.system.gray};
|
background-color: transparent;
|
||||||
color: ${Constants.system.darkGray};
|
color: ${Constants.system.gray};
|
||||||
|
|
||||||
:focus {
|
|
||||||
outline: 0;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const ButtonDisabled = (props) => {
|
export const ButtonDisabled = (props) => {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
css={props.full ? STYLES_BUTTON_DISABLED_FULL : STYLES_BUTTON_DISABLED}
|
css={
|
||||||
|
props.transparent
|
||||||
|
? STYLES_BUTTON_DISABLED_TRANSPARENT
|
||||||
|
: STYLES_BUTTON_DISABLED
|
||||||
|
}
|
||||||
{...props}
|
{...props}
|
||||||
|
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -252,30 +234,23 @@ const STYLES_BUTTON_WARNING = css`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_BUTTON_WARNING_FULL = css`
|
const STYLES_BUTTON_WARNING_TRANSPARENT = css`
|
||||||
${STYLES_BUTTON_FULL}
|
${STYLES_BUTTON}
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: #e0e0e0;
|
background-color: transparent;
|
||||||
color: ${Constants.system.red};
|
color: ${Constants.system.red};
|
||||||
|
|
||||||
:hover {
|
|
||||||
background-color: #d4d4d4;
|
|
||||||
}
|
|
||||||
|
|
||||||
:focus {
|
|
||||||
box-shadow: inset 0 0 5px 2px rgba(0, 0, 0, 0.3);
|
|
||||||
background-color: #d4d4d4;
|
|
||||||
outline: 0;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const ButtonWarning = (props) => {
|
export const ButtonWarning = (props) => {
|
||||||
if (props.loading) {
|
if (props.loading) {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
css={props.full ? STYLES_BUTTON_WARNING_FULL : STYLES_BUTTON_WARNING}
|
css={
|
||||||
style={props.style}
|
props.transparent
|
||||||
|
? STYLES_BUTTON_WARNING_TRANSPARENT
|
||||||
|
: STYLES_BUTTON_WARNING
|
||||||
|
}
|
||||||
|
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
||||||
>
|
>
|
||||||
<LoaderSpinner style={{ height: 16, width: 16 }} />
|
<LoaderSpinner style={{ height: 16, width: 16 }} />
|
||||||
</button>
|
</button>
|
||||||
@ -285,8 +260,12 @@ export const ButtonWarning = (props) => {
|
|||||||
if (props.type === "label") {
|
if (props.type === "label") {
|
||||||
return (
|
return (
|
||||||
<label
|
<label
|
||||||
css={props.full ? STYLES_BUTTON_WARNING_FULL : STYLES_BUTTON_WARNING}
|
css={
|
||||||
style={props.style}
|
props.transparent
|
||||||
|
? STYLES_BUTTON_WARNING_TRANSPARENT
|
||||||
|
: STYLES_BUTTON_WARNING
|
||||||
|
}
|
||||||
|
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
||||||
children={props.children}
|
children={props.children}
|
||||||
type={props.label}
|
type={props.label}
|
||||||
htmlFor={props.htmlFor}
|
htmlFor={props.htmlFor}
|
||||||
@ -298,8 +277,12 @@ export const ButtonWarning = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
css={props.full ? STYLES_BUTTON_WARNING_FULL : STYLES_BUTTON_WARNING}
|
css={
|
||||||
style={props.style}
|
props.transparent
|
||||||
|
? STYLES_BUTTON_WARNING_TRANSPARENT
|
||||||
|
: STYLES_BUTTON_WARNING
|
||||||
|
}
|
||||||
|
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
||||||
onMouseUp={props.onClick}
|
onMouseUp={props.onClick}
|
||||||
onTouchEnd={props.onClick}
|
onTouchEnd={props.onClick}
|
||||||
children={props.children}
|
children={props.children}
|
||||||
|
@ -74,8 +74,27 @@ export class CheckBox extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<label css={STYLES_CHECKBOX} style={this.props.style}>
|
<label css={STYLES_CHECKBOX} style={this.props.style}>
|
||||||
<figure css={STYLES_CHECKBOX_FIGURE} style={this.props.boxStyle}>
|
<figure
|
||||||
{this.props.value ? <SVG.CheckBox height="20px" /> : null}
|
css={STYLES_CHECKBOX_FIGURE}
|
||||||
|
style={
|
||||||
|
this.props.value
|
||||||
|
? {
|
||||||
|
backgroundColor: Constants.system.brand,
|
||||||
|
boxShadow: `0 0 0 1px ${Constants.system.brand}`,
|
||||||
|
...this.props.boxStyle,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
backgroundColor: Constants.system.white,
|
||||||
|
...this.props.boxStyle,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{this.props.value ? (
|
||||||
|
<SVG.CheckBox
|
||||||
|
height="14px"
|
||||||
|
style={{ color: Constants.system.white }}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
</figure>
|
</figure>
|
||||||
<input
|
<input
|
||||||
css={STYLES_CHECKBOX_INPUT}
|
css={STYLES_CHECKBOX_INPUT}
|
||||||
|
@ -70,6 +70,11 @@ export default async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let newObjects = [];
|
let newObjects = [];
|
||||||
|
if (Array.isArray(req.body.data)) {
|
||||||
|
newObjects = [...req.body.data];
|
||||||
|
} else {
|
||||||
|
newObjects = [req.body.data];
|
||||||
|
}
|
||||||
const isArray = req.body.data && req.body.data.length;
|
const isArray = req.body.data && req.body.data.length;
|
||||||
if (isArray) {
|
if (isArray) {
|
||||||
newObjects = [...req.body.data];
|
newObjects = [...req.body.data];
|
||||||
|
@ -8,6 +8,10 @@ import { css } from "@emotion/react";
|
|||||||
import { TabGroup } from "~/components/core/TabGroup";
|
import { TabGroup } from "~/components/core/TabGroup";
|
||||||
import { Boundary } from "~/components/system/components/fragments/Boundary";
|
import { Boundary } from "~/components/system/components/fragments/Boundary";
|
||||||
import { PopoverNavigation } from "~/components/system/components/PopoverNavigation";
|
import { PopoverNavigation } from "~/components/system/components/PopoverNavigation";
|
||||||
|
import {
|
||||||
|
ButtonPrimary,
|
||||||
|
ButtonSecondary,
|
||||||
|
} from "~/components/system/components/Buttons";
|
||||||
|
|
||||||
import ScenePage from "~/components/core/ScenePage";
|
import ScenePage from "~/components/core/ScenePage";
|
||||||
import ScenePageHeader from "~/components/core/ScenePageHeader";
|
import ScenePageHeader from "~/components/core/ScenePageHeader";
|
||||||
@ -178,21 +182,22 @@ export default class SceneDirectory extends React.Component {
|
|||||||
.map((relation) => {
|
.map((relation) => {
|
||||||
let button = (
|
let button = (
|
||||||
<div css={STYLES_BUTTONS}>
|
<div css={STYLES_BUTTONS}>
|
||||||
<div
|
<ButtonPrimary
|
||||||
css={STYLES_ACTION_BUTTON}
|
transparent
|
||||||
|
style={{ fontSize: 16 }}
|
||||||
onClick={(e) => this._handleAccept(e, relation.owner.id)}
|
onClick={(e) => this._handleAccept(e, relation.owner.id)}
|
||||||
>
|
>
|
||||||
Accept
|
Accept
|
||||||
</div>
|
</ButtonPrimary>
|
||||||
<div
|
<ButtonSecondary
|
||||||
css={STYLES_ACTION_BUTTON}
|
transparent
|
||||||
style={{ color: Constants.system.darkGray, marginLeft: "16px" }}
|
style={{ fontSize: 16 }}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
this._handleDelete(e, relation.id);
|
this._handleDelete(e, relation.id);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Decline
|
Decline
|
||||||
</div>
|
</ButtonSecondary>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
|
@ -50,6 +50,7 @@ export default class SceneFilesFolder extends React.Component {
|
|||||||
{this.props.viewer.library[0].children &&
|
{this.props.viewer.library[0].children &&
|
||||||
this.props.viewer.library[0].children.length ? (
|
this.props.viewer.library[0].children.length ? (
|
||||||
<DataView
|
<DataView
|
||||||
|
onAction={this.props.onAction}
|
||||||
viewer={this.props.viewer}
|
viewer={this.props.viewer}
|
||||||
items={this.props.viewer.library[0].children}
|
items={this.props.viewer.library[0].children}
|
||||||
onRehydrate={this.props.onRehydrate}
|
onRehydrate={this.props.onRehydrate}
|
||||||
|
@ -54,18 +54,6 @@ export default class SceneHome extends React.Component {
|
|||||||
{hasChildren ? (
|
{hasChildren ? (
|
||||||
<div style={{ marginTop: "48px" }}>
|
<div style={{ marginTop: "48px" }}>
|
||||||
<DataView
|
<DataView
|
||||||
buttons={[
|
|
||||||
{
|
|
||||||
name: "View files",
|
|
||||||
type: "NAVIGATE",
|
|
||||||
value: this.props.viewer.library[0].id,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Upload data",
|
|
||||||
type: "SIDEBAR",
|
|
||||||
value: "SIDEBAR_ADD_FILE_TO_BUCKET",
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
viewer={this.props.viewer}
|
viewer={this.props.viewer}
|
||||||
items={this.props.viewer.library[0].children}
|
items={this.props.viewer.library[0].children}
|
||||||
onAction={this.props.onAction}
|
onAction={this.props.onAction}
|
||||||
|
@ -516,6 +516,7 @@ export default class SceneSlate extends React.Component {
|
|||||||
<div onClick={this._handleFollow}>
|
<div onClick={this._handleFollow}>
|
||||||
{following ? (
|
{following ? (
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
|
transparent
|
||||||
style={{ minWidth: 120 }}
|
style={{ minWidth: 120 }}
|
||||||
loading={this.state.followLoading}
|
loading={this.state.followLoading}
|
||||||
>
|
>
|
||||||
@ -523,6 +524,7 @@ export default class SceneSlate extends React.Component {
|
|||||||
</ButtonSecondary>
|
</ButtonSecondary>
|
||||||
) : (
|
) : (
|
||||||
<ButtonPrimary
|
<ButtonPrimary
|
||||||
|
transparent
|
||||||
style={{ minWidth: 120 }}
|
style={{ minWidth: 120 }}
|
||||||
loading={this.state.followLoading}
|
loading={this.state.followLoading}
|
||||||
>
|
>
|
||||||
|
Loading…
Reference in New Issue
Block a user