mirror of
https://github.com/filecoin-project/slate.git
synced 2024-12-23 09:01:56 +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) => {
|
||||
return await returnJSON(`/api/users/update`, {
|
||||
...DEFAULT_OPTIONS,
|
||||
|
@ -29,6 +29,7 @@ export const system = {
|
||||
slate: "#27292e",
|
||||
moonstone: "#807d78",
|
||||
wall: "#cfced3",
|
||||
shadow: "rgba(15, 14, 18, 0.03)",
|
||||
};
|
||||
|
||||
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) => {
|
||||
return (
|
||||
<svg
|
||||
@ -915,6 +935,21 @@ export const Plus = (props) => (
|
||||
</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) => (
|
||||
<svg
|
||||
viewBox="0 0 127 127"
|
||||
|
@ -75,16 +75,6 @@ export const slatename = (text) => {
|
||||
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) => {
|
||||
if (Strings.isEmpty(text)) {
|
||||
return false;
|
||||
|
@ -39,6 +39,7 @@ import SidebarCreateWalletAddress from "~/components/sidebars/SidebarCreateWalle
|
||||
import SidebarWalletSendFunds from "~/components/sidebars/SidebarWalletSendFunds";
|
||||
import SidebarFileStorageDeal from "~/components/sidebars/SidebarFileStorageDeal";
|
||||
import SidebarAddFileToBucket from "~/components/sidebars/SidebarAddFileToBucket";
|
||||
import SidebarAddFileToSlate from "~/components/sidebars/SidebarAddFileToSlate";
|
||||
import SidebarDragDropNotice from "~/components/sidebars/SidebarDragDropNotice";
|
||||
import SidebarSingleSlateSettings from "~/components/sidebars/SidebarSingleSlateSettings";
|
||||
import SidebarFilecoinArchive from "~/components/sidebars/SidebarFilecoinArchive";
|
||||
@ -64,6 +65,7 @@ const SIDEBARS = {
|
||||
SIDEBAR_WALLET_SEND_FUNDS: <SidebarWalletSendFunds />,
|
||||
SIDEBAR_CREATE_WALLET_ADDRESS: <SidebarCreateWalletAddress />,
|
||||
SIDEBAR_ADD_FILE_TO_BUCKET: <SidebarAddFileToBucket />,
|
||||
SIDEBAR_ADD_FILE_TO_SLATE: <SidebarAddFileToSlate />,
|
||||
SIDEBAR_CREATE_SLATE: <SidebarCreateSlate />,
|
||||
SIDEBAR_DRAG_DROP_NOTICE: <SidebarDragDropNotice />,
|
||||
SIDEBAR_SINGLE_SLATE_SETTINGS: <SidebarSingleSlateSettings />,
|
||||
@ -104,6 +106,7 @@ export default class ApplicationPage extends React.Component {
|
||||
sidebar: null,
|
||||
sidebarLoading: false,
|
||||
online: null,
|
||||
sidebar: <SidebarAddFileToSlate />, //remove this
|
||||
};
|
||||
|
||||
async componentDidMount() {
|
||||
@ -743,6 +746,7 @@ export default class ApplicationPage extends React.Component {
|
||||
selected: this.state.selected,
|
||||
viewer: this.state.viewer,
|
||||
data: this.state.data,
|
||||
sidebarData: this.state.sidebarData,
|
||||
fileLoading: this.state.fileLoading,
|
||||
sidebarLoading: this.state.sidebarLoading,
|
||||
onSelectedChange: this._handleSelectedChange,
|
||||
|
@ -164,7 +164,7 @@ export default class ApplicationUserControls extends React.Component {
|
||||
<Boundary
|
||||
captureResize={true}
|
||||
captureScroll={false}
|
||||
enabled={this.state.visible}
|
||||
enabled
|
||||
onOutsideRectEvent={this._handleHide}
|
||||
style={this.props.style}
|
||||
>
|
||||
|
@ -10,7 +10,8 @@ const MAX_IN_BYTES = 10737418240 * 4;
|
||||
|
||||
const STYLES_CONTAINER = css`
|
||||
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;
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
|
@ -14,7 +14,10 @@ import { generateLayout } from "~/components/core/Slate";
|
||||
import { CheckBox } from "~/components/system/components/CheckBox";
|
||||
import { Table } from "~/components/core/Table";
|
||||
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 SlateMediaObject from "~/components/core/SlateMediaObject";
|
||||
@ -40,11 +43,22 @@ const STYLES_ICON_BOX = css`
|
||||
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`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 80px;
|
||||
margin-bottom: 42px;
|
||||
margin-bottom: 30px;
|
||||
`;
|
||||
|
||||
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;
|
||||
align-items: center;
|
||||
`;
|
||||
@ -87,8 +119,8 @@ const STYLES_LEFT = css`
|
||||
min-width: 10%;
|
||||
`;
|
||||
|
||||
const STYLES_RIGHT = css`
|
||||
flex-shrink: 0;
|
||||
const STYLES_FILES_SELECTED = css`
|
||||
font-family: ${Constants.font.semiBold};
|
||||
`;
|
||||
|
||||
const STYLES_ICON_ELEMENT = css`
|
||||
@ -120,10 +152,8 @@ const STYLES_COPY_INPUT = css`
|
||||
`;
|
||||
|
||||
const STYLES_IMAGE_GRID = css`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(214px, 1fr));
|
||||
margin: 0 -27px;
|
||||
`;
|
||||
|
||||
@ -134,7 +164,8 @@ const STYLES_IMAGE_BOX = css`
|
||||
display: flex;
|
||||
align-items: 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;
|
||||
`;
|
||||
|
||||
@ -165,6 +196,7 @@ export default class DataView extends React.Component {
|
||||
"remote-slate-object-add",
|
||||
this._handleRemoteSlateObjectAdd
|
||||
);
|
||||
window.addEventListener("remote-update-carousel", this._handleUpdate);
|
||||
}
|
||||
|
||||
await this._handleUpdate();
|
||||
@ -185,6 +217,7 @@ export default class DataView extends React.Component {
|
||||
"remote-slate-object-add",
|
||||
this._handleRemoteSlateObjectAdd
|
||||
);
|
||||
window.removeEventListener("remote-update-carousel", this._handleUpdate);
|
||||
}
|
||||
|
||||
_increment = (direction) => {
|
||||
@ -218,9 +251,8 @@ export default class DataView extends React.Component {
|
||||
if (!window.confirm(message)) {
|
||||
return;
|
||||
}
|
||||
console.log(this.state.checked);
|
||||
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(
|
||||
"/ipfs/",
|
||||
""
|
||||
@ -372,13 +404,9 @@ export default class DataView extends React.Component {
|
||||
detail: { loading: { id: slate.id } },
|
||||
});
|
||||
|
||||
const addResponse = await fetch(`/api/slates/add-url`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({ slate, data: [{ title: data.name, ...data }] }),
|
||||
const addResponse = await Actions.addFileToSlate({
|
||||
slate,
|
||||
data: [{ title: data.name, ...data }],
|
||||
});
|
||||
|
||||
if (!addResponse) {
|
||||
@ -491,10 +519,6 @@ export default class DataView extends React.Component {
|
||||
this.setState({ menu: null });
|
||||
};
|
||||
|
||||
_handleRemoteDeletion = async (e) => {
|
||||
await this._handleDelete(e.detail.cid);
|
||||
};
|
||||
|
||||
_handleLoading = ({ cids }) => {
|
||||
let loading = this.state.loading;
|
||||
for (let cid of cids) {
|
||||
@ -511,6 +535,23 @@ export default class DataView extends React.Component {
|
||||
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() {
|
||||
const header = (
|
||||
<div css={STYLES_HEADER_LINE}>
|
||||
@ -552,25 +593,8 @@ export default class DataView extends React.Component {
|
||||
</div>
|
||||
);
|
||||
const footer = (
|
||||
<div css={STYLES_ACTION_ROW}>
|
||||
<div css={STYLES_LEFT}>
|
||||
{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}>
|
||||
<React.Fragment>
|
||||
<div css={STYLES_ARROWS}>
|
||||
<span
|
||||
css={STYLES_ICON_ELEMENT}
|
||||
style={
|
||||
@ -604,7 +628,33 @@ export default class DataView extends React.Component {
|
||||
<SVG.NavigationArrow height="24px" />
|
||||
</span>
|
||||
</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") {
|
||||
return (
|
||||
@ -640,7 +690,19 @@ export default class DataView extends React.Component {
|
||||
const columns = [
|
||||
{
|
||||
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",
|
||||
},
|
||||
{
|
||||
@ -667,7 +729,7 @@ export default class DataView extends React.Component {
|
||||
|
||||
return {
|
||||
...each,
|
||||
checkbox: this._handleCheckBox ? (
|
||||
checkbox: (
|
||||
<div
|
||||
style={{
|
||||
margin: "12px 0",
|
||||
@ -680,19 +742,13 @@ export default class DataView extends React.Component {
|
||||
}}
|
||||
>
|
||||
<CheckBox
|
||||
name={`checkbox-${this.state.startIndex + index}`}
|
||||
value={
|
||||
!!this.state.checked[
|
||||
`checkbox-${this.state.startIndex + index}`
|
||||
]
|
||||
}
|
||||
name={this.state.startIndex + index}
|
||||
value={!!this.state.checked[this.state.startIndex + index]}
|
||||
onChange={this._handleCheckBox}
|
||||
boxStyle={{ height: 16, width: 16 }}
|
||||
style={{ position: "relative", right: 3 }}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div />
|
||||
),
|
||||
name: (
|
||||
<div
|
||||
|
@ -8,7 +8,7 @@ import { css } from "@emotion/react";
|
||||
const STYLES_EMPTY_STATE = css`
|
||||
width: 100%;
|
||||
height: 328px;
|
||||
border: 1px solid ${Constants.system.border};
|
||||
border: 1px solid rgba(229, 229, 229, 0.75);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
@ -37,7 +37,7 @@ const STYLES_DROPDOWN_ITEM = css`
|
||||
margin-bottom: -1px;
|
||||
|
||||
: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={{
|
||||
borderColor:
|
||||
this.state.selectedIndex === i
|
||||
? Constants.system.border
|
||||
? "rgba(229, 229, 229, 0.75)"
|
||||
: "transparent",
|
||||
...this.props.itemStyle,
|
||||
}}
|
||||
|
@ -11,6 +11,22 @@ import { dispatchCustomEvent } from "~/common/custom-events";
|
||||
|
||||
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`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@ -18,9 +34,11 @@ const STYLES_IMAGE_ROW = css`
|
||||
height: 160px;
|
||||
justify-content: space-between;
|
||||
overflow: hidden;
|
||||
margin: 0 -12px;
|
||||
|
||||
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||
justify-content: center;
|
||||
margin: 0 -8px;
|
||||
}
|
||||
`;
|
||||
|
||||
@ -35,19 +53,21 @@ const STYLES_ITEM_BOX = css`
|
||||
cursor: pointer;
|
||||
|
||||
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||
margin: 0 auto;
|
||||
margin: 0 8px;
|
||||
}
|
||||
|
||||
:hover {
|
||||
color: ${Constants.system.brand};
|
||||
}
|
||||
`;
|
||||
|
||||
:first-of-type {
|
||||
margin-left: 0px;
|
||||
}
|
||||
const STYLES_EMPTY_BOX = css`
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
margin: 0px 12px;
|
||||
|
||||
:last-of-type {
|
||||
margin-right: 0px;
|
||||
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||
margin: 0 8px;
|
||||
}
|
||||
`;
|
||||
|
||||
@ -57,6 +77,7 @@ const STYLES_IMAGE_ROW_SMALL = css`
|
||||
flex-wrap: wrap;
|
||||
height: 56px;
|
||||
overflow: hidden;
|
||||
margin: 0 -8px;
|
||||
`;
|
||||
|
||||
const STYLES_ITEM_BOX_SMALL = css`
|
||||
@ -67,49 +88,72 @@ const STYLES_ITEM_BOX_SMALL = css`
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0px 0px 0px 1px rgba(229, 229, 229, 0.5) inset;
|
||||
`;
|
||||
|
||||
:first-of-type {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
:last-of-type {
|
||||
margin-right: 0px;
|
||||
}
|
||||
const STYLES_EMPTY_BOX_SMALL = css`
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
margin: 0px 8px;
|
||||
`;
|
||||
|
||||
export function SlatePreviewRow(props) {
|
||||
let numItems = props.numItems || 5;
|
||||
let objects =
|
||||
props.slate.data.objects.length > numItems
|
||||
? props.slate.data.objects.slice(0, numItems)
|
||||
: props.slate.data.objects;
|
||||
let objects;
|
||||
if (props.slate.data.objects.length === 0) {
|
||||
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 (
|
||||
<div
|
||||
css={props.small ? STYLES_IMAGE_ROW_SMALL : STYLES_IMAGE_ROW}
|
||||
style={props.containerStyle}
|
||||
>
|
||||
{objects.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>
|
||||
))}
|
||||
{objects}
|
||||
{extra}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
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;
|
||||
padding: 32px 40px;
|
||||
font-size: 12px;
|
||||
@ -153,17 +197,6 @@ const STYLES_BODY = css`
|
||||
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`
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
@ -354,20 +387,10 @@ export default class SlatePreviewBlock extends React.Component {
|
||||
) : (
|
||||
<div style={{ height: "8px" }} />
|
||||
)}
|
||||
{this.props.slate.data.objects &&
|
||||
this.props.slate.data.objects.length ? (
|
||||
<SlatePreviewRow
|
||||
{...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>
|
||||
)}
|
||||
<SlatePreviewRow
|
||||
{...this.props}
|
||||
previewStyle={this.props.previewStyle}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ const TABLE_COLUMN_WIDTH_DEFAULTS = {
|
||||
|
||||
const STYLES_CONTAINER = css`
|
||||
border: 1px solid rgba(229, 229, 229, 0.75);
|
||||
box-shadow: 0 0 40px 0 ${Constants.system.shadow};
|
||||
`;
|
||||
|
||||
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 System from "~/components/system";
|
||||
import * as Validations from "~/common/validations";
|
||||
import * as Actions from "~/common/actions";
|
||||
|
||||
import { dispatchCustomEvent } from "~/common/custom-events";
|
||||
import { css } from "@emotion/react";
|
||||
@ -87,6 +88,48 @@ export default class SidebarCreateSlate extends React.Component {
|
||||
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.props.onAction({
|
||||
type: "NAVIGATE",
|
||||
|
@ -28,7 +28,7 @@ export default class SidebarCreateSlate extends React.Component {
|
||||
|
||||
_handleSubmit = async () => {
|
||||
this.setState({ loading: true });
|
||||
if (!this.state.email || !this.state.email.length) {
|
||||
if (Strings.isEmpty(this.state.email)) {
|
||||
dispatchCustomEvent({
|
||||
name: "create-alert",
|
||||
detail: {
|
||||
@ -54,17 +54,6 @@ export default class SidebarCreateSlate extends React.Component {
|
||||
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({
|
||||
username: this.props.viewer.username,
|
||||
name: this.state.name,
|
||||
|
@ -11,32 +11,13 @@ const STYLES_BUTTON = `
|
||||
outline: 0;
|
||||
border: 0;
|
||||
min-height: 40px;
|
||||
padding: 6px 24px 6px 24px;
|
||||
padding: 4px 16px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
letter-spacing: 0.2px;
|
||||
font-family: ${Constants.font.semiBold};
|
||||
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};
|
||||
font-family: ${Constants.font.medium};
|
||||
transition: 200ms ease all;
|
||||
overflow-wrap: break-word;
|
||||
user-select: none;
|
||||
@ -60,30 +41,25 @@ const STYLES_BUTTON_PRIMARY = css`
|
||||
}
|
||||
`;
|
||||
|
||||
const STYLES_BUTTON_PRIMARY_FULL = css`
|
||||
${STYLES_BUTTON_FULL}
|
||||
const STYLES_BUTTON_PRIMARY_TRANSPARENT = css`
|
||||
${STYLES_BUTTON}
|
||||
${"" /* font-size: 16px;
|
||||
font-family: ${Constants.font.medium}; */}
|
||||
cursor: pointer;
|
||||
background-color: ${Constants.system.brand};
|
||||
color: ${Constants.system.white};
|
||||
|
||||
: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;
|
||||
}
|
||||
background-color: transparent;
|
||||
color: ${Constants.system.brand};
|
||||
`;
|
||||
|
||||
export const ButtonPrimary = (props) => {
|
||||
if (props.loading) {
|
||||
return (
|
||||
<button
|
||||
css={props.full ? STYLES_BUTTON_PRIMARY_FULL : STYLES_BUTTON_PRIMARY}
|
||||
style={props.style}
|
||||
css={
|
||||
props.transparent
|
||||
? STYLES_BUTTON_PRIMARY_TRANSPARENT
|
||||
: STYLES_BUTTON_PRIMARY
|
||||
}
|
||||
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
||||
>
|
||||
<LoaderSpinner style={{ height: 16, width: 16 }} />
|
||||
</button>
|
||||
@ -93,8 +69,12 @@ export const ButtonPrimary = (props) => {
|
||||
if (props.type === "label") {
|
||||
return (
|
||||
<label
|
||||
css={props.full ? STYLES_BUTTON_PRIMARY_FULL : STYLES_BUTTON_PRIMARY}
|
||||
style={props.style}
|
||||
css={
|
||||
props.transparent
|
||||
? STYLES_BUTTON_PRIMARY_TRANSPARENT
|
||||
: STYLES_BUTTON_PRIMARY
|
||||
}
|
||||
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
||||
children={props.children}
|
||||
type={props.label}
|
||||
htmlFor={props.htmlFor}
|
||||
@ -106,8 +86,12 @@ export const ButtonPrimary = (props) => {
|
||||
|
||||
return (
|
||||
<button
|
||||
css={props.full ? STYLES_BUTTON_PRIMARY_FULL : STYLES_BUTTON_PRIMARY}
|
||||
style={props.style}
|
||||
css={
|
||||
props.transparent
|
||||
? STYLES_BUTTON_PRIMARY_TRANSPARENT
|
||||
: STYLES_BUTTON_PRIMARY
|
||||
}
|
||||
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
||||
onMouseUp={props.onClick}
|
||||
onTouchEnd={props.onClick}
|
||||
children={props.children}
|
||||
@ -137,22 +121,11 @@ const STYLES_BUTTON_SECONDARY = css`
|
||||
}
|
||||
`;
|
||||
|
||||
const STYLES_BUTTON_SECONDARY_FULL = css`
|
||||
${STYLES_BUTTON_FULL}
|
||||
const STYLES_BUTTON_SECONDARY_TRANSPARENT = css`
|
||||
${STYLES_BUTTON}
|
||||
cursor: pointer;
|
||||
background-color: ${Constants.system.white};
|
||||
box-shadow: 0 0 0 1px ${Constants.system.border} inset;
|
||||
color: ${Constants.system.brand};
|
||||
|
||||
:hover {
|
||||
${"" /* box-shadow: 0 0 0 1px #065ca8 inset;
|
||||
color: #065ca8; */}
|
||||
}
|
||||
|
||||
:focus {
|
||||
outline: 0;
|
||||
border: 0;
|
||||
}
|
||||
background-color: transparent;
|
||||
color: ${Constants.system.darkGray};
|
||||
`;
|
||||
|
||||
export const ButtonSecondary = (props) => {
|
||||
@ -160,9 +133,11 @@ export const ButtonSecondary = (props) => {
|
||||
return (
|
||||
<button
|
||||
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 }} />
|
||||
</button>
|
||||
@ -173,9 +148,11 @@ export const ButtonSecondary = (props) => {
|
||||
return (
|
||||
<label
|
||||
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}
|
||||
onTouchEnd={props.onClick}
|
||||
children={props.children}
|
||||
@ -187,8 +164,13 @@ export const ButtonSecondary = (props) => {
|
||||
|
||||
return (
|
||||
<button
|
||||
css={props.full ? STYLES_BUTTON_SECONDARY_FULL : STYLES_BUTTON_SECONDARY}
|
||||
css={
|
||||
props.transparent
|
||||
? STYLES_BUTTON_SECONDARY_TRANSPARENT
|
||||
: STYLES_BUTTON_SECONDARY
|
||||
}
|
||||
{...props}
|
||||
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@ -209,23 +191,23 @@ const STYLES_BUTTON_DISABLED = css`
|
||||
}
|
||||
`;
|
||||
|
||||
const STYLES_BUTTON_DISABLED_FULL = css`
|
||||
${STYLES_BUTTON_FULL}
|
||||
const STYLES_BUTTON_DISABLED_TRANSPARENT = css`
|
||||
${STYLES_BUTTON}
|
||||
cursor: not-allowed;
|
||||
background-color: ${Constants.system.gray};
|
||||
color: ${Constants.system.darkGray};
|
||||
|
||||
:focus {
|
||||
outline: 0;
|
||||
border: 0;
|
||||
}
|
||||
background-color: transparent;
|
||||
color: ${Constants.system.gray};
|
||||
`;
|
||||
|
||||
export const ButtonDisabled = (props) => {
|
||||
return (
|
||||
<button
|
||||
css={props.full ? STYLES_BUTTON_DISABLED_FULL : STYLES_BUTTON_DISABLED}
|
||||
css={
|
||||
props.transparent
|
||||
? STYLES_BUTTON_DISABLED_TRANSPARENT
|
||||
: STYLES_BUTTON_DISABLED
|
||||
}
|
||||
{...props}
|
||||
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@ -252,30 +234,23 @@ const STYLES_BUTTON_WARNING = css`
|
||||
}
|
||||
`;
|
||||
|
||||
const STYLES_BUTTON_WARNING_FULL = css`
|
||||
${STYLES_BUTTON_FULL}
|
||||
const STYLES_BUTTON_WARNING_TRANSPARENT = css`
|
||||
${STYLES_BUTTON}
|
||||
cursor: pointer;
|
||||
background-color: #e0e0e0;
|
||||
background-color: transparent;
|
||||
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) => {
|
||||
if (props.loading) {
|
||||
return (
|
||||
<button
|
||||
css={props.full ? STYLES_BUTTON_WARNING_FULL : STYLES_BUTTON_WARNING}
|
||||
style={props.style}
|
||||
css={
|
||||
props.transparent
|
||||
? STYLES_BUTTON_WARNING_TRANSPARENT
|
||||
: STYLES_BUTTON_WARNING
|
||||
}
|
||||
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
||||
>
|
||||
<LoaderSpinner style={{ height: 16, width: 16 }} />
|
||||
</button>
|
||||
@ -285,8 +260,12 @@ export const ButtonWarning = (props) => {
|
||||
if (props.type === "label") {
|
||||
return (
|
||||
<label
|
||||
css={props.full ? STYLES_BUTTON_WARNING_FULL : STYLES_BUTTON_WARNING}
|
||||
style={props.style}
|
||||
css={
|
||||
props.transparent
|
||||
? STYLES_BUTTON_WARNING_TRANSPARENT
|
||||
: STYLES_BUTTON_WARNING
|
||||
}
|
||||
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
||||
children={props.children}
|
||||
type={props.label}
|
||||
htmlFor={props.htmlFor}
|
||||
@ -298,8 +277,12 @@ export const ButtonWarning = (props) => {
|
||||
|
||||
return (
|
||||
<button
|
||||
css={props.full ? STYLES_BUTTON_WARNING_FULL : STYLES_BUTTON_WARNING}
|
||||
style={props.style}
|
||||
css={
|
||||
props.transparent
|
||||
? STYLES_BUTTON_WARNING_TRANSPARENT
|
||||
: STYLES_BUTTON_WARNING
|
||||
}
|
||||
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
||||
onMouseUp={props.onClick}
|
||||
onTouchEnd={props.onClick}
|
||||
children={props.children}
|
||||
|
@ -74,8 +74,27 @@ export class CheckBox extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<label css={STYLES_CHECKBOX} style={this.props.style}>
|
||||
<figure css={STYLES_CHECKBOX_FIGURE} style={this.props.boxStyle}>
|
||||
{this.props.value ? <SVG.CheckBox height="20px" /> : null}
|
||||
<figure
|
||||
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>
|
||||
<input
|
||||
css={STYLES_CHECKBOX_INPUT}
|
||||
|
@ -70,6 +70,11 @@ export default async (req, res) => {
|
||||
}
|
||||
|
||||
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;
|
||||
if (isArray) {
|
||||
newObjects = [...req.body.data];
|
||||
|
@ -8,6 +8,10 @@ import { css } from "@emotion/react";
|
||||
import { TabGroup } from "~/components/core/TabGroup";
|
||||
import { Boundary } from "~/components/system/components/fragments/Boundary";
|
||||
import { PopoverNavigation } from "~/components/system/components/PopoverNavigation";
|
||||
import {
|
||||
ButtonPrimary,
|
||||
ButtonSecondary,
|
||||
} from "~/components/system/components/Buttons";
|
||||
|
||||
import ScenePage from "~/components/core/ScenePage";
|
||||
import ScenePageHeader from "~/components/core/ScenePageHeader";
|
||||
@ -178,21 +182,22 @@ export default class SceneDirectory extends React.Component {
|
||||
.map((relation) => {
|
||||
let button = (
|
||||
<div css={STYLES_BUTTONS}>
|
||||
<div
|
||||
css={STYLES_ACTION_BUTTON}
|
||||
<ButtonPrimary
|
||||
transparent
|
||||
style={{ fontSize: 16 }}
|
||||
onClick={(e) => this._handleAccept(e, relation.owner.id)}
|
||||
>
|
||||
Accept
|
||||
</div>
|
||||
<div
|
||||
css={STYLES_ACTION_BUTTON}
|
||||
style={{ color: Constants.system.darkGray, marginLeft: "16px" }}
|
||||
</ButtonPrimary>
|
||||
<ButtonSecondary
|
||||
transparent
|
||||
style={{ fontSize: 16 }}
|
||||
onClick={(e) => {
|
||||
this._handleDelete(e, relation.id);
|
||||
}}
|
||||
>
|
||||
Decline
|
||||
</div>
|
||||
</ButtonSecondary>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
|
@ -50,6 +50,7 @@ export default class SceneFilesFolder extends React.Component {
|
||||
{this.props.viewer.library[0].children &&
|
||||
this.props.viewer.library[0].children.length ? (
|
||||
<DataView
|
||||
onAction={this.props.onAction}
|
||||
viewer={this.props.viewer}
|
||||
items={this.props.viewer.library[0].children}
|
||||
onRehydrate={this.props.onRehydrate}
|
||||
|
@ -54,18 +54,6 @@ export default class SceneHome extends React.Component {
|
||||
{hasChildren ? (
|
||||
<div style={{ marginTop: "48px" }}>
|
||||
<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}
|
||||
items={this.props.viewer.library[0].children}
|
||||
onAction={this.props.onAction}
|
||||
|
@ -516,6 +516,7 @@ export default class SceneSlate extends React.Component {
|
||||
<div onClick={this._handleFollow}>
|
||||
{following ? (
|
||||
<ButtonSecondary
|
||||
transparent
|
||||
style={{ minWidth: 120 }}
|
||||
loading={this.state.followLoading}
|
||||
>
|
||||
@ -523,6 +524,7 @@ export default class SceneSlate extends React.Component {
|
||||
</ButtonSecondary>
|
||||
) : (
|
||||
<ButtonPrimary
|
||||
transparent
|
||||
style={{ minWidth: 120 }}
|
||||
loading={this.state.followLoading}
|
||||
>
|
||||
|
Loading…
Reference in New Issue
Block a user