Merge pull request #872 from filecoin-project/@aminejv/remove-slate-layout

Chore: Remove Slate Layout
This commit is contained in:
martinalong 2021-08-16 17:06:31 -07:00 committed by GitHub
commit 123c59850a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 233 additions and 2160 deletions

View File

@ -340,14 +340,6 @@ export const updateSlate = async (data) => {
});
};
export const updateSlateLayout = async (data) => {
await Websockets.checkWebsocket();
return await returnJSON(`/api/slates/update-layout`, {
...DEFAULT_OPTIONS,
body: JSON.stringify({ data }),
});
};
export const deleteSlate = async (data) => {
await Websockets.checkWebsocket();
return await returnJSON(`/api/slates/delete`, {

View File

@ -1,4 +1,4 @@
export const NODE_ENV = process.env.NEXT_PUBLIC_NODE_ENV;
export const NODE_ENV = process.env.NEXT_PUBLIC_NODE_ENV || "development";
//NOTE(amine): feature flags
export const ACTIVITY_FEATURE_FLAG = NODE_ENV === "development" || NODE_ENV === "staging";

View File

@ -108,12 +108,6 @@ export const error = {
SERVER_REMOVE_FROM_SLATE_SLATE_NOT_FOUND: "We are having trouble locating that collection",
SERVER_REMOVE_FROM_SLATE_FAILED: "We are having trouble removing from that collection right now",
//Update slate layout
SERVER_UPDATE_SLATE_LAYOUT_MUST_PROVIDE_DATA: "No layout was provided to update",
SERVER_UPDATE_SLATE_LAYOUT_NOT_FOUND: "We are having trouble locating that collection",
SERVER_UPDATE_SLATE_LAYOUT:
"We are unable to update that collection's layout right now. Please try again later",
//Update slate
SERVER_UPDATE_SLATE_MUST_PROVIDE_DATA:
"We are unable to update that collection because no data was provided",

View File

@ -287,6 +287,96 @@ class Tags extends React.Component {
}
}
function Footer({
type = "myslate",
close,
isOwner,
totalSelectedFiles,
addToCollection,
downloadFiles,
deleteFiles,
//NOTE(amine): Myslate actions
editTags,
//NOTE(amine): Collection actions
removeFromCollection,
saveCopy,
}) {
const totalFiles = `${totalSelectedFiles} ${Strings.pluralize(
"file",
totalSelectedFiles
)} selected`;
const isCollectionType = type === "collection";
return (
<React.Fragment>
<div css={STYLES_ACTION_BAR_CONTAINER}>
<div css={STYLES_ACTION_BAR}>
<div css={STYLES_LEFT}>
<span css={STYLES_FILES_SELECTED}>{totalFiles}</span>
</div>
<div css={STYLES_RIGHT}>
<ButtonPrimary
transparent
style={{ color: Constants.system.white }}
onClick={addToCollection}
>
Add to collection
</ButtonPrimary>
{isOwner && !isCollectionType && (
<ButtonPrimary
transparent
style={{ color: Constants.system.white }}
onClick={editTags}
>
Edit tags
</ButtonPrimary>
)}
{!isOwner && isCollectionType && (
<ButtonPrimary
transparent
onClick={saveCopy}
style={{ color: Constants.system.white }}
>
Save
</ButtonPrimary>
)}
{isOwner && (
<ButtonWarning
transparent
style={{ marginLeft: 8, color: Constants.system.white }}
onClick={downloadFiles}
>
Download
</ButtonWarning>
)}
{isOwner && isCollectionType && (
<ButtonWarning
transparent
style={{ marginLeft: 8, color: Constants.system.white }}
onClick={removeFromCollection}
>
Remove
</ButtonWarning>
)}
{isOwner && (
<ButtonWarning
transparent
style={{ marginLeft: 8, color: Constants.system.white }}
onClick={deleteFiles}
>
Delete
</ButtonWarning>
)}
<div css={STYLES_ICON_BOX} onClick={close}>
<SVG.Dismiss height="20px" style={{ color: Constants.system.grayLight2 }} />
</div>
</div>
</div>
</div>
</React.Fragment>
);
}
export default class DataView extends React.Component {
_mounted = false;
@ -295,8 +385,8 @@ export default class DataView extends React.Component {
checked: {},
viewLimit: 40,
scrollDebounce: false,
imageSize: 100,
modalShow: false,
items: this.props.items,
};
isShiftDown = false;
@ -305,8 +395,6 @@ export default class DataView extends React.Component {
gridWrapperEl = React.createRef();
async componentDidMount() {
this.calculateWidth();
this.debounceInstance = Window.debounce(this.calculateWidth, 200);
if (!this._mounted) {
this._mounted = true;
window.addEventListener("scroll", this._handleCheckScroll);
@ -332,17 +420,6 @@ export default class DataView extends React.Component {
}
}
calculateWidth = () => {
let windowWidth = window.innerWidth;
let imageSize;
if (windowWidth < Constants.sizes.mobile) {
imageSize = (windowWidth - 2 * 24 - 20) / 2;
} else {
imageSize = (windowWidth - 2 * 56 - 4 * 20) / 5;
}
this.setState({ imageSize });
};
_handleScroll = (e) => {
const windowHeight =
"innerHeight" in window ? window.innerHeight : document.documentElement.offsetHeight;
@ -467,21 +544,30 @@ export default class DataView extends React.Component {
this.setState({ checked: {} });
};
_handleDelete = (res, id) => {
_handleDelete = (res) => {
if (!res) {
this.setState({ modalShow: false });
return;
}
let ids;
if (id) {
ids = [id];
} else {
ids = Object.keys(this.state.checked).map((id) => {
let index = parseInt(id);
let item = this.props.viewer.library[index];
return item.id;
});
const ids = Object.keys(this.state.checked).map((id) => {
let index = parseInt(id);
let item = this.props.viewer.library[index];
return item.id;
});
// NOTE(amine): delete files from current collection
if (this.props.collection) {
const { slates } = this.props.viewer;
const slateId = this.props.collection.id;
for (let slate of slates) {
if (slate.id === slateId) {
slate.objects = slate.objects.filter((obj) => !ids.includes(obj.id));
slate.fileCount = slate.objects.length;
break;
}
}
this.props.onAction({ type: "UPDATE_VIEWER", viewer: { slates } });
}
let library = this.props.viewer.library.filter((obj) => !ids.includes(obj.id));
@ -563,6 +649,57 @@ export default class DataView extends React.Component {
e.dataTransfer.setData("DownloadURL", `${type}:${title}:${url}`);
};
_handleCloseFooter = () => {
this.setState({ checked: {} });
this.lastSelectedItemIndex = null;
};
_handleRemoveFromCollection = (e, i) => {
e.stopPropagation();
e.preventDefault();
let ids = [];
if (i !== undefined) {
ids = [this.state.items[i].id.replace("data-", "")];
} else {
for (let index of Object.keys(this.state.checked)) {
ids.push(this.state.items[index].id.replace("data-", ""));
}
this.setState({ checked: {} });
}
let { slates } = this.props.viewer;
let slateId = this.props.collection.id;
for (let slate of slates) {
if (slate.id === slateId) {
slate.objects = slate.objects.filter((obj) => !ids.includes(obj.id.replace("data-", "")));
slate.fileCount = slate.objects.length;
this.props.onAction({ type: "UPDATE_VIEWER", viewer: { slates } });
break;
}
}
UserBehaviors.removeFromSlate({ slate: this.props.collection, ids });
};
_handleSaveCopy = async (e, i) => {
if (!this.props.viewer) {
Events.dispatchCustomEvent({ name: "slate-global-open-cta", detail: {} });
return;
}
e.stopPropagation();
e.preventDefault();
let items = [];
if (i !== undefined) {
items = [this.state.items[i]];
} else {
this.setState({ checked: {} });
for (let i of Object.keys(this.state.checked)) {
items.push(this.state.items[i]);
}
}
UserBehaviors.saveCopy({ files: items });
};
getCommonTagFromSelectedItems = () => {
const { items } = this.props;
const { checked } = this.state;
@ -626,82 +763,46 @@ export default class DataView extends React.Component {
// </span>
// </div>
// );
const handleEditTags = () => {
this.props.onAction({
type: "SIDEBAR",
value: "SIDEBAR_EDIT_TAGS",
data: {
numChecked,
commonTags: this.getCommonTagFromSelectedItems(),
objects: this.props.items,
checked: this.state.checked,
},
});
};
const footer = (
<React.Fragment>
{numChecked ? (
<div css={STYLES_ACTION_BAR_CONTAINER}>
<div css={STYLES_ACTION_BAR}>
<div css={STYLES_LEFT}>
<span css={STYLES_FILES_SELECTED}>
{numChecked} file{numChecked > 1 ? "s" : ""} selected
</span>
</div>
<div css={STYLES_RIGHT}>
<ButtonPrimary
transparent
style={{ color: Constants.system.white }}
onClick={this._handleAddToSlate}
>
Add to collection
</ButtonPrimary>
{this.props.isOwner && (
<ButtonPrimary
transparent
style={{ color: Constants.system.white }}
onClick={() => {
this.props.onAction({
type: "SIDEBAR",
value: "SIDEBAR_EDIT_TAGS",
data: {
numChecked,
commonTags: this.getCommonTagFromSelectedItems(),
objects: this.props.items,
checked: this.state.checked,
},
});
}}
>
Edit tags
</ButtonPrimary>
)}
<ButtonWarning
transparent
style={{ marginLeft: 8, color: Constants.system.white }}
onClick={() => this._handleDownloadFiles()}
>
Download
</ButtonWarning>
{this.props.isOwner && (
<ButtonWarning
transparent
style={{ marginLeft: 8, color: Constants.system.white }}
onClick={() => this.setState({ modalShow: true })}
>
Delete
</ButtonWarning>
)}
{this.state.modalShow && (
<ConfirmationModal
type={"DELETE"}
withValidation={false}
callback={this._handleDelete}
header={`Are you sure you want to delete the selected files?`}
subHeader={`These files will be deleted from all connected collections and your file library. You cant undo this action.`}
/>
)}
<div
css={STYLES_ICON_BOX}
onClick={() => {
this.setState({ checked: {} });
this.lastSelectedItemIndex = null;
}}
>
<SVG.Dismiss height="20px" style={{ color: Constants.system.grayLight2 }} />
</div>
</div>
</div>
</div>
<>
<Footer
type={this.props.type}
totalSelectedFiles={numChecked}
isOwner={this.props.isOwner}
addToCollection={this._handleAddToSlate}
downloadFiles={this._handleDownloadFiles}
deleteFiles={() => this.setState({ modalShow: true })}
close={this._handleCloseFooter}
//NOTE(amine): Myslate actions
editTags={handleEditTags}
//NOTE(amine): Collection actions
removeFromCollection={this._handleRemoveFromCollection}
saveCopy={this._handleSaveCopy}
/>
{this.state.modalShow && (
<ConfirmationModal
type={"DELETE"}
withValidation={false}
callback={this._handleDelete}
header={`Are you sure you want to delete the selected files?`}
subHeader={`These files will be deleted from all connected collections and your file library. You cant undo this action.`}
/>
)}
</>
) : null}
</React.Fragment>
);
@ -734,7 +835,6 @@ export default class DataView extends React.Component {
<ObjectPreview
viewer={this.props.viewer}
file={each}
owner={this.props.user}
onAction={this.props.onAction}
isSelected={i in this.state.checked}
/>

File diff suppressed because it is too large Load Diff

View File

@ -1,54 +0,0 @@
import * as React from "react";
import * as Constants from "~/common/constants";
import SlateMediaObjectPreview from "~/components/core/SlateMediaObjectPreview";
import { css } from "@emotion/react";
const STYLES_LAYOUT = css`
display: flex;
flex-direction: column;
margin-top: 48px;
`;
const STYLES_IMAGE_CONTAINER = css`
margin-bottom: 24px;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
`;
export class SlateLayoutMobile extends React.Component {
render() {
return (
<div css={STYLES_LAYOUT}>
{this.props.items.map((item, i) => (
<div
key={item.id}
css={STYLES_IMAGE_CONTAINER}
style={{
width: `calc(100vw - 48px)`,
}}
onClick={() => this.props.onSelect(i)}
>
<SlateMediaObjectPreview
file={item}
iconOnly={this.props.fileNames}
charCap={70}
style={{
height: `calc(100vw - 48px)`,
width: `calc(100vw - 48px)`,
background: Constants.system.white,
}}
imageStyle={{
maxWidth: `calc(100vw - 48px)`,
maxHeight: `calc(100vw - 48px)`,
}}
/>
</div>
))}
</div>
);
}
}

View File

@ -6,6 +6,7 @@ import * as Validations from "~/common/validations";
import * as Actions from "~/common/actions";
import * as Events from "~/common/custom-events";
import * as SVG from "~/common/svg";
import * as UserBehaviors from "~/common/user-behaviors";
import { RadioGroup } from "~/components/system/components/RadioGroup";
import { css } from "@emotion/react";

View File

@ -1,5 +1,5 @@
/* eslint-disable prefer-destructuring */
export const NODE_ENV = process.env.NEXT_PUBLIC_NODE_ENV;
export const NODE_ENV = process.env.NODE_ENV || "development";
export const IS_PRODUCTION = NODE_ENV === "production";
export const PORT = process.env.PORT || 1337;
export const SOURCE = process.env.SOURCE;

View File

@ -34,7 +34,6 @@ export const sanitizeSlate = (entity) => {
name: entity.data?.name,
body: entity.data?.body,
preview: entity.data?.preview,
layouts: entity.data?.layouts,
tags: entity.data?.tags,
},
fileCount: entity.fileCount,
@ -110,7 +109,6 @@ export const cleanSlate = (entity) => {
// name: entity.data?.name,
// body: entity.data?.body,
// preview: entity.data?.preview,
// layouts: entity.data?.layouts,
// tags: entity.data?.tags,
// },
};

View File

@ -11,8 +11,6 @@ import * as UserBehaviors from "~/common/user-behaviors";
import { ButtonSecondary } from "~/components/system/components/Buttons";
import { css } from "@emotion/react";
import { ViewAllButton } from "~/components/core/ViewAll";
import { SlateLayout } from "~/components/core/SlateLayout";
import { SlateLayoutMobile } from "~/components/core/SlateLayoutMobile";
import { GlobalCarousel } from "~/components/system/components/GlobalCarousel";
import { GlobalModal } from "~/components/system/components/GlobalModal";
@ -21,6 +19,7 @@ import WebsitePrototypeWrapper from "~/components/core/WebsitePrototypeWrapper";
import WebsitePrototypeHeader from "~/components/core/WebsitePrototypeHeader";
import WebsitePrototypeFooter from "~/components/core/WebsitePrototypeFooter";
import CTATransition from "~/components/core/CTATransition";
import DataView from "~/components/core/DataView";
const DEFAULT_IMAGE =
"https://slate.textile.io/ipfs/bafkreiaow45dlq5xaydaeqocdxvffudibrzh2c6qandpqkb6t3ahbvh6re";
@ -199,13 +198,6 @@ export default class SlatePage extends React.Component {
});
};
_handleSave = async (layouts) => {
await Actions.updateSlateLayout({
id: this.props.slate.id,
layouts,
});
};
_handleDownloadFiles = () => {
const slateName = this.props.slate.data.name;
const slateFiles = this.props.slate.data.objects;
@ -221,7 +213,7 @@ export default class SlatePage extends React.Component {
let headerURL = `https://slate.host/${this.props.creator.username}`;
let { objects, isPublic } = this.props.slate;
let { layouts, body, preview } = this.props.slate.data;
let { body, preview } = this.props.slate.data;
let image;
if (Strings.isEmpty(this.props.cid)) {
image = preview;
@ -326,30 +318,21 @@ export default class SlatePage extends React.Component {
isOwner={false}
external
/>
{this.props.isMobile ? (
<SlateLayoutMobile
isOwner={false}
items={objects}
fileNames={layouts && layouts.ver === "2.0" ? layouts.fileNames : false}
onSelect={this._handleSelect}
external
/>
) : (
<SlateLayout
external
slateId={this.props.slate.id}
key={this.props.slate.id}
layout={layouts && layouts.ver === "2.0" ? layouts.layout : null}
onSaveLayout={this._handleSave}
isOwner={false}
fileNames={layouts && layouts.ver === "2.0" ? layouts.fileNames : false}
items={objects}
onSelect={this._handleSelect}
defaultLayout={layouts && layouts.ver === "2.0" ? layouts.defaultLayout : true}
creator={this.props.creator}
slate={this.props.slate}
/>
)}
{
<div style={{ marginTop: 40 }}>
<DataView
key="scene-collection"
type="collection"
collection={this.props.slate}
onAction={this.props.onAction}
viewer={this.props.viewer}
items={objects}
view={"grid"}
isOwner={false}
page={this.props.page}
/>
</div>
}
</div>
</div>
<GlobalModal />

View File

@ -1,47 +0,0 @@
import * as Utilities from "~/node_common/utilities";
import * as Data from "~/node_common/data";
import * as Strings from "~/common/strings";
import * as ViewerManager from "~/node_common/managers/viewer";
export default async (req, res) => {
if (!req.body.data) {
return res.status(500).send({
decorator: "SERVER_UPDATE_SLATE_LAYOUT_MUST_PROVIDE_DATA",
error: true,
});
}
const slate = await Data.getSlateById({ id: req.body.data.id });
if (!slate) {
return res.status(404).send({ decorator: "SERVER_UPDATE_SLATE_LAYOUT_NOT_FOUND", error: true });
}
if (slate.error) {
return res.status(500).send({ decorator: "SERVER_UPDATE_SLATE_LAYOUT_NOT_FOUND", error: true });
}
let update = await Data.updateSlateById({
id: slate.id,
data: {
...slate.data,
layouts: req.body.data.layouts,
},
});
if (!update) {
return res.status(404).send({ decorator: "SERVER_UPDATE_SLATE_LAYOUT", error: true });
}
if (update.error) {
return res.status(500).send({ decorator: "SERVER_UPDATE_SLATE_LAYOUT", error: true });
}
const id = Utilities.getIdFromCookie(req);
if (id && slate.ownerId === id) {
ViewerManager.hydratePartial(id, { slates: true });
}
return res.status(200).send({ decorator: "SERVER_UPDATE_SLATE_LAYOUT", slate });
};

View File

@ -55,7 +55,6 @@ export default async (req, res) => {
public: slate.isPublic,
objects: reformattedObjects,
ownerId: slate.ownerId,
layouts: slate.data.layouts,
},
};

View File

@ -60,7 +60,6 @@ export default async (req, res) => {
public: slate.isPublic,
objects: reformattedObjects,
ownerId: slate.ownerId,
layouts: slate.data.layouts,
},
};
});

View File

@ -468,7 +468,6 @@ export default class SceneFilesFolder extends React.Component {
key="scene-files-folder"
onAction={this.props.onAction}
viewer={this.props.viewer}
user={this.props.viewer}
items={files}
view={tab}
isOwner={true}

View File

@ -12,8 +12,6 @@ import * as Events from "~/common/custom-events";
import { Link } from "~/components/core/Link";
import { LoaderSpinner } from "~/components/system/components/Loaders";
import { css } from "@emotion/react";
import { SlateLayout } from "~/components/core/SlateLayout";
import { SlateLayoutMobile } from "~/components/core/SlateLayoutMobile";
import { FileTypeGroup } from "~/components/core/FileTypeIcon";
import { ButtonPrimary, ButtonSecondary } from "~/components/system/components/Buttons";
import { GlobalCarousel } from "~/components/system/components/GlobalCarousel";
@ -24,6 +22,7 @@ import ScenePage from "~/components/core/ScenePage";
import ScenePageHeader from "~/components/core/ScenePageHeader";
import SquareButtonGray from "~/components/core/SquareButtonGray";
import EmptyState from "~/components/core/EmptyState";
import DataView from "~/components/core/DataView";
const STYLES_LOADER = css`
display: flex;
@ -322,17 +321,6 @@ class SlatePage extends React.Component {
});
};
_handleSaveLayout = async (layouts, autoSave) => {
const response = await Actions.updateSlateLayout({
id: this.props.data.id,
layouts,
});
if (!autoSave) {
Events.hasError(response);
}
};
_handleSavePreview = async (preview) => {
if (!this.props.viewer) {
return;
@ -409,7 +397,6 @@ class SlatePage extends React.Component {
const { user, data } = this.props.data;
const { body = "", preview } = data;
let objects = this.props.data.objects;
let layouts = this.props.data.data.layouts;
const isPublic = this.props.data.isPublic;
const isOwner = this.props.viewer ? this.props.data.ownerId === this.props.viewer.id : false;
const tags = data.tags;
@ -503,35 +490,20 @@ class SlatePage extends React.Component {
index={this.state.index}
onChange={(index) => this.setState({ index })}
/>
{this.props.isMobile ? (
<SlateLayoutMobile
isOwner={isOwner}
<div style={{ marginTop: 40 }}>
<DataView
key="scene-files-folder"
type="collection"
collection={this.props.data}
onAction={this.props.onAction}
viewer={this.props.viewer}
items={objects}
fileNames={layouts && layouts.ver === "2.0" ? layouts.fileNames : false}
onSelect={this._handleSelect}
view={"grid"}
resources={this.props.resources}
isOwner={isOwner}
page={this.props.page}
/>
) : (
<div style={{ marginTop: isOwner ? 24 : 48 }}>
<SlateLayout
page={this.props.page}
external={this.props.external}
key={this.props.data.id}
data={this.props.data}
viewer={this.props.viewer}
slateId={this.props.data.id}
layout={layouts && layouts.ver === "2.0" ? layouts.layout || [] : null}
onSaveLayout={this._handleSaveLayout}
isOwner={isOwner}
fileNames={layouts && layouts.ver === "2.0" ? layouts.fileNames : false}
preview={preview}
onSavePreview={this._handleSavePreview}
items={objects}
onSelect={this._handleSelect}
defaultLayout={layouts && layouts.ver === "2.0" ? layouts.defaultLayout : true}
onAction={this.props.onAction}
/>
</div>
)}
</div>
</>
) : isOwner ? (
<div>

View File

@ -534,26 +534,14 @@ const cleanUsersTable = async () => {
const cleanSlatesTable = async () => {
const slates = await DB.select("*").from("slates");
for (let slate of slates) {
const id = slate.id;
let layouts = slate.data.layouts;
if (layouts && layouts.ver === "2.0" && layouts.layout) {
for (let position of layouts.layout) {
if (position.id) {
position.id = position.id.replace("data-", "");
}
}
} else {
layouts = null;
}
let data = {
layouts,
body: slate.data.body,
name: slate.data.name,
preview: slate.data.preview,
tags: slate.data.tags,
};
// Logging.log(layouts?.layout);
// Logging.log(data);
const { id } = slate;
await DB.from("slates").where("id", id).update({ data });
}
};