diff --git a/common/validations.js b/common/validations.js
index 43088e62..aa05ccbb 100644
--- a/common/validations.js
+++ b/common/validations.js
@@ -26,3 +26,15 @@ export const password = (text) => {
return true;
};
+
+export const isFileTypeAllowed = (type = "") => {
+ if (type.startsWith("application/pdf")) {
+ return true;
+ }
+
+ if (type.startsWith("image/")) {
+ return true;
+ }
+
+ return false;
+};
diff --git a/components/core/Application.js b/components/core/Application.js
index a80d01ae..feed6a8a 100644
--- a/components/core/Application.js
+++ b/components/core/Application.js
@@ -3,6 +3,7 @@ import * as NavigationData from "~/common/navigation-data";
import * as Actions from "~/common/actions";
import * as State from "~/common/state";
import * as Credentials from "~/common/credentials";
+import * as Validations from "~/common/validations";
// NOTE(jim):
// Scenes each have an ID and can be navigated to with _handleAction
@@ -11,7 +12,6 @@ import SceneEditAccount from "~/scenes/SceneEditAccount";
import SceneFile from "~/scenes/SceneFile";
import SceneFilesFolder from "~/scenes/SceneFilesFolder";
import SceneHome from "~/scenes/SceneHome";
-import SceneMiners from "~/scenes/SceneMiners";
import SceneSettings from "~/scenes/SceneSettings";
import SceneWallet from "~/scenes/SceneWallet";
import SceneSlates from "~/scenes/SceneSlates";
@@ -26,7 +26,6 @@ import SidebarCreateSlate from "~/components/sidebars/SidebarCreateSlate";
import SidebarCreateWalletAddress from "~/components/sidebars/SidebarCreateWalletAddress";
import SidebarWalletSendFunds from "~/components/sidebars/SidebarWalletSendFunds";
import SidebarFileStorageDeal from "~/components/sidebars/SidebarFileStorageDeal";
-import SidebarCreatePaymentChannel from "~/components/sidebars/SidebarCreatePaymentChannel";
import SidebarAddFileToBucket from "~/components/sidebars/SidebarAddFileToBucket";
// NOTE(jim):
@@ -68,7 +67,7 @@ export default class ApplicationPage extends React.Component {
this.setState({ fileLoading: true });
let data = new FormData();
- data.append("image", file);
+ data.append("data", file);
const options = {
method: "POST",
@@ -156,7 +155,9 @@ export default class ApplicationPage extends React.Component {
if (e.dataTransfer.items[i].kind === "file") {
var file = e.dataTransfer.items[i].getAsFile();
- await this._handleSetFile({ file, slate });
+ if (Validations.isFileTypeAllowed(file.type)) {
+ await this._handleSetFile({ file, slate });
+ }
break;
}
}
diff --git a/components/core/MediaObject.js b/components/core/MediaObject.js
new file mode 100644
index 00000000..1bdc37bb
--- /dev/null
+++ b/components/core/MediaObject.js
@@ -0,0 +1,69 @@
+import * as React from "react";
+import * as Constants from "~/common/constants";
+
+import { css } from "@emotion/react";
+
+const STYLES_FAILURE = css`
+ background-color: ${Constants.system.pitchBlack};
+ color: ${Constants.system.white};
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 88px;
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ min-height: 10%;
+ height: 100%;
+`;
+
+const STYLES_OBJECT = css`
+ display: block;
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ min-height: 10%;
+ height: 100%;
+`;
+
+const STYLES_ASSET = css`
+ background-color: ${Constants.system.pitchBlack};
+ width: 100%;
+ margin: 0;
+ padding: 0;
+ min-height: 10%;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ position: relative;
+`;
+
+const STYLES_IMAGE = css`
+ display: block;
+ max-width: 100%;
+ max-height: 100%;
+`;
+
+export default class MediaObject extends React.Component {
+ render() {
+ const name = `${this.props.data.name}`;
+ const url = this.props.data.url ? this.props.data.url : `https://hub.textile.io${this.props.data.ipfs}`;
+
+ let mediaElement =
No Preview
;
+
+ if (this.props.data.type.startsWith("application/pdf")) {
+ mediaElement = ;
+ }
+
+ if (this.props.data.type.startsWith("image/")) {
+ mediaElement = (
+
+
+
+ );
+ }
+
+ return mediaElement;
+ }
+}
diff --git a/components/sidebars/SidebarAddFileToBucket.js b/components/sidebars/SidebarAddFileToBucket.js
index 4a84791f..e12771a8 100644
--- a/components/sidebars/SidebarAddFileToBucket.js
+++ b/components/sidebars/SidebarAddFileToBucket.js
@@ -1,8 +1,7 @@
import * as React from "react";
-import * as Strings from "~/common/strings";
import * as Constants from "~/common/constants";
-import * as SVG from "~/components/system/svg";
import * as System from "~/components/system";
+import * as Validations from "~/common/validations";
import { css } from "@emotion/react";
@@ -49,36 +48,31 @@ export default class SidebarAddFileToBucket extends React.Component {
let file = e.target.files[0];
if (!file) {
- alert("Something went wrong");
+ alert("TODO: Something went wrong");
+ return;
+ }
+
+ const isAllowed = Validations.isFileTypeAllowed(file.type);
+ if (!isAllowed) {
+ alert("TODO: File type is not allowed, yet.");
return;
}
await this.props.onSetFile({
file,
- slate:
- this.props.data && this.props.data.slateId
- ? { id: this.props.data.slateId }
- : null,
+ slate: this.props.data && this.props.data.slateId ? { id: this.props.data.slateId } : null,
});
};
render() {
return (
-
- Upload a file to Slate
-
-
+ Upload a file to Slate
+
{this.props.data && this.props.data.decorator === "SLATE" ? (
- This will add an image to your Slate named{" "}
- {this.props.data.slatename} .
+ This will add an image to your Slate named {this.props.data.slatename} .
) : null}
@@ -86,16 +80,12 @@ export default class SidebarAddFileToBucket extends React.Component {
type="label"
htmlFor="file"
style={{ marginTop: 24 }}
- loading={this.props.fileLoading}
- >
+ loading={this.props.fileLoading}>
Add file
{!this.props.fileLoading ? (
-
+
Cancel
) : null}
diff --git a/node_common/upload.js b/node_common/upload.js
index aed8a741..a2883914 100644
--- a/node_common/upload.js
+++ b/node_common/upload.js
@@ -19,32 +19,30 @@ export const formMultipart = (req, res, { user }) =>
});
}
- if (!files.image) {
+ console.log(files);
+
+ if (!files.data) {
return reject({
- decorator: "SERVER_UPLOAD_NOT_IMAGE_TYPE",
+ decorator: "SERVER_UPLOAD_ERROR",
error: true,
message: files,
});
}
- const path = files.image._writeStream.path;
+ const path = files.data._writeStream.path;
const localPath = `./${path}`;
- const data = LibraryManager.createLocalDataIncomplete(files.image);
+ const data = LibraryManager.createLocalDataIncomplete(files.data);
- const {
- buckets,
- bucketKey,
- bucketName,
- } = await Utilities.getBucketAPIFromUserToken(user.data.tokens.api);
+ const { buckets, bucketKey, bucketName } = await Utilities.getBucketAPIFromUserToken(user.data.tokens.api);
let readFile;
let push;
- // TODO(jim): Send this file to buckets.
try {
- // NOTE(jim): Push pathPath to your bucket.
readFile = await FS.readFileSync(path).buffer;
push = await buckets.pushPath(bucketKey, data.name, readFile);
} catch (e) {
+ await FS.unlinkSync(localPath);
+
return reject({
decorator: "SERVER_BUCKETS_PUSH_ISSUE",
error: true,
diff --git a/pages/api/slates/add-url.js b/pages/api/slates/add-url.js
index fc321b92..c2b8f3a8 100644
--- a/pages/api/slates/add-url.js
+++ b/pages/api/slates/add-url.js
@@ -1,8 +1,6 @@
import * as MW from "~/node_common/middleware";
import * as Utilities from "~/node_common/utilities";
import * as Data from "~/node_common/data";
-import * as Strings from "~/common/strings";
-import * as Powergate from "~/node_common/powergate";
const initCORS = MW.init(MW.CORS);
const initAuth = MW.init(MW.RequireCookieAuthentication);
@@ -13,9 +11,7 @@ export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
if (!id) {
- return res
- .status(403)
- .json({ decorator: "SERVER_ADD_TO_SLATE_USER_NOT_FOUND", error: true });
+ return res.status(403).json({ decorator: "SERVER_ADD_TO_SLATE_USER_NOT_FOUND", error: true });
}
const user = await Data.getUserById({
@@ -62,6 +58,7 @@ export default async (req, res) => {
id: req.body.data.id,
ownerId: user.id,
name: req.body.data.name,
+ type: req.body.data.type,
url: `https://hub.textile.io${req.body.data.ipfs}`,
},
...slate.data.objects,
@@ -83,7 +80,5 @@ export default async (req, res) => {
});
}
- return res
- .status(200)
- .json({ decorator: "SERVER_SLATE_ADD_TO_SLATE", slate });
+ return res.status(200).json({ decorator: "SERVER_SLATE_ADD_TO_SLATE", slate });
};
diff --git a/scenes/SceneEditAccount.js b/scenes/SceneEditAccount.js
index d097bcc8..15111d77 100644
--- a/scenes/SceneEditAccount.js
+++ b/scenes/SceneEditAccount.js
@@ -42,7 +42,13 @@ export default class SceneEditAccount extends React.Component {
let file = e.target.files[0];
if (!file) {
- alert("Something went wrong");
+ alert("TODO: Something went wrong");
+ return;
+ }
+
+ if (!file.type.startsWith("image/")) {
+ alert("TODO: Error message for not an image.");
+ return;
}
let data = new FormData();
@@ -144,25 +150,15 @@ export default class SceneEditAccount extends React.Component {
description="This image will appear in various lists."
/>
-
+
-
+
+ loading={this.state.changingAvatar}>
Pick avatar
@@ -172,8 +168,7 @@ export default class SceneEditAccount extends React.Component {
label="Username"
description={
- This is your username on Slate. Your username is used for your
- profile URL{" "}
+ This is your username on Slate. Your username is used for your profile URL{" "}
{profileURL}
@@ -186,10 +181,7 @@ export default class SceneEditAccount extends React.Component {
/>
-
+
Change username
@@ -221,10 +213,7 @@ export default class SceneEditAccount extends React.Component {
/>
-
+
Change password
@@ -236,10 +225,7 @@ export default class SceneEditAccount extends React.Component {
/>
-
+
Delete my account
diff --git a/scenes/SceneFile.js b/scenes/SceneFile.js
index 04810a81..db06c74e 100644
--- a/scenes/SceneFile.js
+++ b/scenes/SceneFile.js
@@ -1,14 +1,10 @@
import * as React from "react";
-import * as Strings from "~/common/strings";
import * as Constants from "~/common/constants";
-import * as Fixtures from "~/common/fixtures";
-import * as System from "~/components/system";
import * as SVG from "~/components/system/svg";
import { css } from "@emotion/react";
-import Section from "~/components/core/Section";
-import ScenePage from "~/components/core/ScenePage";
+import MediaObject from "~/components/core/MediaObject";
const STYLES_FLEX = css`
display: flex;
@@ -47,19 +43,6 @@ const STYLES_RIGHT = css`
}
`;
-const STYLES_ASSET = css`
- display: block;
- width: 100%;
- margin: 0;
- padding: 0;
- min-height: 10%;
- height: 100%;
- background-color: ${Constants.system.pitchBlack};
- background-size: contain;
- background-repeat: no-repeat;
- background-position: 50% 50%;
-`;
-
const STYLES_BOTTOM = css`
background: ${Constants.system.pitchBlack};
color: ${Constants.system.white};
@@ -79,62 +62,21 @@ const STYLES_PATH = css`
overflow-wrap: break-word;
`;
-const STYLES_ITEM = css`
- border-radius: 4px;
- outline: 0;
- border: 0;
- min-height: 32px;
- padding: 6px 16px 6px 16px;
- display: inline-flex;
- align-items: center;
- justify-content: center;
- font-size: 12px;
- letter-spacing: 0.2px;
- font-family: ${Constants.font.semiBold};
- transition: 200ms ease all;
- cursor: pointer;
- background-color: ${Constants.system.brand};
- color: ${Constants.system.white};
- margin-left: 16px;
-
- :hover {
- background-color: ${Constants.system.green};
- }
-
- :focus {
- box-shadow: inset 0 0 5px 2px rgba(0, 0, 0, 0.3);
- outline: 0;
- border: 0;
- }
-`;
-
export default class SceneFile extends React.Component {
- state = {};
-
- _handleChange = (e) => {
- this.setState({ [e.target.name]: e.target.value });
- };
-
render() {
- const file = this.props.data;
-
- const fileName = `${file.name}`;
- const fileURL = file.url ? file.url : `https://hub.textile.io${file.ipfs}`;
+ const fileURL = this.props.data.url ? this.props.data.url : `https://hub.textile.io${this.props.data.ipfs}`;
return (
- {fileName}
+ {fileURL}
this.props.onBack()}>
-
+
);
}
diff --git a/scenes/SceneFilesFolder.js b/scenes/SceneFilesFolder.js
index c6cd93d0..58bca1a1 100644
--- a/scenes/SceneFilesFolder.js
+++ b/scenes/SceneFilesFolder.js
@@ -1,6 +1,4 @@
import * as React from "react";
-import * as Strings from "~/common/strings";
-import * as Constants from "~/common/constants";
import * as Actions from "~/common/actions";
import * as System from "~/components/system";
@@ -30,13 +28,14 @@ export default class SceneFilesFolder extends React.Component {
});
console.log({ jobs });
+ if (jobs.length) {
+ const response = await Actions.checkCIDStatus(jobs);
- const response = await Actions.checkCIDStatus(jobs);
+ console.log(response);
- console.log(response);
-
- if (response && response.update) {
- await this.props.onRehydrate();
+ if (response && response.update) {
+ await this.props.onRehydrate();
+ }
}
if (this._interval) {
@@ -63,7 +62,8 @@ export default class SceneFilesFolder extends React.Component {
const data = {
columns: [
- { key: "name", name: "File", type: "FILE_LINK" },
+ { key: "name", name: "File", type: "FILE_LINK", width: "100%" },
+ { key: "type", name: "Type" },
{
key: "size",
name: "Size",
@@ -105,7 +105,7 @@ export default class SceneFilesFolder extends React.Component {
title={this.props.current.name}
buttons={[
{
- name: "Upload to IPFS",
+ name: "Upload data",
type: "SIDEBAR",
value: "SIDEBAR_ADD_FILE_TO_BUCKET",
},
diff --git a/scenes/SceneHome.js b/scenes/SceneHome.js
index 89e734cf..989a313e 100644
--- a/scenes/SceneHome.js
+++ b/scenes/SceneHome.js
@@ -78,14 +78,13 @@ export default class SceneHome extends React.Component {
};
// TODO(jim): Refactor later.
- const slateButtons = [
- { name: "Create slate", type: "SIDEBAR", value: "SIDEBAR_CREATE_SLATE" },
- ];
+ const slateButtons = [{ name: "Create slate", type: "SIDEBAR", value: "SIDEBAR_CREATE_SLATE" }];
// TODO(jim): Refactor later.
const data = {
columns: [
- { key: "name", name: "Data", type: "FILE_LINK" },
+ { key: "name", name: "Data", type: "FILE_LINK", width: "100%" },
+ { key: "type", name: "Type" },
{
key: "size",
name: "Size",
@@ -97,14 +96,13 @@ export default class SceneHome extends React.Component {
name: "Date uploaded",
width: "160px",
type: "FILE_DATE",
- tooltip:
- "This date represents when the file was first uploaded to IPFS.",
},
{
key: "networks",
name: "Network",
type: "NETWORK_TYPE",
width: "188px",
+ tooltip: "This data is publicly available to share on the internet!",
},
],
rows: this.props.viewer.library[0].children.map((each) => {
@@ -123,7 +121,7 @@ export default class SceneHome extends React.Component {
value: this.props.viewer.library[0].id,
},
{
- name: "Upload to IPFS",
+ name: "Upload data",
type: "SIDEBAR",
value: "SIDEBAR_ADD_FILE_TO_BUCKET",
},
@@ -152,11 +150,7 @@ export default class SceneHome extends React.Component {
Home
{this.props.viewer.addresses[0] ? (
-
+
) : null}
-
+
{this.props.viewer.library[0] ? (
-
+
https://slate.host/@{this.props.viewer.username}/{slatename}
-