cleanup moving functions to userbehaviors

This commit is contained in:
Martina 2020-11-21 13:25:40 -08:00
parent b5131f3e7f
commit 00d1c738f3
16 changed files with 411 additions and 713 deletions

View File

@ -2,3 +2,50 @@ export const dispatchCustomEvent = ({ name, detail }) => {
let event = new CustomEvent(name, { detail });
window.dispatchEvent(event);
};
export const handleError = (response) => {
if (!response) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
message: "We're having trouble connecting right now. Please try again later",
},
},
});
return true;
} else if (updateReponse.error) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
decorator: response.decorator,
},
},
});
return true;
}
return false;
};
export const dispatchMessage = ({ message, decorator }) => {
if (decorator) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
decorator,
},
},
});
} else if (message) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
message,
},
},
});
}
};

View File

@ -1,6 +1,7 @@
import * as Websockets from "~/common/browser-websockets";
import * as Credentials from "~/common/credentials";
import * as Actions from "~/common/actions";
import * as Window from "~/common/window";
import * as Store from "~/common/store";
import * as FileUtilities from "~/common/file-utilities";
@ -10,17 +11,7 @@ import { dispatchCustomEvent } from "~/common/custom-events";
const cookies = new Cookies();
// NOTE(martina): Creates a new user, then authenticates them
export const createUser = async (state) => {
let response = await Actions.createUser(state);
if (!response || response.error) {
return response;
}
return this._handleAuthenticate(state, true);
};
export const authenticate = async (state, newAccount) => {
export const authenticate = async (state) => {
// NOTE(jim): Kills existing session cookie if there is one.
const jwt = cookies.get(Credentials.session.key);
@ -29,16 +20,28 @@ export const authenticate = async (state, newAccount) => {
}
let response = await Actions.signIn(state);
if (!response || response.error) {
if (!response) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
message: "We failed to sign you in, please try again.",
message: "We're having trouble connecting right now. Please try again later",
},
},
});
return null;
return false;
}
if (response.error) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
decorator: response.decorator,
},
},
});
return false;
}
if (response.token) {
@ -193,6 +196,212 @@ export const formatUploadedFiles = ({ files }) => {
return { toUpload, fileLoading, numFailed: files.length - toUpload.length };
};
export const uploadImage = async (file) => {
if (!file) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
message: "Something went wrong with the upload. Please try again",
},
},
});
return;
}
if (!Validations.isPreviewableImage(file.type)) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: { message: "Upload failed. Only images and gifs are allowed" },
},
});
return;
}
const response = await FileUtilities.upload({ file, routes: resources });
if (!response) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: { message: "We're having trouble connecting right now" },
},
});
return false;
}
if (response.error) {
dispatchCustomEvent({
name: "create-alert",
detail: { alert: { decorator: response.decorator } },
});
return false;
}
return response.json;
};
export const deleteFiles = async (fileCids) => {
let cids;
if (Array.isArray(fileCids)) {
cids = fileCids;
} else {
cids = [fileCids];
}
const response = await Actions.deleteBucketItems({ cids });
if (!response) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
message: "We're having trouble connecting right now. Please try again later",
},
},
});
return false;
}
if (response.error) {
dispatchCustomEvent({
name: "create-alert",
detail: { alert: { decorator: response.decorator } },
});
return false;
}
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: { message: "Files successfully deleted!", status: "INFO" },
},
});
return response;
};
export const removeFromSlate = async ({ slate, ids }) => {
const response = await Actions.removeFileFromSlate({
slateId: slate.id,
ids,
});
if (!response) {
System.dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
message: "We're having trouble connecting right now. Please try again later",
},
},
});
return false;
}
if (response.error) {
System.dispatchCustomEvent({
name: "create-alert",
detail: { alert: { decorator: response.decorator } },
});
return false;
}
return response;
};
export const addToSlate = async ({ slate, files, fromSlate }) => {
let data = files.map((file) => {
return {
title: file.name || file.title || file.file,
...file,
};
});
const addResponse = await Actions.addFileToSlate({
slate,
data,
fromSlate,
});
if (!addResponse) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
message: "We're having trouble connecting right now. Please try again later",
},
},
});
return false;
}
if (addResponse.error) {
dispatchCustomEvent({
name: "create-alert",
detail: { alert: { decorator: addResponse.decorator } },
});
return false;
}
const { added, skipped } = addResponse;
let message = Strings.formatAsUploadMessage(added, skipped, true);
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: { message, status: !added ? null : "INFO" },
},
});
return true;
};
export const addToDataFromSlate = async ({ files }) => {
let items = files.map((file) => {
return {
ownerId: file.ownerId,
cid: file.cid
? file.cid
: file.ipfs
? file.ipfs.replace("/ipfs/", "")
: Strings.urlToCid(file.url),
};
});
let response = await Actions.addCIDToData({ items });
if (!response) {
System.dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
message: "We're having trouble connecting right now. Please try again later",
},
},
});
return false;
}
if (response.error) {
System.dispatchCustomEvent({
name: "create-alert",
detail: { alert: { decorator: response.decorator } },
});
return false;
}
let message = Strings.formatAsUploadMessage(response.data.added, response.data.skipped);
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: { message, status: !response.data.added ? null : "INFO" },
},
});
return response;
};
export const download = (file) => {
const filename = file.file || file.name || file.title;
let uri;
if (file.url) {
uri = file.url.replace("https://undefined", "https://");
} else {
let cid = file.cid || file.ipfs.replace("/ipfs/", "");
uri = Strings.getCIDGatewayURL(cid);
}
Window.saveAs(uri, filename);
};
// export const createSlate = async (data) => {
// let response = await Actions.createSlate({
// name: data.name,

View File

@ -103,7 +103,6 @@ export default class ApplicationPage extends React.Component {
currentIndex: 0,
data: null,
sidebar: null,
sidebarLoading: false,
online: null,
sidebar: null,
mobile: this.props.mobile,
@ -387,35 +386,43 @@ export default class ApplicationPage extends React.Component {
e.preventDefault();
};
_handleSidebarLoading = (sidebarLoading) => this.setState({ sidebarLoading });
_handleDeleteYourself = async () => await UserBehaviors.deleteMe();
_handleSignOut = async () => await UserBehaviors.signOut();
_handleCreateUser = async (state) => {
let response = await Actions.createUser(state);
if (!response || response.error) {
if (!response) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
message: "We had an issue creating your user account.",
message: "We're having trouble connecting right now. Please try again later",
},
},
});
return response;
return;
}
if (response.error) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
decorator: response.decorator,
},
},
});
return;
}
return this._handleAuthenticate(state, true);
};
_handleAuthenticate = async (state, newAccount) => {
let response = await UserBehaviors.authenticate(state, newAccount);
if (!response || response.error) {
return response;
let response = await UserBehaviors.authenticate(state);
if (!response) {
return;
}
let viewer = await UserBehaviors.hydrate();
if (!viewer) {
return viewer;
@ -485,7 +492,7 @@ export default class ApplicationPage extends React.Component {
};
_handleDismissSidebar = () => {
this.setState({ sidebar: null, sidebarLoading: false, sidebarData: null });
this.setState({ sidebar: null, sidebarData: null });
};
_handleAction = (options) => {
@ -674,7 +681,6 @@ export default class ApplicationPage extends React.Component {
onAction={this._handleAction}
onBack={this._handleBack}
onForward={this._handleForward}
onSignOut={this._handleSignOut}
mobile={this.state.mobile}
/>
);
@ -686,7 +692,6 @@ export default class ApplicationPage extends React.Component {
selected: this.state.selected,
onSelectedChange: this._handleSelectedChange,
onViewerChange: this._handleViewerChange,
onDeleteYourself: this._handleDeleteYourself,
onAction: this._handleAction,
onUpload: this._handleUploadFiles,
onBack: this._handleBack,
@ -706,13 +711,9 @@ export default class ApplicationPage extends React.Component {
data: this.state.data,
sidebarData: this.state.sidebarData,
fileLoading: this.state.fileLoading,
sidebarLoading: this.state.sidebarLoading,
onSelectedChange: this._handleSelectedChange,
onSubmit: this._handleSubmit,
onCancel: this._handleDismissSidebar,
onRegisterFileLoading: this._handleRegisterFileLoading,
onUpload: this._handleUploadFiles,
onSidebarLoading: this._handleSidebarLoading,
onAction: this._handleAction,
resources: this.props.resources,
});

View File

@ -146,11 +146,6 @@ export default class ApplicationHeader extends React.Component {
window.addEventListener("keyup", this._handleKeyUp);
};
//TODO toast: add a command-f light text next to svg
//add cmd svg to header
//add on-hover keybinds next to cmd svg
//--> argue with haris about how that looks
_handleKeyDown = (e) => {
let prevValue = this.keysPressed[e.key];
if (prevValue) {
@ -288,7 +283,6 @@ export default class ApplicationHeader extends React.Component {
onTogglePopup={this._handleTogglePopup}
viewer={this.props.viewer}
onAction={this.props.onAction}
onSignOut={this.props.onSignOut}
/>
</span>
</div>

View File

@ -1,6 +1,7 @@
import * as React from "react";
import * as Constants from "~/common/constants";
import * as SVG from "~/common/svg";
import * as UserBehaviors from "~/common/user-behaviors";
import { PopoverNavigation } from "~/components/system";
import { css } from "@emotion/core";
@ -130,9 +131,11 @@ export default class ApplicationUserControls extends React.Component {
return this.props.onAction(data);
};
_handleSignOut = (data) => {
_handleSignOut = (e) => {
e.preventDefault();
e.stopPropagation();
this.props.onTogglePopup();
return this.props.onSignOut(data);
UserBehaviors.signOut();
};
render() {
@ -177,8 +180,6 @@ export default class ApplicationUserControls extends React.Component {
{
text: "Sign out",
onClick: (e) => {
e.preventDefault();
e.stopPropagation();
this._handleSignOut(e);
},
},

View File

@ -4,6 +4,7 @@ import * as Strings from "~/common/strings";
import * as Validations from "~/common/validations";
import * as Actions from "~/common/actions";
import * as System from "~/components/system";
import * as UserBehaviors from "~/common/user-behaviors";
import * as SVG from "~/common/svg";
import * as Window from "~/common/window";
import * as FileUtilities from "~/common/file-utilities";
@ -232,58 +233,13 @@ export default class CarouselSidebarData extends React.Component {
};
_handleSetLoading = (e) => {
console.log("set loading to:");
console.log(e.detail.loading);
this.setState({ loading: e.detail.loading });
};
_handleUpload = async (e) => {
this.setState({ changingPreview: true });
e.persist();
let file = e.target.files[0];
console.log(file);
if (!file) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
message: "Something went wrong with the upload. Please try again",
},
},
});
return;
}
if (!Validations.isPreviewableImage(file.type)) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: { message: "Upload failed. Only images and gifs are allowed" },
},
});
return;
}
const response = await FileUtilities.upload({ file, routes: this.props.resources });
const { json } = response;
if (!response) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: { message: "We're having trouble connecting right now" },
},
});
this.setState({ changingPreview: false });
return;
}
if (response.error) {
dispatchCustomEvent({
name: "create-alert",
detail: { alert: { decorator: response.decorator } },
});
let json = await UserBehaviors.uploadImage(e.target.files[0], this.props.resources);
if (!json) {
this.setState({ changingPreview: false });
return;
}
@ -319,10 +275,7 @@ export default class CarouselSidebarData extends React.Component {
};
_handleDownload = () => {
const filename = this.props.data.file;
let cid = this.props.data.cid || this.props.data.ipfs.replace("/ipfs/", "");
const uri = Strings.getCIDGatewayURL(cid);
Window.saveAs(uri, filename);
UserBehaviors.download(this.props.data);
};
_handleCreateSlate = async () => {
@ -334,27 +287,6 @@ export default class CarouselSidebarData extends React.Component {
});
};
_handleAdd = (slate) => {
//NOTE(martina): triggers action through DataView.js (which is always mounted if this carousel is open)
if (this.state.selected[slate.id]) {
dispatchCustomEvent({
name: "remote-slate-object-remove",
detail: { id: this.props.data.id, slate: slate, data: this.props.data },
});
this.setState({
selected: { ...this.state.selected, [slate.id]: false },
});
} else {
dispatchCustomEvent({
name: "remote-slate-object-add",
detail: { id: this.props.data.id, slate: slate, data: this.props.data },
});
this.setState({
selected: { ...this.state.selected, [slate.id]: slate },
});
}
};
_handleCopy = (copyValue, loading) => {
this.setState({ copyValue, loading }, () => {
this._ref.select();
@ -366,12 +298,13 @@ export default class CarouselSidebarData extends React.Component {
};
_handleDelete = async (cid) => {
//NOTE(martina): triggers action through DataView.js (which is always mounted if this carousel is open)
const message = `Are you sure you want to delete this? It will be deleted from your slates as well`;
if (!window.confirm(message)) {
return;
}
await this.setState({ loading: cid });
dispatchCustomEvent({
name: "remote-data-deletion",
detail: { cid },
});
await UserBehaviors.deleteFiles(cid);
this.setState({ loading: false });
};
render() {
@ -426,11 +359,9 @@ export default class CarouselSidebarData extends React.Component {
<SlatePicker
dark
slates={this.props.slates}
selected={this.state.selected}
onAdd={this._handleAdd}
onCreateSlate={this._handleCreateSlate}
loading={this.props.loading}
selectedColor={Constants.system.white}
files={[this.props.data]}
/>
{type && type.startsWith("image/") ? null : (
<div>

View File

@ -3,6 +3,7 @@ import * as SVG from "~/common/svg";
import * as Constants from "~/common/constants";
import * as Strings from "~/common/strings";
import * as Actions from "~/common/actions";
import * as UserBehaviors from "~/common/user-behaviors";
import * as Window from "~/common/window";
import { css } from "@emotion/core";
@ -223,68 +224,8 @@ export default class CarouselSidebarSlate extends React.Component {
this.setState({ [e.target.name]: e.target.value, unsavedChanges: true });
};
_handleAdd = async (slate) => {
if (this.props.external) return;
if (this.state.selected[slate.id]) {
const removeResponse = await Actions.removeFileFromSlate({
slateId: slate.id,
ids: [this.props.data.id],
});
if (!removeResponse) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
message: "We're having trouble connecting right now. Please try again later",
},
},
});
return;
}
if (removeResponse.error) {
dispatchCustomEvent({
name: "create-alert",
detail: { alert: { decorator: removeResponse.decorator } },
});
return;
}
this.setState({
selected: { ...this.state.selected, [slate.id]: false },
});
} else {
const addResponse = await Actions.addFileToSlate({
slate,
data: [{ title: this.props.data.title || this.props.data.name, ...this.props.data }],
fromSlate: true,
});
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: addResponse.decorator } },
});
return;
}
this.setState({
selected: { ...this.state.selected, [slate.id]: true },
});
}
};
_handleDownload = () => {
const filename = this.props.data.name || this.props.data.title;
const uri = this.props.data.url.replace("https://undefined", "https://");
Window.saveAs(uri, filename);
UserBehaviors.download(this.props.data);
};
_handleCopy = (copyValue, loading) => {
@ -298,79 +239,23 @@ export default class CarouselSidebarSlate extends React.Component {
};
_handleSaveCopy = async (data) => {
this.setState({ loading: "savingCopy" });
let items = [
{
ownerId: data.ownerId,
cid: data.cid || Strings.urlToCid(data.url),
},
];
let response = await Actions.addCIDToData({ items });
if (!response) {
this.setState({ loading: false, saving: "ERROR" });
System.dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
message: "We're having trouble connecting right now. Please try again later",
},
},
});
return;
}
if (response.error) {
this.setState({ loading: false, saving: "ERROR" });
System.dispatchCustomEvent({
name: "create-alert",
detail: { alert: { decorator: response.decorator } },
});
return;
}
let message = Strings.formatAsUploadMessage(response.data.added, response.data.skipped);
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: { message, status: !response.data.added ? null : "INFO" },
},
});
await this.setState({ loading: "savingCopy" });
await UserBehaviors.addToDataFromSlate({ files: [data] });
this.setState({ loading: false });
};
_handleDelete = async (cid) => {
if (this.props.external || !this.props.isOwner) return;
this.setState({ loading: "deleting" });
if (
!window.confirm(
"Are you sure you want to delete this? It will be removed from your slates too."
"Are you sure you want to delete this? It will be removed from all your slates too."
)
) {
this.setState({ loading: false });
return;
}
const response = await Actions.deleteBucketItems({ cids: [cid] });
if (!response) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
message: "We're having trouble connecting right now. Please try again later",
},
},
});
this.setState({ loading: false });
return;
}
if (response.error) {
dispatchCustomEvent({
name: "create-alert",
detail: { alert: { decorator: response.decorator } },
});
this.setState({ loading: false });
return;
}
await this.setState({ loading: "deleting" });
await UserBehaviors.deleteFiles(cid);
this.setState({ loading: false });
console.log("got here to end of handle delete");
};
_toggleAccordion = (tab) => {
@ -428,7 +313,6 @@ export default class CarouselSidebarSlate extends React.Component {
const hasBody = !Strings.isEmpty(this.props.data.body);
const hasSource = !Strings.isEmpty(this.props.data.source);
const hasAuthor = !Strings.isEmpty(this.props.data.author);
console.log(this.props.data);
if (hasTitle) {
elements.push(
@ -509,11 +393,10 @@ export default class CarouselSidebarSlate extends React.Component {
<div style={{ width: "100%", margin: "24px 0 44px 0" }}>
<SlatePicker
slates={this.props.slates}
selected={this.state.selected}
onAdd={this._handleAdd}
onCreateSlate={this._handleCreateSlate}
loading={this.props.loading}
dark
fromSlate
files={[this.props.data]}
selectedColor={Constants.system.white}
/>
</div>

View File

@ -5,6 +5,7 @@ import * as System from "~/components/system";
import * as Actions from "~/common/actions";
import * as SVG from "~/common/svg";
import * as Window from "~/common/window";
import * as UserBehaviors from "~/common/user-behaviors";
import { css } from "@emotion/core";
import { Boundary } from "~/components/system/components/fragments/Boundary";
@ -189,8 +190,6 @@ const STYLES_MOBILE_HIDDEN = css`
}
`;
const delay = (ms) => new Promise((resolve) => window.setTimeout(resolve, ms));
export default class DataView extends React.Component {
_mounted = false;
@ -206,18 +205,12 @@ export default class DataView extends React.Component {
async componentDidMount() {
if (!this._mounted) {
this._mounted = true;
window.addEventListener("remote-data-deletion", this._handleDataDeletion);
window.addEventListener("remote-slate-object-remove", this._handleRemoteSlateObjectRemove);
window.addEventListener("remote-slate-object-add", this._handleRemoteSlateObjectAdd);
window.addEventListener("scroll", this._handleCheckScroll);
}
}
componentWillUnmount() {
this._mounted = false;
window.removeEventListener("remote-data-deletion", this._handleDataDeletion);
window.removeEventListener("remote-slate-object-remove", this._handleRemoteSlateObjectRemove);
window.removeEventListener("remote-slate-object-add", this._handleRemoteSlateObjectAdd);
window.removeEventListener("scroll", this._handleCheckScroll);
}
@ -256,9 +249,9 @@ export default class DataView extends React.Component {
_handleDelete = async (cid) => {
const message = `Are you sure you want to delete these files? They will be deleted from your slates as well`;
if (!window.confirm(message)) {
dispatchCustomEvent({ name: "data-global-carousel-loading", detail: { loading: false } });
return;
}
await this._handleLoading({ cids });
let cids;
if (cid) {
cids = [cid];
@ -268,41 +261,10 @@ export default class DataView extends React.Component {
let item = this.props.viewer.library[0].children[index];
return item.cid || item.ipfs.replace("/ipfs/", "");
});
this.setState({ checked: {} });
}
await UserBehaviors.deleteFiles(cids);
this._handleLoading({ cids });
const response = await Actions.deleteBucketItems({ cids });
if (!response) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
message: "We're having trouble connecting right now. Please try again later",
},
},
});
this._handleLoading({ cids });
dispatchCustomEvent({ name: "data-global-carousel-loading", detail: { loading: false } });
return;
}
if (response.error) {
dispatchCustomEvent({
name: "create-alert",
detail: { alert: { decorator: response.decorator } },
});
this._handleLoading({ cids });
dispatchCustomEvent({ name: "data-global-carousel-loading", detail: { loading: false } });
return;
}
this._handleLoading({ cids });
this.setState({ checked: {} });
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: { message: "Files successfully deleted!", status: "INFO" },
},
});
dispatchCustomEvent({ name: "data-global-carousel-loading", detail: { loading: false } });
};
_handleSelect = (index) => {
@ -312,109 +274,6 @@ export default class DataView extends React.Component {
});
};
_handleDataDeletion = (e) => {
this._handleDelete(e.detail.cid);
};
_handleRemoteSlateObjectAdd = async ({ detail }) => {
const { id, slate, data } = detail;
System.dispatchCustomEvent({
name: "data-global-carousel-loading",
detail: { loading: { id: slate.id } },
});
const addResponse = await Actions.addFileToSlate({
slate,
data: [{ title: data.name, ...data }],
});
if (!addResponse) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
message: "We're having trouble connecting right now. Please try again later",
},
},
});
return null;
}
if (addResponse.error) {
dispatchCustomEvent({
name: "create-alert",
detail: { alert: { decorator: addResponse.decorator } },
});
return null;
}
const { added, skipped } = addResponse;
let message = Strings.formatAsUploadMessage(added, skipped, true);
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: { message, status: !added ? null : "INFO" },
},
});
System.dispatchCustomEvent({
name: "data-global-carousel-loading",
detail: { loading: false },
});
};
_handleRemoteSlateObjectRemove = async ({ detail }) => {
const { id, slate } = detail;
System.dispatchCustomEvent({
name: "data-global-carousel-loading",
detail: { loading: { id: slate.id } },
});
const response = await Actions.removeFileFromSlate({ slateId: slate.id, ids: [id] });
if (!response) {
System.dispatchCustomEvent({
name: "data-global-carousel-loading",
detail: { loading: false },
});
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
message:
"We're having trouble connecting right now and weren't able to delete that. Please try again later",
},
},
});
return null;
}
if (response.error) {
System.dispatchCustomEvent({
name: "data-global-carousel-loading",
detail: { loading: false },
});
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
decorator: response.decorator,
},
},
});
return null;
}
System.dispatchCustomEvent({
name: "data-global-carousel-loading",
detail: { loading: false },
});
};
_handleCopy = (e, value) => {
e.stopPropagation();
this._handleHide();

View File

@ -169,6 +169,7 @@ export class SignIn extends React.Component {
password: this.state.password,
});
}
<<<<<<< HEAD
if (!response) {
dispatchCustomEvent({
@ -192,6 +193,9 @@ export class SignIn extends React.Component {
return;
}
this.setState({ scene: "whatever" });
=======
this.setState({ loading: false });
>>>>>>> cleanup moving functions to userbehaviors
};
_handleCheckUsername = async () => {
@ -220,7 +224,7 @@ export class SignIn extends React.Component {
name: "create-alert",
detail: {
alert: {
message: "2We're having trouble connecting right now. Please try again later.",
message: "We're having trouble connecting right now. Please try again later.",
},
},
});

View File

@ -4,6 +4,7 @@ import * as SVG from "~/common/svg";
import * as Strings from "~/common/strings";
import * as Window from "~/common/window";
import * as Validations from "~/common/validations";
import * as UserBehaviors from "~/common/user-behaviors";
import SlateMediaObjectPreview from "~/components/core/SlateMediaObjectPreview";
import CTATransition from "~/components/core/CTATransition";
@ -310,17 +311,9 @@ export class SlateLayout extends React.Component {
signInModal: false,
};
//LEFT OFF HERE:
//make sure things work if you delete while in editing mode (haven't tested that yet)
//add the "delete" and checkbox actions. drag handle. and make preview image
//if there's repeats of ids (not cids), it'll style them the same way (potentially diff position though) everytime you change something
//if width under a certain amount, set to a default mobile flex or grid layout of single items
//add flag for following defaultLayout for last element or not. so know where to put next one. "unchanged since last add" flag. if something deleted, messes this up as well
componentDidMount = async () => {
this.debounceInstance = this.debounce(this._recalculate, 250);
window.addEventListener("resize", this.debounceInstance);
window.addEventListener("remote-object-update", this._handleRemoteEditObject);
await this.calculateUnit();
if (this.props.layout) {
let layout = await this.repairLayout(this.state.items);
@ -356,7 +349,6 @@ export class SlateLayout extends React.Component {
componentWillUnmount = () => {
window.removeEventListener("resize", this.debounceInstance);
window.removeEventListener("remote-object-update", this._handleRemoteEditObject);
if (this.state.editing) {
window.removeEventListener("keydown", this._handleKeyDown);
window.removeEventListener("keyup", this._handleKeyUp);
@ -437,18 +429,18 @@ export class SlateLayout extends React.Component {
}
};
_handleRemoteEditObject = async ({ detail }) => {
const { object } = detail;
// _handleRemoteEditObject = async ({ detail }) => {
// const { object } = detail;
const items = [...this.state.items];
for (let i = 0; i < items.length; i++) {
if (items[i].id === object.id) {
items[i] = object;
break;
}
}
this.setState({ items });
};
// const items = [...this.state.items];
// for (let i = 0; i < items.length; i++) {
// if (items[i].id === object.id) {
// items[i] = object;
// break;
// }
// }
// this.setState({ items });
// };
debounce = (func, ms) => {
let timer;
@ -959,10 +951,6 @@ export class SlateLayout extends React.Component {
});
};
_handleDelete = (ids) => {
dispatchCustomEvent({ name: "remote-delete-object", detail: { ids } });
};
_handleCopy = (e, value) => {
e.stopPropagation();
e.preventDefault();
@ -985,48 +973,23 @@ export class SlateLayout extends React.Component {
e.stopPropagation();
e.preventDefault();
if (i !== undefined) {
let filename = this.state.items[i].name || this.state.items[i].title;
let uri = this.state.items[i].url.replace("https://undefined", "https://");
Window.saveAs(uri, filename);
UserBehaviors.download(this.state.items[i]);
}
// else {
// for (let i of Object.keys(this.state.checked)) {
// console.log(i);
// download = this.state.items[i].name || this.state.items[i].title;
// uri = this.state.items[i].url.replace("https://undefined", "https://");
// let link = document.createElement("a");
// document.body.appendChild(link);
// link.target = "_blank";
// link.download = download;
// link.href = uri;
// link.click();
// document.body.removeChild(link);
// }
// }
// this.setState({ checked: {} });
};
_handleSaveCopy = (e, i) => {
_handleSaveCopy = async (e, i) => {
e.stopPropagation();
e.preventDefault();
let items = [];
if (i !== undefined) {
items = [
{
ownerId: this.state.items[i].ownerId,
cid: this.state.items[i].cid || Strings.urlToCid(this.state.items[i].url),
},
];
items = [this.state.items[i]];
} else {
this.setState({ checked: {} });
for (let i of Object.keys(this.state.checked)) {
items.push({
ownerId: this.state.items[i].ownerId,
cid: this.state.items[i].cid || Strings.urlToCid(this.state.items[i].url),
});
items.push(this.state.items[i]);
}
}
this.props.onSaveCopy(items);
this.setState({ checked: {} });
UserBehaviors.addToDataFromSlate({ files: items });
};
_handleAddToSlate = (e, i) => {
@ -1058,9 +1021,9 @@ export class SlateLayout extends React.Component {
for (let index of Object.keys(this.state.checked)) {
ids.push(this.state.items[index].id);
}
this.setState({ checked: {} });
}
this.props.onRemoveFromSlate({ detail: { ids } });
this.setState({ checked: {} });
UserBehaviors.removeFromSlate({ slate: this.props.current, ids });
};
_handleDeleteFiles = (e, i) => {
@ -1073,6 +1036,7 @@ export class SlateLayout extends React.Component {
for (let index of Object.keys(this.state.checked)) {
ids.push(this.state.items[index].id);
}
this.setState({ checked: {} });
}
let cids = [];
for (let file of this.props.viewer.library[0].children) {
@ -1080,8 +1044,7 @@ export class SlateLayout extends React.Component {
cids.push(file.cid || file.ipfs.replace("/ipfs/", ""));
}
}
this.props.onDeleteFiles(cids);
this.setState({ checked: {} });
UserBehaviors.deleteFiles(cids);
};
_stopProp = (e) => {

View File

@ -2,6 +2,7 @@ import * as React from "react";
import * as Strings from "~/common/strings";
import * as Constants from "~/common/constants";
import * as SVG from "~/common/svg";
import * as UserBehaviors from "~/common/user-behaviors";
import { css } from "@emotion/core";
import { LoaderSpinner } from "~/components/system/components/Loaders";
@ -104,7 +105,34 @@ const STYLES_ICON_BOX = css`
`;
export class SlatePicker extends React.Component {
state = {
selected: {},
loading: null,
};
_handleAdd = async (slate) => {
if (this.props.onAdd) {
this.props.onAdd(slate);
return;
}
await this.setState({ loading: slate.id });
if (this.state.selected[slate.id]) {
await UserBehaviors.removeFromSlate({ slate, ids: this.props.files.map((file) => file.id) });
} else {
await UserBehaviors.addToSlate({
slate,
files: this.props.files,
fromSlate: this.props.fromSlate,
});
}
this.setState({
selected: { ...this.state.selected, [slate.id]: !this.state.selected[slate.id] },
loading: null,
});
};
render() {
const selected = this.props.selected || this.state.selected;
return (
<React.Fragment>
<div
@ -129,14 +157,12 @@ export class SlatePicker extends React.Component {
<div
key={slate.id}
css={this.props.dark ? STYLES_SLATE_LINE_DARK : STYLES_SLATE_LINE}
onClick={() => this.props.onAdd(slate)}
onClick={() => this._handleAdd(slate)}
>
<div css={STYLES_ICON_BOX}>
{this.props.loading &&
this.props.loading.id &&
this.props.loading.id === slate.id ? (
{this.state.loading && this.state.loading === slate.id ? (
<LoaderSpinner style={{ height: 20, width: 20, margin: "2px 8px 2px 2px" }} />
) : this.props.selected[slate.id] ? (
) : selected[slate.id] ? (
<SVG.Slate
height="24px"
style={{
@ -158,7 +184,7 @@ export class SlatePicker extends React.Component {
<div
css={this.props.dark ? STYLES_SLATE_NAME_DARK : STYLES_SLATE_NAME}
style={{
color: this.props.selected[slate.id] ? this.props.selectedColor : "inherit",
color: selected[slate.id] ? this.props.selectedColor : "inherit",
}}
>
{Strings.getPresentationSlateName(slate)}

View File

@ -3,6 +3,7 @@ import * as Strings from "~/common/strings";
import * as Constants from "~/common/constants";
import * as System from "~/components/system";
import * as Actions from "~/common/actions";
import * as UserBehaviors from "~/common/user-behaviors";
import { dispatchCustomEvent } from "~/common/custom-events";
import { css } from "@emotion/core";
@ -18,6 +19,7 @@ const STYLES_HEADER = css`
export default class SidebarAddFileToSlate extends React.Component {
state = {
selected: {},
loading: false,
};
componentDidMount = () => {
@ -55,46 +57,16 @@ export default class SidebarAddFileToSlate extends React.Component {
};
_handleSubmit = async () => {
let data = this.props.sidebarData.files.map((file) => {
return { title: file.name, ...file };
});
await this.setState({ loading: true });
for (let slate of Object.values(this.state.selected)) {
if (!slate) continue;
const addResponse = await Actions.addFileToSlate({
await UserBehaviors.addToSlate({
slate,
data,
files: this.props.sidebarData.files,
fromSlate: this.props.sidebarData.fromSlate,
});
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: addResponse.decorator } },
});
return;
}
const { added, skipped } = addResponse;
let message = Strings.formatAsUploadMessage(added, skipped, true);
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: { message, status: !added ? null : "INFO" },
},
});
}
this.setState({ loading: false });
this.props.onCancel();
};
@ -121,7 +93,12 @@ export default class SidebarAddFileToSlate extends React.Component {
/>
{Object.keys(this.state.selected).length ? (
<ButtonPrimary full onClick={this._handleSubmit} style={{ marginTop: 32 }}>
<ButtonPrimary
full
onClick={this._handleSubmit}
style={{ marginTop: 32 }}
loading={this.state.loading}
>
Add to slates
</ButtonPrimary>
) : (

View File

@ -37,6 +37,7 @@ export default class SidebarFileStorageDeal extends React.Component {
settings_cold_default_duration: this.props.viewer.settings_cold_default_duration,
settings_cold_default_replication_factor: this.props.viewer
.settings_cold_default_replication_factor,
loading: false,
};
async componentDidMount() {
@ -71,9 +72,10 @@ export default class SidebarFileStorageDeal extends React.Component {
e.persist();
}
this.props.onSidebarLoading(true);
await this.setState({ loading: true });
await this._handleMakeDeal({ ipfs: this.props.data.ipfs || `/ipfs/${this.props.data.cid}` });
await this.props.onSubmit({});
this.setState({ loading: false });
await this.props.onCancel();
};
_handleCancel = () => {
@ -110,7 +112,7 @@ export default class SidebarFileStorageDeal extends React.Component {
</div>
</div>
{!this.props.sidebarLoading ? (
{!this.state.loading ? (
<System.Input
containerStyle={{ marginTop: 48 }}
label="Deal duration"
@ -122,7 +124,7 @@ export default class SidebarFileStorageDeal extends React.Component {
/>
) : null}
{!this.props.sidebarLoading ? (
{!this.state.loading ? (
<System.Input
containerStyle={{ marginTop: 24 }}
label="Replication factor"
@ -132,7 +134,7 @@ export default class SidebarFileStorageDeal extends React.Component {
/>
) : null}
{!this.props.sidebarLoading ? (
{!this.state.loading ? (
<System.SelectMenu
full
containerStyle={{ marginTop: 24 }}
@ -149,12 +151,12 @@ export default class SidebarFileStorageDeal extends React.Component {
full
style={{ marginTop: 48 }}
onClick={this._handleSubmit}
loading={this.props.sidebarLoading}
loading={this.state.loading}
>
Make storage deal
</System.ButtonPrimary>
{!this.props.sidebarLoading ? (
{!this.state.loading ? (
<System.ButtonSecondary full style={{ marginTop: 16 }} onClick={this._handleCancel}>
Cancel deal
</System.ButtonSecondary>

View File

@ -10,7 +10,7 @@ import { dispatchCustomEvent } from "~/common/custom-events";
const DEFAULT_ERROR_MESSAGE = "We could not make your deal. Please try again later.";
export default class SidebarFilecoinArchive extends React.Component {
state = { response: null };
state = { response: null, loading: false };
async componentDidMount() {}
@ -23,11 +23,11 @@ export default class SidebarFilecoinArchive extends React.Component {
e.persist();
}
this.props.onSidebarLoading(true);
await this.setState({ loading: true });
const response = await this._handleMakeDeal();
if (!response) {
this.props.onSidebarLoading(false);
this.setState({ loading: false });
return dispatchCustomEvent({
name: "create-alert",
detail: {
@ -39,7 +39,7 @@ export default class SidebarFilecoinArchive extends React.Component {
}
if (response.error) {
this.props.onSidebarLoading(false);
this.setState({ loading: false });
if (response.message) {
return dispatchCustomEvent({
name: "create-alert",
@ -99,7 +99,7 @@ export default class SidebarFilecoinArchive extends React.Component {
full
style={{ marginTop: 48 }}
onClick={this._handleSubmit}
loading={this.props.sidebarLoading}
loading={this.state.loading}
>
Make storage deal
</System.ButtonPrimary>

View File

@ -6,6 +6,7 @@ import * as Validations from "~/common/validations";
import * as Window from "~/common/window";
import * as Constants from "~/common/constants";
import * as FileUtilities from "~/common/file-utilities";
import * as UserBehaviors from "~/common/user-behaviors";
import { css } from "@emotion/core";
import { dispatchCustomEvent } from "~/common/custom-events";
@ -58,58 +59,12 @@ export default class SceneEditAccount extends React.Component {
_handleUpload = async (e) => {
this.setState({ changingAvatar: true });
e.persist();
let file = e.target.files[0];
if (!file) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
message: "Something went wrong with the upload. Please try again",
},
},
});
return;
}
// NOTE(jim): Only allow images for account avatar.
if (!Validations.isPreviewableImage(file.type)) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: { message: "Upload failed. Only images and gifs are allowed" },
},
});
return;
}
const response = await FileUtilities.upload({ file, routes: this.props.resources });
if (!response) {
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: { message: "We're having trouble connecting right now" },
},
});
let json = await UserBehaviors.uploadImage(e.target.files[0], this.props.resources);
if (!json) {
this.setState({ changingAvatar: false });
return;
}
if (response.error) {
dispatchCustomEvent({
name: "create-alert",
detail: { alert: { decorator: response.decorator } },
});
this.setState({ changingAvatar: false });
return;
}
const { json } = response;
const cid = json.data.cid || json.data.ipfs.replace("/ipfs/", "");
const url = Strings.getCIDGatewayURL(cid);
let updateResponse = await Actions.updateViewer({
@ -285,16 +240,11 @@ export default class SceneEditAccount extends React.Component {
await Window.delay(100);
const response = await this.props.onDeleteYourself();
await UserBehaviors.deleteMe();
this.setState({ deleting: false });
};
_handleChange = (e) => {
e.persist();
this.setState({ [e.target.name]: e.target.value });
};
_handleCheckboxChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
};
@ -378,7 +328,7 @@ export default class SceneEditAccount extends React.Component {
style={{ marginTop: 48 }}
name="allow_filecoin_directory_listing"
value={this.state.allow_filecoin_directory_listing}
onChange={this._handleCheckboxChange}
onChange={this._handleChange}
>
Show your successful deals on a directory page where others can retrieve them.
</System.CheckBox>
@ -387,7 +337,7 @@ export default class SceneEditAccount extends React.Component {
style={{ marginTop: 24 }}
name="allow_automatic_data_storage"
value={this.state.allow_automatic_data_storage}
onChange={this._handleCheckboxChange}
onChange={this._handleChange}
>
Allow Slate to make archive storage deals on your behalf to the Filecoin Network. You
will get a receipt in the Filecoin section.
@ -397,7 +347,7 @@ export default class SceneEditAccount extends React.Component {
style={{ marginTop: 24 }}
name="allow_encrypted_data_storage"
value={this.state.allow_encrypted_data_storage}
onChange={this._handleCheckboxChange}
onChange={this._handleChange}
>
Force encryption on archive storage deals (only you can see retrieved data from the
Filecoin network).

View File

@ -122,8 +122,6 @@ export default class SceneSlate extends React.Component {
return false;
}
isMounted = true;
window.addEventListener("remote-delete-object", this._handleRemoteDeleteObject);
window.addEventListener("remote-object-update", this._handleRemoteEditObject);
if (this.state.isOwner) {
let changed = false;
@ -147,8 +145,6 @@ export default class SceneSlate extends React.Component {
componentWillUnmount() {
isMounted = false;
window.removeEventListener("remote-delete-object", this._handleRemoteDeleteObject);
window.removeEventListener("remote-object-update", this._handleRemoteEditObject);
}
_handleFollow = () => {
@ -210,114 +206,6 @@ export default class SceneSlate extends React.Component {
});
};
_handleRemoteEditObject = async ({ detail }) => {
const { object } = detail;
console.log(object);
System.dispatchCustomEvent({
name: "state-global-carousel-loading",
detail: { saving: true },
});
const objects = [...this.props.current.data.objects];
for (let i = 0; i < objects.length; i++) {
if (objects[i].id === object.id) {
objects[i] = object;
break;
}
}
await this._handleSave(null, objects);
System.dispatchCustomEvent({
name: "state-global-carousel-loading",
detail: { saving: false },
});
};
_handleDeleteFiles = async (cids) => {
const message = `Are you sure you want to delete these files? They will be deleted from your slates as well`;
if (!window.confirm(message)) {
return;
}
const response = await Actions.deleteBucketItems({ cids });
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;
}
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: { message: "Files successfully deleted!", status: "INFO" },
},
});
};
_handleRemoteDeleteObject = async ({ detail }) => {
System.dispatchCustomEvent({
name: "state-global-carousel-loading",
detail: { loading: true },
});
let objects = this.props.current.data.objects.filter((obj) => {
return !detail.ids.includes(obj.id);
});
const response = await Actions.updateSlate({
id: this.props.current.id,
data: {
objects,
},
});
if (!response) {
System.dispatchCustomEvent({
name: "state-global-carousel-loading",
detail: { loading: false },
});
System.dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
message: "We're having trouble connecting right now. Please try again later",
},
},
});
return;
}
if (response.error) {
System.dispatchCustomEvent({
name: "state-global-carousel-loading",
detail: { loading: false },
});
System.dispatchCustomEvent({
name: "create-alert",
detail: { alert: { decorator: response.decorator } },
});
return;
}
System.dispatchCustomEvent({
name: "state-global-carousel-loading",
detail: { loading: false },
});
};
_handleSelect = (index) =>
System.dispatchCustomEvent({
name: "slate-global-open-carousel",
@ -332,40 +220,6 @@ export default class SceneSlate extends React.Component {
});
};
_handleSaveCopy = async (items) => {
this.setState({ loading: true });
let response = await Actions.addCIDToData({ items });
if (!response) {
this.setState({ loading: false, saving: "ERROR" });
System.dispatchCustomEvent({
name: "create-alert",
detail: {
alert: {
message: "We're having trouble connecting right now. Please try again later",
},
},
});
return;
}
if (response.error) {
this.setState({ loading: false, saving: "ERROR" });
System.dispatchCustomEvent({
name: "create-alert",
detail: { alert: { decorator: response.decorator } },
});
return;
}
let message = Strings.formatAsUploadMessage(response.data.added, response.data.skipped);
dispatchCustomEvent({
name: "create-alert",
detail: {
alert: { message, status: !response.data.added ? null : "INFO" },
},
});
this.setState({ loading: false, saving: "SAVED" });
};
_handleShowSettings = () => {
return this.props.onAction({
type: "SIDEBAR",
@ -523,9 +377,6 @@ export default class SceneSlate extends React.Component {
onSelect={this._handleSelect}
defaultLayout={layouts && layouts.ver === "2.0" ? layouts.defaultLayout : true}
onAction={this.props.onAction}
onRemoveFromSlate={this._handleRemoteDeleteObject}
onDeleteFiles={this._handleDeleteFiles}
onSaveCopy={this._handleSaveCopy}
/>
</div>
)