mirror of
https://github.com/filecoin-project/slate.git
synced 2024-12-23 09:01:56 +03:00
new carousel for data view
This commit is contained in:
parent
6a21d4c0f7
commit
5bbfe2e41b
@ -19,6 +19,7 @@ export const system = {
|
||||
lightBorder: "#ececec",
|
||||
border: "#d8d8d8",
|
||||
darkGray: "#b2b2b2",
|
||||
grayBlack: "#666666",
|
||||
black: "#1b1f23",
|
||||
pitchBlack: "#0c0c0c",
|
||||
brand: "#0666bb",
|
||||
|
@ -654,6 +654,24 @@ export const Trash = (props) => (
|
||||
</svg>
|
||||
);
|
||||
|
||||
export const Download = (props) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
height={props.height}
|
||||
style={props.style}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<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="M8 12L12 16L16 12" />
|
||||
<path d="M12 8V16" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
export const Folder = (props) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@ -957,6 +975,42 @@ export const InfoCircle = (props) => (
|
||||
</svg>
|
||||
);
|
||||
|
||||
export const Minimize = (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="M4 14H10V20" />
|
||||
<path d="M20 10H14V4" />
|
||||
<path d="M14 10L21 3" />
|
||||
<path d="M3 21L10 14" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
export const Maximize = (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="M15 3H21V9" />
|
||||
<path d="M9 21H3V15" />
|
||||
<path d="M21 3L14 10" />
|
||||
<path d="M3 21L10 14" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
export const Plus = (props) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@ -1062,6 +1116,7 @@ export const CopyAndPaste = (props) => {
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
strokeWidth="2"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
|
@ -59,7 +59,7 @@ const STYLES_INFO = css`
|
||||
const STYLES_MESSAGE = css`
|
||||
${STYLES_ALERT}
|
||||
background-color: ${Constants.system.foreground};
|
||||
color: #666666;
|
||||
color: ${Constants.system.grayBlack};
|
||||
|
||||
@supports (
|
||||
(-webkit-backdrop-filter: blur(25px)) or (backdrop-filter: blur(25px))
|
||||
@ -67,7 +67,7 @@ const STYLES_MESSAGE = css`
|
||||
-webkit-backdrop-filter: blur(25px);
|
||||
backdrop-filter: blur(25px);
|
||||
background-color: rgba(244, 244, 244, 0.75);
|
||||
color: #666666;
|
||||
color: ${Constants.system.grayBlack};
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -797,7 +797,10 @@ export default class ApplicationPage extends React.Component {
|
||||
>
|
||||
{scene}
|
||||
</ApplicationLayout>
|
||||
<GlobalViewerCID />
|
||||
<GlobalViewerCID
|
||||
onRehydrate={this.rehydrate}
|
||||
onAction={this._handleAction}
|
||||
/>
|
||||
<System.GlobalCarousel />
|
||||
<System.GlobalModal />
|
||||
</WebsitePrototypeWrapper>
|
||||
|
@ -584,7 +584,7 @@ export default class DataView extends React.Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
let numChecked = Object.keys(this.state.checked).length;
|
||||
let numChecked = Object.keys(this.state.checked).length || 0;
|
||||
const header = (
|
||||
<div css={STYLES_HEADER_LINE}>
|
||||
<TabGroup disabled tabs={["Uploads"]} style={{ margin: 0 }} />
|
||||
@ -901,7 +901,7 @@ export default class DataView extends React.Component {
|
||||
name: (
|
||||
<div
|
||||
css={STYLES_CONTAINER_HOVER}
|
||||
onClick={() => this._handleSelect(index)}
|
||||
onClick={() => this._handleSelect(this.state.startIndex + index)}
|
||||
>
|
||||
<div
|
||||
css={STYLES_ICON_BOX_HOVER}
|
||||
|
106
components/core/SlatePicker.js
Normal file
106
components/core/SlatePicker.js
Normal file
@ -0,0 +1,106 @@
|
||||
import * as React from "react";
|
||||
import * as Strings from "~/common/strings";
|
||||
import * as Constants from "~/common/constants";
|
||||
import * as SVG from "~/common/svg";
|
||||
|
||||
import { css } from "@emotion/react";
|
||||
import { LoaderSpinner } from "~/components/system/components/Loaders";
|
||||
|
||||
const STYLES_SLATE_NAME = css`
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-family: ${Constants.font.medium};
|
||||
`;
|
||||
|
||||
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;
|
||||
color: ${Constants.system.darkGray};
|
||||
|
||||
:hover {
|
||||
color: ${Constants.system.black} !important;
|
||||
}
|
||||
`;
|
||||
|
||||
const STYLES_ICON_BOX = css`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
export class SlatePicker extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div
|
||||
css={STYLES_SLATE_LINE}
|
||||
style={{ marginBottom: 32 }}
|
||||
onClick={this.props.onCreateSlate}
|
||||
>
|
||||
<SVG.Plus
|
||||
height="24px"
|
||||
style={{
|
||||
marginRight: 8,
|
||||
pointerEvents: "none",
|
||||
}}
|
||||
/>
|
||||
<div css={STYLES_SLATE_NAME}>Create new slate</div>
|
||||
</div>
|
||||
<div css={STYLES_SLATE_LIST} style={this.props.style}>
|
||||
{this.props.slates.map((slate) => (
|
||||
<div
|
||||
css={STYLES_SLATE_LINE}
|
||||
onClick={() => this.props.onAdd(slate)}
|
||||
>
|
||||
<div css={STYLES_ICON_BOX}>
|
||||
{this.props.loading &&
|
||||
this.props.loading.id &&
|
||||
this.props.loading.id === slate.id ? (
|
||||
<LoaderSpinner
|
||||
style={{ height: 20, width: 20, margin: "2px 8px 2px 2px" }}
|
||||
/>
|
||||
) : this.props.selected[slate.id] ? (
|
||||
<SVG.Slate
|
||||
height="24px"
|
||||
style={{
|
||||
marginRight: 8,
|
||||
pointerEvents: "none",
|
||||
color: Constants.system.black,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<SVG.PlusCircle
|
||||
height="24px"
|
||||
style={{
|
||||
marginRight: 8,
|
||||
pointerEvents: "none",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div
|
||||
css={STYLES_SLATE_NAME}
|
||||
style={{
|
||||
color: this.props.selected[slate.id]
|
||||
? Constants.system.black
|
||||
: "auto",
|
||||
}}
|
||||
>
|
||||
{slate.data.name || slate.slatename}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@ const STYLES_BOX = css`
|
||||
|
||||
const STYLES_MESSAGE = css`
|
||||
line-height: 1.5;
|
||||
color: #666666;
|
||||
color: ${Constants.system.grayBlack};
|
||||
`;
|
||||
|
||||
export class WarningMessage extends React.Component {
|
||||
|
@ -21,6 +21,14 @@ const STYLES_ROOT = css`
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
@supports (
|
||||
(-webkit-backdrop-filter: blur(15px)) or (backdrop-filter: blur(15px))
|
||||
) {
|
||||
-webkit-backdrop-filter: blur(15px);
|
||||
backdrop-filter: blur(15px);
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
@keyframes global-data-fade-in {
|
||||
from {
|
||||
transform: translateX(8px);
|
||||
@ -66,6 +74,19 @@ const STYLES_ROOT_CONTENT = css`
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
const STYLES_EXPANDER = css`
|
||||
color: ${Constants.system.darkGray};
|
||||
position: absolute;
|
||||
padding: 4px;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
cursor: pointer;
|
||||
|
||||
:hover {
|
||||
color: ${Constants.system.black};
|
||||
}
|
||||
`;
|
||||
|
||||
export class GlobalViewerCID extends React.Component {
|
||||
state = {
|
||||
index: 0,
|
||||
@ -73,6 +94,7 @@ export class GlobalViewerCID extends React.Component {
|
||||
visible: false,
|
||||
loading: false,
|
||||
saving: false,
|
||||
showSidebar: true,
|
||||
};
|
||||
|
||||
componentDidMount = () => {
|
||||
@ -195,12 +217,27 @@ export class GlobalViewerCID extends React.Component {
|
||||
<SVG.ChevronRight height="20px" />
|
||||
</span>
|
||||
{current.component}
|
||||
<div
|
||||
css={STYLES_EXPANDER}
|
||||
onClick={() =>
|
||||
this.setState({ showSidebar: !this.state.showSidebar })
|
||||
}
|
||||
>
|
||||
{this.state.showSidebar ? (
|
||||
<SVG.Maximize height="24px" />
|
||||
) : (
|
||||
<SVG.Minimize height="24px" />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<GlobalViewerCIDSidebar
|
||||
display={this.state.showSidebar ? "block" : "none"}
|
||||
onClose={this._handleClose}
|
||||
key={current.id}
|
||||
saving={this.state.saving}
|
||||
loading={this.state.loading}
|
||||
onRehydrate={this.props.onRehydrate}
|
||||
onAction={this.props.onAction}
|
||||
{...current}
|
||||
/>
|
||||
</div>
|
||||
|
@ -14,7 +14,7 @@ import GlobalViewerCIDSidebarSlates from "~/components/core/viewers/GlobalViewer
|
||||
|
||||
const STYLES_SIDEBAR = css`
|
||||
width: 420px;
|
||||
padding-left: 24px;
|
||||
padding: 48px 24px;
|
||||
flex-shrink: 0;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
@ -22,6 +22,14 @@ const STYLES_SIDEBAR = css`
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
|
||||
@supports (
|
||||
(-webkit-backdrop-filter: blur(75px)) or (backdrop-filter: blur(75px))
|
||||
) {
|
||||
-webkit-backdrop-filter: blur(75px);
|
||||
backdrop-filter: blur(75px);
|
||||
background-color: rgba(248, 248, 248, 0.5);
|
||||
}
|
||||
|
||||
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||
display: none;
|
||||
}
|
||||
@ -32,7 +40,7 @@ const STYLES_BUTTON = css`
|
||||
color: ${Constants.system.pitchBlack};
|
||||
flex-shrink: 0;
|
||||
width: 100%;
|
||||
padding: 16px 24px 16px 24px;
|
||||
padding: 16px 24px;
|
||||
min-height: 56px;
|
||||
font-size: 14px;
|
||||
transition: 200ms ease all;
|
||||
@ -46,6 +54,18 @@ const STYLES_BUTTON = css`
|
||||
}
|
||||
`;
|
||||
|
||||
const STYLES_DISMISS_BOX = css`
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
color: ${Constants.system.darkGray};
|
||||
cursor: pointer;
|
||||
|
||||
:hover {
|
||||
color: ${Constants.system.black};
|
||||
}
|
||||
`;
|
||||
|
||||
const STYLES_SIDEBAR_SECTION = css`
|
||||
flex-shrink: 0;
|
||||
width: 100%;
|
||||
@ -96,15 +116,14 @@ export default class GlobalViewerCIDSidebar extends React.Component {
|
||||
|
||||
if (this.props.onClose) {
|
||||
elements.push(
|
||||
<span
|
||||
<div
|
||||
key="s-1"
|
||||
css={STYLES_BUTTON}
|
||||
style={{ textAlign: "right" }}
|
||||
css={STYLES_DISMISS_BOX}
|
||||
onMouseUp={this.props.onClose}
|
||||
onTouchEnd={this.props.onClose}
|
||||
>
|
||||
<SVG.Dismiss height="20px" />
|
||||
</span>
|
||||
<SVG.Dismiss height="24px" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -117,31 +136,40 @@ export default class GlobalViewerCIDSidebar extends React.Component {
|
||||
loading={this.props.loading}
|
||||
onAddToSlate={this.props.onAddToSlate}
|
||||
onRemoveFromSlate={this.props.onRemoveFromSlate}
|
||||
onDownload={this._handleDownload}
|
||||
onDataDelete={this.props.onDataDelete}
|
||||
onClose={this.props.onClose}
|
||||
onRehydrate={this.props.onRehydrate}
|
||||
onAction={this.props.onAction}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (this.props.onDataDelete) {
|
||||
elements.push(
|
||||
<span
|
||||
key="s-4"
|
||||
css={STYLES_BUTTON}
|
||||
onMouseUp={this.props.onDataDelete}
|
||||
onTouchEnd={this.props.onDataDelete}
|
||||
>
|
||||
{this.props.loading ? (
|
||||
<LoaderSpinner style={{ height: 16, width: 16 }} />
|
||||
) : (
|
||||
<span>Delete CID and from all slates ⭢</span>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
// if (this.props.onDataDelete) {
|
||||
// elements.push(
|
||||
// <span
|
||||
// key="s-4"
|
||||
// css={STYLES_BUTTON}
|
||||
// onMouseUp={this.props.onDataDelete}
|
||||
// onTouchEnd={this.props.onDataDelete}
|
||||
// >
|
||||
// {this.props.loading ? (
|
||||
// <LoaderSpinner style={{ height: 16, width: 16 }} />
|
||||
// ) : (
|
||||
// <span>Delete CID and from all slates ⭢</span>
|
||||
// )}
|
||||
// </span>
|
||||
// );
|
||||
// }
|
||||
|
||||
if (!elements.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <div css={STYLES_SIDEBAR}>{elements}</div>;
|
||||
return (
|
||||
<div css={STYLES_SIDEBAR} style={{ display: this.props.display }}>
|
||||
{elements}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,12 @@ import * as React from "react";
|
||||
import * as SVG from "~/common/svg";
|
||||
import * as Strings from "~/common/strings";
|
||||
import * as Constants from "~/common/constants";
|
||||
import * as Actions from "~/common/actions";
|
||||
|
||||
import { css } from "@emotion/react";
|
||||
import { LoaderSpinner } from "~/components/system/components/Loaders";
|
||||
import { SlatePicker } from "~/components/core/SlatePicker";
|
||||
import { dispatchCustomEvent } from "~/common/custom-events";
|
||||
|
||||
const STYLES_CONTAINER = css`
|
||||
width: 100%;
|
||||
@ -20,16 +23,15 @@ const STYLES_CONTAINER = css`
|
||||
`;
|
||||
|
||||
const STYLES_META = css`
|
||||
padding: 14px 24px 8px 24px;
|
||||
padding: 14px 0px 8px 0px;
|
||||
overflow-wrap: break-word;
|
||||
`;
|
||||
|
||||
const STYLES_META_TITLE = css`
|
||||
font-family: ${Constants.font.code};
|
||||
font-family: ${Constants.font.semiBold};
|
||||
color: ${Constants.system.pitchBlack};
|
||||
font-size: 12px;
|
||||
font-size: ${Constants.typescale.lvl2};
|
||||
text-decoration: none;
|
||||
transition: 200ms ease all;
|
||||
|
||||
:visited {
|
||||
color: ${Constants.system.pitchBlack};
|
||||
@ -40,155 +42,184 @@ const STYLES_META_TITLE = css`
|
||||
}
|
||||
`;
|
||||
|
||||
const STYLES_META_ITEM = css`
|
||||
display: inline-flex;
|
||||
const STYLES_TAG = css`
|
||||
margin-right: 24px;
|
||||
margin-bottom: 16px;
|
||||
padding: 0px 2px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid ${Constants.system.grayBlack};
|
||||
`;
|
||||
|
||||
const STYLES_META_DETAILS = css`
|
||||
font-family: ${Constants.font.code};
|
||||
font-size: 12px;
|
||||
color: ${Constants.system.grayBlack};
|
||||
text-transform: uppercase;
|
||||
margin-top: 24px;
|
||||
margin: 24px 0px;
|
||||
font-family: ${Constants.font.medium};
|
||||
font-size: 0.9rem;
|
||||
`;
|
||||
|
||||
const STYLES_ITEM = css`
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
padding-left: 24px;
|
||||
padding-bottom: 16px;
|
||||
`;
|
||||
|
||||
const STYLES_LEFT = css`
|
||||
color: ${Constants.system.white};
|
||||
flex-shrink: 0;
|
||||
height: 36px;
|
||||
width: 36px;
|
||||
border-radius: 100%;
|
||||
background-color: ${Constants.system.pitchBlack};
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
const STYLES_RIGHT = css`
|
||||
min-width: 10%;
|
||||
width: 100%;
|
||||
padding: 0px 24px 0 16px;
|
||||
overflow-wrap: break-word;
|
||||
`;
|
||||
|
||||
const STYLES_NAME = css`
|
||||
color: ${Constants.system.black};
|
||||
`;
|
||||
|
||||
const STYLES_DESCRIPTION = css`
|
||||
font-family: ${Constants.font.code};
|
||||
color: ${Constants.system.black};
|
||||
font-size: 12px;
|
||||
text-transform: uppercase;
|
||||
margin-top: 4px;
|
||||
display: inline-block;
|
||||
const STYLES_ACTIONS = css`
|
||||
color: ${Constants.system.darkGray};
|
||||
border: 1px solid ${Constants.system.gray};
|
||||
border-radius: 4px;
|
||||
background-color: ${Constants.system.white};
|
||||
margin-bottom: 48px;
|
||||
`;
|
||||
|
||||
const STYLES_ACTION = css`
|
||||
font-family: ${Constants.font.codeBold};
|
||||
cursor: pointer;
|
||||
margin-left: 24px;
|
||||
display: inline-block;
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid ${Constants.system.gray};
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
:hover {
|
||||
color: ${Constants.system.blue};
|
||||
color: ${Constants.system.brand};
|
||||
}
|
||||
|
||||
:last-child {
|
||||
border: none;
|
||||
}
|
||||
`;
|
||||
|
||||
const SlateItem = (props) => {
|
||||
return (
|
||||
<div css={STYLES_ITEM}>
|
||||
<div
|
||||
css={STYLES_LEFT}
|
||||
style={{
|
||||
backgroundColor: props.member ? null : Constants.system.gray,
|
||||
}}
|
||||
>
|
||||
{!props.loading ? (
|
||||
<SVG.Slate height="20px" />
|
||||
) : (
|
||||
<LoaderSpinner style={{ height: 20, width: 20 }} />
|
||||
)}
|
||||
</div>
|
||||
<div css={STYLES_RIGHT}>
|
||||
<div
|
||||
css={STYLES_NAME}
|
||||
style={{
|
||||
fontFamily: props.member ? Constants.font.semiBold : null,
|
||||
}}
|
||||
>
|
||||
{Strings.getPresentationSlateName(props.slate)}
|
||||
</div>
|
||||
const STYLES_SECTION_HEADER = css`
|
||||
font-family: ${Constants.font.semiBold};
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: 32px;
|
||||
`;
|
||||
|
||||
<div css={STYLES_DESCRIPTION}>
|
||||
{Strings.zeroPad(props.slate.data.objects.length, 4)}{" "}
|
||||
{Strings.pluralize("object", props.slate.data.objects.length)}{" "}
|
||||
{!props.member ? (
|
||||
<span
|
||||
css={STYLES_ACTION}
|
||||
onClick={() =>
|
||||
props.onAddToSlate({
|
||||
id: props.id,
|
||||
slate: props.slate,
|
||||
data: props.data,
|
||||
})
|
||||
}
|
||||
>
|
||||
Add
|
||||
</span>
|
||||
) : (
|
||||
<span
|
||||
css={STYLES_ACTION}
|
||||
onClick={() =>
|
||||
props.onRemoveFromSlate({
|
||||
id: props.id,
|
||||
slate: props.slate,
|
||||
data: props.data,
|
||||
})
|
||||
}
|
||||
>
|
||||
Remove
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
const STYLES_HIDDEN = css`
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
`;
|
||||
|
||||
export default class GlobalViewerCIDSidebarSlates extends React.Component {
|
||||
render() {
|
||||
const { id, cid, file, type, size } = this.props.data;
|
||||
_ref = null;
|
||||
|
||||
const slateElements = this.props.slates.map((s) => {
|
||||
const hasElement = s.data.objects.some((o) => o.id === id);
|
||||
const loading =
|
||||
this.props.loading &&
|
||||
this.props.loading.id &&
|
||||
this.props.loading.id === s.id;
|
||||
state = {
|
||||
selected: {},
|
||||
isPublic: false,
|
||||
copyValue: "",
|
||||
};
|
||||
|
||||
return (
|
||||
<SlateItem
|
||||
key={s.id}
|
||||
id={id}
|
||||
data={this.props.data}
|
||||
slate={s}
|
||||
member={hasElement}
|
||||
loading={loading}
|
||||
onAddToSlate={loading ? () => {} : this.props.onAddToSlate}
|
||||
onRemoveFromSlate={loading ? () => {} : this.props.onRemoveFromSlate}
|
||||
/>
|
||||
);
|
||||
componentDidMount = () => {
|
||||
let isPublic = false;
|
||||
let selected = {};
|
||||
const id = this.props.data.id;
|
||||
for (let slate of this.props.slates) {
|
||||
if (slate.data.objects.some((o) => o.id === id)) {
|
||||
if (slate.data.public) {
|
||||
isPublic = true;
|
||||
}
|
||||
selected[slate.id] = true;
|
||||
}
|
||||
}
|
||||
this.setState({ selected, isPublic });
|
||||
};
|
||||
|
||||
_handleCreateSlate = async () => {
|
||||
this.props.onClose();
|
||||
this.props.onAction({
|
||||
type: "SIDEBAR",
|
||||
value: "SIDEBAR_CREATE_SLATE",
|
||||
data: { files: [this.props.data] },
|
||||
});
|
||||
};
|
||||
|
||||
_handleAdd = (slate) => {
|
||||
if (this.state.selected[slate.id]) {
|
||||
this.props.onRemoveFromSlate({
|
||||
id: this.props.data.id,
|
||||
slate: slate,
|
||||
data: this.props.data,
|
||||
});
|
||||
this.setState({
|
||||
selected: { ...this.state.selected, [slate.id]: false },
|
||||
});
|
||||
} else {
|
||||
this.props.onAddToSlate({
|
||||
id: this.props.data.id,
|
||||
slate: slate,
|
||||
data: this.props.data,
|
||||
});
|
||||
this.setState({
|
||||
selected: { ...this.state.selected, [slate.id]: slate },
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
_handleCopy = (copyValue) => {
|
||||
this.setState({ copyValue }, () => {
|
||||
this._ref.select();
|
||||
document.execCommand("copy");
|
||||
});
|
||||
};
|
||||
|
||||
_handleDelete = async (cid) => {
|
||||
if (
|
||||
!window.confirm(
|
||||
"Are you sure you want to delete this? It will be removed from your Slates too."
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await Actions.deleteBucketItem({ cid });
|
||||
console.log(response);
|
||||
if (!response) {
|
||||
dispatchCustomEvent({
|
||||
name: "create-alert",
|
||||
detail: {
|
||||
alert: {
|
||||
message:
|
||||
"We're having trouble connecting right now. Please try again later",
|
||||
},
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (response.error) {
|
||||
dispatchCustomEvent({
|
||||
name: "create-alert",
|
||||
detail: { alert: { decorator: response.decorator } },
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.props.onClose();
|
||||
|
||||
await this.props.onRehydrate();
|
||||
|
||||
dispatchCustomEvent({
|
||||
name: "remote-update-carousel",
|
||||
detail: {},
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { cid, file, type, size, url } = this.props.data;
|
||||
console.log(this.props.data);
|
||||
|
||||
// const slateElements = this.props.slates.map((s) => {
|
||||
// const hasElement = s.data.objects.some((o) => o.id === id);
|
||||
// const loading =
|
||||
// this.props.loading &&
|
||||
// this.props.loading.id &&
|
||||
// this.props.loading.id === s.id;
|
||||
|
||||
// return (
|
||||
// <SlateItem
|
||||
// key={s.id}
|
||||
// id={id}
|
||||
// data={this.props.data}
|
||||
// slate={s}
|
||||
// member={hasElement}
|
||||
// loading={loading}
|
||||
// onAddToSlate={loading ? () => {} : this.props.onAddToSlate}
|
||||
// onRemoveFromSlate={loading ? () => {} : this.props.onRemoveFromSlate}
|
||||
// />
|
||||
// );
|
||||
// });
|
||||
|
||||
return (
|
||||
<div css={STYLES_CONTAINER}>
|
||||
@ -198,15 +229,48 @@ export default class GlobalViewerCIDSidebarSlates extends React.Component {
|
||||
target="_blank"
|
||||
href={Strings.getCIDGatewayURL(cid)}
|
||||
>
|
||||
{Strings.getCIDGatewayURL(cid)}
|
||||
{file}
|
||||
</a>
|
||||
<div css={STYLES_META_DETAILS}>
|
||||
<span css={STYLES_META_ITEM}>{file}</span>{" "}
|
||||
<span css={STYLES_META_ITEM}>{type}</span>{" "}
|
||||
<span css={STYLES_META_ITEM}>{Strings.bytesToSize(size)}</span>
|
||||
<span css={STYLES_TAG}>{type}</span>{" "}
|
||||
<span>{Strings.bytesToSize(size)}</span>
|
||||
</div>
|
||||
</div>
|
||||
{slateElements}
|
||||
<div css={STYLES_ACTIONS}>
|
||||
<div css={STYLES_ACTION} onClick={() => this._handleCopy(cid)}>
|
||||
<SVG.CopyAndPaste height="24px" />
|
||||
<span style={{ marginLeft: 16 }}>Copy file CID</span>
|
||||
</div>
|
||||
<div css={STYLES_ACTION} onClick={() => this._handleCopy(url)}>
|
||||
<SVG.DeepLink height="24px" />
|
||||
<span style={{ marginLeft: 16 }}>Copy link</span>
|
||||
</div>
|
||||
{/* <div css={STYLES_ACTION} onClick={this.props.onDownload}>
|
||||
<SVG.Download height="24px" />
|
||||
<span style={{ marginLeft: 16 }}>Download</span>
|
||||
</div> */}
|
||||
<div css={STYLES_ACTION} onClick={() => this._handleDelete(cid)}>
|
||||
<SVG.Trash height="24px" />
|
||||
<span style={{ marginLeft: 16 }}>Delete</span>
|
||||
</div>
|
||||
</div>
|
||||
<div css={STYLES_SECTION_HEADER}>Connected Slates</div>
|
||||
<SlatePicker
|
||||
slates={this.props.slates}
|
||||
selected={this.state.selected}
|
||||
onAdd={this._handleAdd}
|
||||
onCreateSlate={this._handleCreateSlate}
|
||||
loading={this.props.loading}
|
||||
style={{ maxHeight: "300px" }}
|
||||
/>
|
||||
<input
|
||||
css={STYLES_HIDDEN}
|
||||
ref={(c) => {
|
||||
this._ref = c;
|
||||
}}
|
||||
readOnly
|
||||
value={this.state.copyValue}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import {
|
||||
ButtonPrimary,
|
||||
ButtonDisabled,
|
||||
} from "~/components/system/components/Buttons";
|
||||
import { SlatePicker } from "~/components/core/SlatePicker";
|
||||
|
||||
const STYLES_SLATE_NAME = css`
|
||||
overflow: hidden;
|
||||
@ -150,59 +151,14 @@ export default class SidebarAddFileToSlate extends React.Component {
|
||||
</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,
|
||||
pointerEvents: "none",
|
||||
}}
|
||||
|
||||
<SlatePicker
|
||||
slates={this.props.viewer.slates}
|
||||
selected={this.state.selected}
|
||||
onAdd={this._handleAdd}
|
||||
onCreateSlate={this._handleCreateSlate}
|
||||
/>
|
||||
<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, pointerEvents: "none" }}
|
||||
/>
|
||||
) : (
|
||||
<SVG.PlusCircle
|
||||
height="24px"
|
||||
style={{
|
||||
color: Constants.system.darkGray,
|
||||
marginRight: 8,
|
||||
pointerEvents: "none",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</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>
|
||||
|
||||
{Object.keys(this.state.selected).length ? (
|
||||
<ButtonPrimary
|
||||
full
|
||||
|
@ -34,6 +34,7 @@ export default async (req, res) => {
|
||||
.status(500)
|
||||
.send({ decorator: "SERVER_REMOVE_DATA_NO_CID", error: true });
|
||||
}
|
||||
console.log(req.body.data.cid);
|
||||
|
||||
const id = Utilities.getIdFromCookie(req);
|
||||
if (!id) {
|
||||
@ -46,10 +47,14 @@ export default async (req, res) => {
|
||||
id,
|
||||
});
|
||||
|
||||
console.log("got here 1");
|
||||
|
||||
const { buckets, bucketKey } = await Utilities.getBucketAPIFromUserToken({
|
||||
user,
|
||||
});
|
||||
|
||||
console.log("got here 2");
|
||||
|
||||
if (!buckets) {
|
||||
return res.status(500).send({
|
||||
decorator: "SERVER_BUCKET_INIT_FAILURE",
|
||||
@ -77,6 +82,8 @@ export default async (req, res) => {
|
||||
.send({ decorator: "SERVER_REMOVE_DATA_NO_TEXTILE", error: true });
|
||||
}
|
||||
|
||||
console.log("got here 3");
|
||||
|
||||
// TODO(jim): Put this call into a file for all Textile related calls.
|
||||
let items = null;
|
||||
try {
|
||||
@ -105,6 +112,8 @@ export default async (req, res) => {
|
||||
}
|
||||
}
|
||||
|
||||
console.log("got here 4");
|
||||
|
||||
if (!entity) {
|
||||
return res
|
||||
.status(500)
|
||||
@ -128,6 +137,8 @@ export default async (req, res) => {
|
||||
.send({ decorator: "SERVER_REMOVE_DATA_NO_LINK", error: true });
|
||||
}
|
||||
|
||||
console.log("got here 5");
|
||||
|
||||
// NOTE(jim):
|
||||
// Goes through all of your slates and removes all data references.
|
||||
const slates = await Data.getSlatesByUserId({ userId: id });
|
||||
@ -157,6 +168,8 @@ export default async (req, res) => {
|
||||
}
|
||||
}
|
||||
|
||||
console.log("got here 6");
|
||||
|
||||
// NOTE(jim):
|
||||
// Removes the file reference from your library
|
||||
const response = await Data.updateUserById({
|
||||
|
@ -111,7 +111,6 @@ function UserEntry({ user, button, onClick, message }) {
|
||||
const STYLES_COPY_INPUT = css`
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
tabindex: -1;
|
||||
opacity: 0;
|
||||
`;
|
||||
|
||||
@ -517,6 +516,7 @@ export default class SceneDirectory extends React.Component {
|
||||
this._ref = c;
|
||||
}}
|
||||
value={this.state.copyValue}
|
||||
tabIndex="-1"
|
||||
css={STYLES_COPY_INPUT}
|
||||
/>
|
||||
</ScenePage>
|
||||
|
Loading…
Reference in New Issue
Block a user