diff --git a/common/constants.js b/common/constants.js index 1cc02fca..8fc1cb4e 100644 --- a/common/constants.js +++ b/common/constants.js @@ -14,7 +14,7 @@ export const sizes = { export const system = { white: "#ffffff", - foreground: "#f7f7f7", + foreground: "#f8f8f8", gray: "#e0e0e0", border: "#d8d8d8", darkGray: "#b2b2b2", @@ -25,7 +25,7 @@ export const system = { link: "#2935ff", green: "#28a745", yellow: " #FFC940", - red: "#ff0000", + red: "#E05435", slate: "#27292e", moonstone: "#807d78", wall: "#cfced3", diff --git a/common/file-utilities.js b/common/file-utilities.js index b2d0a9f0..6c1c04fb 100644 --- a/common/file-utilities.js +++ b/common/file-utilities.js @@ -1,3 +1,5 @@ +import { dispatchCustomEvent } from "~/common/custom-events"; + export const upload = async ({ file, slate, context }) => { let formData = new FormData(); const HEIC2ANY = require("heic2any"); @@ -93,9 +95,21 @@ export const upload = async ({ file, slate, context }) => { body: JSON.stringify({ slate, data: { title: file.name, ...json.data } }), }); - if (!addResponse || addResponse.error) { - console.log(addResponse.error); - alert("TODO: Adding an image to Slate went wrong."); + if (!addResponse) { + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { + message: + "We're having trouble connecting right now. Please try again later", + }, + }, + }); + } else if (addResponse.error) { + dispatchCustomEvent({ + name: "create-alert", + detail: { alert: { decorator: addResponse.decorator } }, + }); } } diff --git a/common/messages.js b/common/messages.js index 6b268dc7..0581624f 100644 --- a/common/messages.js +++ b/common/messages.js @@ -1,9 +1,15 @@ export const error = { //Slate Create + SERVER_FIND_USER_CREATE_SLATE: "There seems to be an issue with your account", + SERVER_FIND_USER_CREATE_SLATE_USER_NOT_FOUND: "Login to create a Slate!", + SERVER_EXISTING_SLATE: + "A Slate with that name already exists. Please try another", + SERVER_CREATE_SLATE: "There was an error when creating the Slate", FIND_USER_CREATE_SLATE: "There seems to be an issue with your account", FIND_USER_CREATE_SLATE_USER_NOT_FOUND: "Login to create a Slate!", EXISTING_SLATE: "A Slate with that name already exists. Please try another", CREATE_SLATE: "There was an error when creating the Slate", + SERVER_SLATE_LIMIT: "You've reached the limit for number of slates!", //Slate Add URL ADD_TO_SLATE_USER_NOT_FOUND: "Login to add a Slate URL", @@ -11,54 +17,336 @@ export const error = { "Sorry, we couldn't find that Slate! Please try another", ADD_TO_SLATE_ERROR: "There was an error retriving this Slate", + //Slate Delete + DELETE_SLATE_BY_ID: + "Sorry, there was an error while trying to delete that slate. Please try again", + DELETE_SLATES_FOR_USER_ID: + "Sorry, we're having trouble deleting all your slates. Please try again later", + SERVER_DELETE_SLATE: + "We're having trouble deleting that at the moment. Please try again later", + SERVER_DELETE_SLATE_USER_NOT_FOUND: "Login to manage your slates!", + SERVER_DELETE_SLATE_SLATE_NOT_FOUND: + "We're having trouble deleting that at the moment. Please try again later", + SERVER_DELETE_SLATE: + "We're having trouble deleting that at the moment. Please try again later", + + //Slate Get + GET_SLATE_BY_ID: + "We're having trouble retrieving information on that slate right now. Please try again later", + GET_SLATE_BY_NAME: + "We're having trouble retrieving information on that slate right now. Please try again later", + GET_SLATES_BY_USER_ID: + "We're having trouble retrieving that user's information. Please try again later", + SLATE_NOT_FOUND: + "We're having trouble retrieving that user's slates right now. Please try again", + SLATE_OWNER_NOT_FOUND: + "We're having trouble retrieving that slate's owner right now. Please try again", + SERVER_GET_SLATE_USER_NOT_FOUND: + "We're having trouble retrieving that slate's owner right now. Please try again", + SERVER_GET_SLATE: + "We're having trouble retrieving information on that slate right now. Please try again later", + SERVER_GET_SLATE_NOT_FOUND: + "We're having trouble retrieving information on that slate right now. Please try again later", + + //Slate Update + UPDATE_SLATE_BY_ID: + "We ran into an issue while saving your slate. Please try again", + SERVER_ADD_TO_SLATE_USER_NOT_FOUND: "Login to upload files!", + SERVER_FIND_USER_UPDATE_SLATE_USER_NOT_FOUND: "Login to upload files!", + SERVER_ADD_TO_SLATE_SLATE_NOT_FOUND: + "We ran into issues while uploading that file. Please try again", + SERVER_ADD_TO_SLATE_ERROR: + "We ran into issues while uploading that file. Please try again", + SERVER_FIND_USER_UPDATE_SLATE: + "We ran into issues while uploading that file. Please try again", + SERVER_UPDATE_SLATE_NOT_FOUND: + "We ran into issues while locating that slate. Please try again", + SERVER_UPDATE_SLATE_MUST_PROVIDE_DATA: + "The input cannot be blank. Please check your input", + SERVER_UPDATE_SLATE_MUST_PROVIDE_NAME: "Please provide a slate name", + SERVER_UPDATE_SLATE: + "We're having trouble updating that slate right now. Please try again later", + V1_SERVER_UPLOAD_SLATE_NOT_FOUND: + "We're having trouble locating that slate right now. Please try again later", + V1_SERVER_API_KEY_NOT_FOUND: + "We can't seem to find your API key right now. Please try again later", + V1_SERVER_API_UPLOAD_ERROR: + "We're having trouble uploading that right now. Please try again later", + V1_SERVER_UPLOAD_SLATE_NOT_FOUND: + "We're having trouble locating that slate right now", + V1_SERVER_UPLOAD_TO_SLATE_ERROR: + "We're ran into issues while adding that to the slate. Please try again", + V1_GET_SLATE_NOT_FOUND: + "We're having trouble locating that slate right now. Please try again later", + V1_GET_SLATE_USER_NOT_FOUND: + "We're having trouble locating the owner of that slate right now. Please try again later", + V1_GET_SLATE_SLATE_NOT_FOUND: + "We're having trouble locating that slate right now. Please try again later", + V1_GET_SLATES_NOT_FOUND: + "We're having trouble locating those slates right now. Please try again later", + //Address Send - SEND_FILECOIN: "That user doesn't seem to exist. Please try another", + SERVER_SEND_FILECOIN_USER_NOT_FOUND: "Sorry, we couldn't find that user!", + SERVER_SEND_FILECOIN_NO_ID: + "That user doesn't seem to exist. Please try another", + SERVER_SEND_FILECOIN_ACTION_FAILURE: + "There was an error sending the transaction. We're looking into it", SEND_FILECOIN_USER_NOT_FOUND: "Sorry, we couldn't find that user!", + SEND_FILECOIN: + "There was an error sending the transaction. We're looking into it", SEND_FILECOIN_ACTION_FAILURE: "There was an error sending the transaction. We're looking into it", + //Address Create + CREATE_FILECOIN_ADDRESS: + "There was an error when creating the Filecoin address.", + //Data Upload UPLOAD_PARSE_FAILURE: "There was an error when parsing the upload. Please try again", UPLOAD_NOT_IMAGE_TYPE: "We are only accepting JPG and PNG files at this time. Try uploading a different file type!", BUCKETS_PUSH_ISSUE: "There was an error uploading the data", + SERVER_UPLOAD_ERROR: "We're having issues uploading that file right now", + SERVER_API_KEY_MISSING: + "We can't seem to find your API key right now. Please try again later", //Data CID Status NO_CIDS_TO_CHECK: "There are no CIDs to check", + //Data Get + SERVER_GET_BUCKET_DATA: + "We ran into an issue fetching that data. Please try again later", + + //Data Remove + SERVER_REMOVE_DATA_NO_CID: "We could not locate a file that matches that CID", + SERVER_REMOVE_DATA_NOT_ALLOWED: "You aren't authorized to remove that file", + SERVER_REMOVE_DATA_NO_LINK: + "We couldn't remove that data. Please try again later", + //Data Storage Deals + SERVER_STORAGE_DEAL_USER_NOT_FOUND: "Sorry, we couldn't find that user!", + SERVER_NO_CID: "IPFS CID is required", + SERVER_NO_IPFS: "There was a issue retriving data from IPFS", + SERVER_FILECOIN_STORAGE_DEAL_CID_ERROR: + "There was a issue making a storage deal", + SERVER_NO_JOB: "Sorry, this job doesn't exist!", STORAGE_DEAL_USER_NOT_FOUND: "Sorry, we couldn't find that user!", NO_CID: "IPFS CID is required", NO_IPFS: "There was a issue retriving data from IPFS", FILECOIN_STORAGE_DEAL_CID_ERROR: "There was a issue making a storage deal", NO_JOB: "Sorry, this job doesn't exist!", + //Archive Deal + SERVER_REMOVE_DATA_NOT_ALLOWED: "You aren't authorized to archive that deal", + SERVER_BUCKET_ARCHIVE_DEAL_USER_NOT_FOUND: + "Please login first to archive a deal!", + + //CID Status + SERVER_NO_CIDS_TO_CHECK: "No CIDs were entered, please check your input", + //Users Create + SERVER_EXISTING_USER_ALREADY: + "This username is already taken! Please try another one", EXISTING_USER_ALREADY: "This username is already taken! Please try another one", INVALID_USERNAME: "Invalid username. Please include only letters and numbers", + SERVER_INVALID_USERNAME: + "Invalid username. Please include only letters and numbers", INVALID_PASSWORD: "Password length must be more than 8 characters", - USER_CREATE_USER_NOT_FOUND: "Sorry, we couldn't find that user!", + SERVER_INVALID_PASSWORD: "Password length must be more than 8 characters", + USER_CREATE_USER_NOT_FOUND: + "Sorry we weren't able to create your account. Please try again", + SERVER_USER_CREATE_USER_NOT_FOUND: + "Sorry we weren't able to create your account. Please try again", + CREATE_USER: "Sorry we weren't able to create your account. Please try again", //Users Delete USER_DELETE: "That user doesn't seem to exist. Please try another", + SERVER_USER_DELETE: "That user doesn't seem to exist. Please try another", USER_DELETE_USER_NOT_FOUND: "Sorry, we couldn't find that user!", + SERVER_USER_DELETE_USER_NOT_FOUND: "Sorry, we couldn't find that user!", + DELETE_USER_BY_USERNAME: + "We're having trouble deleting your account right now", + SERVER_USER_DELETE: "We're having trouble deleting your account right now", + USER_NOT_FOUND: "We weren't able to locate that user", + SLATES_NOT_FOUND: "We weren't able to locate the slates for that user", //Users Update USER_UPDATE: "That user doesn't seem to exist. Please try another", USER_UPDATE_USER_NOT_FOUND: "Sorry, we couldn't find that user!", - INVALID_PASSWORD: - "Short passwords are too easy to guess. Try one with more than 8 characters", + UPDATE_USER_BY_ID: + "We ran into an issue while updating your information. Please try again", USER_UPDATE_SETTINGS_CONFIG: "Error when updating user settings", - CREATE_FILECOIN_ADDRESS: - "There was an error when creating the Filecoin address.", + SERVER_USER_UPDATE: "Please make sure you are signed in first", + SERVER_USER_UPDATE_USER_NOT_FOUND: + "We're having trouble locating your information. Please try again", + + //Users Get + GET_USER_BY_ID: + "We weren't able to fetch information on that user. Please try again later", + GET_USER_BY_USERNAME: + "We weren't able to fetch information on that user. Please check your input", + USER_NOT_FOUND: + "We aren't able to locate that user at the moment. Please try again", //Hydrate - HYDRATE_FAILURE: "That user doesn't seem to exist. Please try another", + HYDRATE_FAILURE: "Please make sure you're logged in", + SERVER_HYDRATE_FAILURE: "Please make sure you're logged in", + SERVER_VIEWER_DATA_ERROR: + "We're havign trouble fetching your information right now. Please try again", //Sign-in SIGN_IN: "Your username/password can't be blank", + SERVER_SIGN_IN: "Your username/password can't be blank", SIGN_IN_USER_NOT_FOUND: "Sorry, that user doesn't exist!", + SERVER_SIGN_IN_USER_NOT_FOUND: "Sorry, that user doesn't exist!", SIGN_IN_AUTH: "Incorrect password", + SERVER_SIGN_IN_AUTH: "Incorrect password", + + //Activity + CREATE_ACTIVITY: + "We're having issues posting that right now. Please try again", + DELETE_ACTIVITY_BY_ID: "We weren't able to delete that. Please try again", + GET_ACTIVITY_BY_ID: + "We weren't able to fetch that information. Please try again", + GET_ACTIVITY_FOR_SLATE_ID: + "We weren't able to fetch that information. Please try again", + GET_ACTIVITY_FOR_USER_ID: + "We weren't able to fetch that user's information. Please try again", + + //Subscription Create + CREATE_SUBSCRIPTION: + "We weren't able to subscribe you. Please try again later", + SERVER_SUBSCRIBE: "Please login to subscribe", + SERVER_SUBSCRIBE_USER_NOT_FOUND: + "We're having trouble fetching your information. Please try again later", + SERVER_SUBSCRIBE_MUST_PROVIDE_SLATE_OR_USER: + "No user or slate was provided. Please check your input", + SERVER_SUBSCRIBE_CAN_NOT_SUBSCRIBE_TO_YOURSELF: + "You cannot subscribe to yourself", + SERVER_SUBSCRIBE_TARGET_USER_NOT_FOUND: "That user could not be found", + SERVER_SUBSCRIBE_TARGET_SLATE_NOT_FOUND: "That slate could not be found", + SERVER_SUBSCRIBE_SUBSCRIPTION_CHECK_ERROR: + "We weren't able to subscribe you. Please try again later", + SERVER_UNSUBSCRIBE_NOT_FOUND: + "We weren't able to unsubscribe you. Please try again", + SERVER_UNSUBSCRIBE_ERROR: + "We weren't able to unsubscribe you. Please try again", + SERVER_SUBSCRIBE_NOT_FOUND: + "We weren't able to subscribe you. Please try again", + SERVER_SUBSCRIBE_ERROR: "We weren't able to subscribe you. Please try again", + + //Subscription Delete + DELETE_SUBSCRIPTION_BY_ID: + "We weren't able to unsubscribe you. Please try again later", + + //Subscription Get + GET_SUBSCRIBERS_BY_USER_ID: + "We weren't able to retrieve that information. Please try again later", + GET_SUBSCRIPTION_BY_ID: + "We weren't able to retrieve that subscription information. Please try again later", + GET_SUBSCRIPTIONS_BY_USER_ID: + "We weren't able to retrieve that information. Please try again later", + GET_SUBSCRIPTIONS_TO_SLATE_ID: + "We weren't able to retrieve that information. Please try again later", + GET_SUBSCRIPTIONS_TO_USER_ID: + "We weren't able to retrieve that information. Please try again later", + + //Trusted Create + CREATE_TRUSTED_RELATIONSHIP: + "We weren't able to add this user as trusted. Please try again later", + SERVER_TRUST: "Please make sure you are logged in", + SERVER_TRUSTED_RELATIONSHIP_USER_NOT_FOUND: + "We are having trouble retrieving your information right now", + SERVER_TRUSTED_RELATIONSHIP_MUST_PROVIDE_SOMEONE_TO_TRUST: + "No user was specified", + SERVER_TRUSTED_RELATIONSHIP_CAN_NOT_TRUST_YOURSELF: + "You cannot add yourself as trusted", + SERVER_TRUSTED_RELATIONSHIP_TARGET_USER_NOT_FOUND: + "We could not locate that user. Please try again later", + SERVER_TRUSTED_RELATIONSHIP_CHECK_ERROR: + "We're having trouble adding this person as your trusted right now", + SERVER_TRUSTED_RELATIONSHIP_INVERTED_CHECK_ERROR: + "You have already received a trust request from this person. Please accept it instead", + SERVER_DELETE_TRUSTED_RELATIONSHIP_NOT_FOUND: + "There is no trust relationshp to delete", + SERVER_DELETE_TRUSTED_RELATIONSHIP_ERROR: + "We're having trouble deleting this trust relationship right now", + SERVER_TRUSTED_RELATIONSHIP_NOT_FOUND: + "We're having trouble creating this trust relationship right now", + SERVER_TRUSTED_RELATIONSHIP_ERROR: + "We're having trouble creating this trust relationship right now", + + //Trusted Delete + DELETE_TRUSTED_RELATIONSHIP_BY_ID: + "We weren't able to remove this user from your trusted. Please try again later", + SERVER_TRUST_DELETE: "Please login to manage your trusted", + SERVER_TRUST_DELETE_USER_NOT_FOUND: + "We weren't able to locate this user. Please try again later", + SERVER_TRUST_DELETE_MUST_PROVIDE_ID: "Please check your input", + + //Trusted Get + GET_TRUSTED_RELATIONSHIP_BY_ID: + "We're having trouble retrieving that information right now. Please try again later", + GET_TRUSTED_RELATIONSHIP_BY_IDS: + "We're having trouble retrieving that information right now. Please try again later", + GET_TRUSTED_RELATIONSHIPS_BY_USER_ID: + "We're having trouble retrieving that information right now. Please try again later", + + //Trusted Update + UPDATE_TRUSTED_RELATIONSHIP_BY_ID: + "We ran into an issue while updating that information. Please try again later", + SERVER_TRUST_UPDATE: "Please login to mange your trusted", + SERVER_TRUST_UPDATE_USER_NOT_FOUND: + "We weren't able to locate your information. Please try again later", + SERVER_TRUST_UPDATE_MUST_PROVIDE_SOMEONE_TO_TRUST: + "Please check your input. No user was provided", + SERVER_TRUST_UPDATE_CAN_NOT_TRUST_YOURSELF: + "You cannot add yourself as a trusted peer", + SERVER_TRUST_UPDATE_TARGET_USER_NOT_FOUND: + "We weren't able to locate that user. Please try again later", + SERVER_TRUST_UPDATE_CHECK_ERROR: + "This person is already among your trusted peers", + + //API Key Create + CREATE_API_KEY_FOR_USER_ID: + "We're having trouble creating your API keys right now. Please try again", + SERVER_GENERATE_API_KEY_AUTH: "You aren't authorized to create that API key", + SERVER_GENERATE_API_KEY_USER_NOT_FOUND: + "We ran into issues finding your information while trying to generate that API key", + SERVER_GENERATE_API_KEY_TOO_MANY_KEYS: + "You have reached the limit for number of API keys", + SERVER_GENERATE_API_KEY_ERROR: + "We ran into issues while trying to generate that API key", + + //API Key Delete + DELETE_API_KEY_BY_ID: + "We're having trouble deleting that API key right now. Please try again later", + DELETE_API_KEYS_FOR_USER_ID: + "We're having trouble deleting your API keys right now. Please try again later", + SERVER_DELETE_API_KEY_AUTH: "You aren't authorized to delete that API key", + SERVER_DELETE_API_KEY_USER_NOT_FOUND: + "No matching API key was found for that user", + SERVER_DELETE_API_KEY_NOT_FOUND: + "No matching API key was found for that user", + SERVER_DELETE_API_KEY_ERROR: + "We ran into an issue while trying to delete that API key. Please try again", + + //API Key Get + GET_API_KEY_BY_KEY: + "We weren't able to fetch that API key. Please try again later", + GET_API_KEY: "We weren't able to fetch that API key. Please try again later", + GET_API_KEYS_BY_USER_ID: + "We're having trouble retrieving your API keys right now. Please try again", + + //Query + SERVER_DEEPLINK: + "We ran into issues while trying to retrieve that information. Please try again", + SERVER_DEEPLINK_ERROR: + "We ran into issues while trying to retrieve that information. Please try again", + SERVER_SEARCH_NO_QUERY: + "No query was entered. Please enter a query and try again", + + //Add url }; diff --git a/components/core/Alert.js b/components/core/Alert.js new file mode 100644 index 00000000..908dffda --- /dev/null +++ b/components/core/Alert.js @@ -0,0 +1,124 @@ +import * as React from "react"; +import * as Strings from "~/common/strings"; +import * as Constants from "~/common/constants"; + +import { error } from "~/common/messages"; + +import { css } from "@emotion/react"; + +const STYLES_ALERT = css` + box-sizing: border-box; + z-index: ${Constants.zindex.modal}; + position: fixed; + top: 56px; + width: calc(100% - ${Constants.sizes.navigation}px); + min-height: 48px; + background-color: ${Constants.system.red}; + color: ${Constants.system.white}; + padding: 12px 48px; + display: flex; + flex-wrap: wrap; + align-items: center; + + @media (max-width: ${Constants.sizes.mobile}px) { + width: calc(100% - 60px); + } +`; + +export class Alert extends React.Component { + state = { + alert: null, + }; + + componentDidMount = () => { + window.addEventListener("create-alert", this._handleCreate); + window.addEventListener("click", this._handleDelete); + }; + + componentWillUnmount = () => { + window.removeEventListener("create-alert", this._handleCreate); + window.removeEventListener("click", this._handleDelete); + }; + + _handleCreate = (e) => { + this.setState({ alert: e.detail.alert }); + }; + + _handleDelete = (e) => { + if (this.state.alert) { + this.setState({ alert: null }); + } + }; + + render() { + if (!this.state.alert) { + return null; + } + return ( +
+ {this.state.alert.message + ? this.state.alert.message + : this.state.alert.decorator + ? error[this.state.alert.decorator] || + "Whoops something went wrong! Please try again." + : "Whoops something went wrong! Please try again."} +
+ ); + } +} + +export class Confirm extends React.Component { + state = { + alert: null, + }; + + componentDidMount = () => { + window.addEventListener("create-alert", this._handleCreate); + window.addEventListener("click", this._handleDelete); + }; + + componentWillUnmount = () => { + window.removeEventListener("create-alert", this._handleCreate); + window.removeEventListener("click", this._handleDelete); + }; + + _handleCreate = (e) => { + this.setState({ alert: e.detail.alert }); + }; + + _handleDelete = (e) => { + if (this.state.alert) { + this.setState({ alert: null }); + } + }; + + render() { + if (!this.state.alert) { + return null; + } + return ( +
+ {this.state.alert.message + ? this.state.alert.message + : this.state.alert.decorator + ? error[this.state.alert.decorator] || + "Whoops something went wrong! Please try again." + : "Whoops something went wrong! Please try again."} +
+ ); + } +} diff --git a/components/core/Application.js b/components/core/Application.js index 983ee4d5..ba0f502e 100644 --- a/components/core/Application.js +++ b/components/core/Application.js @@ -115,7 +115,17 @@ export default class ApplicationPage extends React.Component { } _handleOnlineStatus = async () => { - window.alert(navigator.onLine ? "online" : "offline"); + if (navigator.onLine) { + dispatchCustomEvent({ + name: "create-alert", + detail: { alert: { message: "Back online!", status: "INFO" } }, + }); + } else { + dispatchCustomEvent({ + name: "create-alert", + detail: { alert: { message: "Offline. Trying to reconnect" } }, + }); + } this.setState({ online: navigator.onLine }); }; @@ -176,8 +186,7 @@ export default class ApplicationPage extends React.Component { this.setState({ fileLoading: true }); - // TODO(jim): - // Refactor later + // TODO(jim): Refactor later const navigation = NavigationData.generate(this.state.viewer); const next = this.state.history[this.state.currentIndex]; const current = NavigationData.getCurrentById(navigation, next.id); @@ -213,7 +222,14 @@ export default class ApplicationPage extends React.Component { } if (!files.length) { - alert("TODO: Files not supported error"); + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { + message: "File type not supported. Please try a different file", + }, + }, + }); this._handleRegisterFileLoading({ fileLoading: null }); return; } @@ -239,7 +255,14 @@ export default class ApplicationPage extends React.Component { const response = await Actions.hydrateAuthenticatedUser(); if (!response || response.error) { - alert("TODO: error fetching authenticated viewer"); + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { + message: "We encountered issues while refreshing. Please try again", + }, + }, + }); return null; } @@ -299,8 +322,7 @@ export default class ApplicationPage extends React.Component { }; _handleDeleteYourself = async () => { - // TODO(jim): - // Put this somewhere better for messages. + // TODO(jim): Put this somewhere better for messages. const message = "Do you really want to delete your account? It will be permanently removed"; if (!window.confirm(message)) { @@ -391,11 +413,17 @@ export default class ApplicationPage extends React.Component { } if (options.type === "ACTION") { - return alert(JSON.stringify(options)); + dispatchCustomEvent({ + name: "create-alert", + detail: { alert: { message: JSON.stringify(options), status: "INFO" } }, + }); } if (options.type === "DOWNLOAD") { - return alert(JSON.stringify(options)); + dispatchCustomEvent({ + name: "create-alert", + detail: { alert: { message: JSON.stringify(options), status: "INFO" } }, + }); } if (options.type === "SIDEBAR") { @@ -405,7 +433,7 @@ export default class ApplicationPage extends React.Component { }); } - return alert(JSON.stringify(options)); + return alert(JSON.stringify(options)); //TODO(martina): convert to alert? }; _handleNavigateTo = (next, data = null) => { diff --git a/components/core/ApplicationLayout.js b/components/core/ApplicationLayout.js index 725a58b3..0ef5fba6 100644 --- a/components/core/ApplicationLayout.js +++ b/components/core/ApplicationLayout.js @@ -5,6 +5,7 @@ import * as SVG from "~/common/svg"; import { css } from "@emotion/react"; import { GlobalTooltip } from "~/components/system/components/fragments/GlobalTooltip"; import { Boundary } from "~/components/system/components/fragments/Boundary"; +import { Alert } from "~/components/core/Alert"; const STYLES_SCROLL = css` overflow-y: scroll; @@ -197,6 +198,7 @@ export default class ApplicationLayout extends React.Component {
+
{this.props.header}
- {/* //change this to allways allow uploads */} + )} - {/* maybe send an alert if fails here */}
)) diff --git a/components/sidebars/SidebarCreatePaymentChannel.js b/components/sidebars/SidebarCreatePaymentChannel.js index 63389589..a9a43b00 100644 --- a/components/sidebars/SidebarCreatePaymentChannel.js +++ b/components/sidebars/SidebarCreatePaymentChannel.js @@ -5,6 +5,7 @@ import * as SVG from "~/common/svg"; import * as System from "~/components/system"; import { css } from "@emotion/react"; +import { dispatchCustomEvent } from "~/common/custom-events"; const STYLES_FOCUS = css` font-size: ${Constants.typescale.lvl1}; @@ -31,7 +32,12 @@ export default class SidebarCreatePaymentChannel extends React.Component { state = { address: "", amount: "" }; _handleSubmit = () => { - alert("TODO: Create a new payment channel"); + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { message: "Creating payment channel...", status: "INFO" }, + }, + }); this.props.onSubmit({}); }; diff --git a/components/sidebars/SidebarCreateSlate.js b/components/sidebars/SidebarCreateSlate.js index 2ad3c3ca..30a116dd 100644 --- a/components/sidebars/SidebarCreateSlate.js +++ b/components/sidebars/SidebarCreateSlate.js @@ -4,6 +4,8 @@ import * as Constants from "~/common/constants"; import * as System from "~/components/system"; import * as Validations from "~/common/validations"; +import { dispatchCustomEvent } from "~/common/custom-events"; + const SLATE_LIMIT = 20; export default class SidebarCreateSlate extends React.Component { @@ -14,14 +16,24 @@ export default class SidebarCreateSlate extends React.Component { _handleSubmit = async () => { if (this.props.viewer.slates.length >= SLATE_LIMIT) { - alert("You have reached the limit of 20 Slates."); + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { message: "You have reached the limit of 20 Slates!" }, + }, + }); return; } this.setState({ loading: true }); if (!Validations.slatename(this.state.name)) { - alert("Please provide a name under 48 characters."); + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { message: "Please provide a name under 48 characters." }, + }, + }); this.setState({ loading: false }); return; } @@ -31,10 +43,24 @@ export default class SidebarCreateSlate extends React.Component { name: this.state.name, }); - if (response && response.error) { - alert( - "Something went wrong while trying to create your new slate. Please try again." - ); + 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; } diff --git a/components/sidebars/SidebarDeleteWalletAddress.js b/components/sidebars/SidebarDeleteWalletAddress.js index 65447d6b..59569f03 100644 --- a/components/sidebars/SidebarDeleteWalletAddress.js +++ b/components/sidebars/SidebarDeleteWalletAddress.js @@ -5,10 +5,16 @@ import * as SVG from "~/common/svg"; import * as System from "~/components/system"; import { css } from "@emotion/react"; +import { dispatchCustomEvent } from "~/common/custom-events"; export default class SidebarDeleteWalletAddress extends React.Component { _handleSubmit = () => { - alert("TODO: Delete wallet address"); + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { message: "Deleting wallet address...", status: "INFO" }, + }, + }); this.props.onSubmit({}); }; diff --git a/components/sidebars/SidebarFilecoinArchive.js b/components/sidebars/SidebarFilecoinArchive.js index a34b6af1..4fac2eb4 100644 --- a/components/sidebars/SidebarFilecoinArchive.js +++ b/components/sidebars/SidebarFilecoinArchive.js @@ -6,6 +6,7 @@ import * as SVG from "~/common/svg"; import * as System from "~/components/system"; import { css } from "@emotion/react"; +import { dispatchCustomEvent } from "~/common/custom-events"; export default class SidebarFilecoinArchive extends React.Component { async componentDidMount() {} @@ -13,7 +14,12 @@ export default class SidebarFilecoinArchive extends React.Component { _handleMakeDeal = async () => { const response = await Actions.archive(); console.log(response); - alert("TODO: Still working on archiving issues."); + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { message: "Deal archiving is still under development" }, + }, + }); }; _handleSubmit = async (e) => { diff --git a/components/sidebars/SidebarSingleSlateSettings.js b/components/sidebars/SidebarSingleSlateSettings.js index 7dbf66b3..1c8aa814 100644 --- a/components/sidebars/SidebarSingleSlateSettings.js +++ b/components/sidebars/SidebarSingleSlateSettings.js @@ -5,6 +5,7 @@ import * as System from "~/components/system"; import * as Strings from "~/common/strings"; import { css } from "@emotion/react"; +import { dispatchCustomEvent } from "~/common/custom-events"; const STYLES_GROUP = css` display: flex; @@ -56,12 +57,23 @@ export default class SidebarSingleSlateSettings extends React.Component { }); if (!response) { - alert("TODO: Server Error"); + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { + message: + "We're having trouble connecting right now. Please try again later", + }, + }, + }); return this.setState({ loading: false }); } if (response.error) { - alert(`TODO: ${response.decorator}`); + dispatchCustomEvent({ + name: "create-alert", + detail: { alert: { decorator: response.decorator } }, + }); return this.setState({ loading: false }); } @@ -92,12 +104,23 @@ export default class SidebarSingleSlateSettings extends React.Component { }); if (!response) { - alert("TODO: Server Error"); + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { + message: + "We're having trouble connecting right now. Please try again later", + }, + }, + }); return this.setState({ loading: false }); } if (response.error) { - alert(`TODO: ${response.decorator}`); + dispatchCustomEvent({ + name: "create-alert", + detail: { alert: { decorator: response.decorator } }, + }); return this.setState({ loading: false }); } diff --git a/components/sidebars/SidebarWalletSendFunds.js b/components/sidebars/SidebarWalletSendFunds.js index 80ae0917..da36a75d 100644 --- a/components/sidebars/SidebarWalletSendFunds.js +++ b/components/sidebars/SidebarWalletSendFunds.js @@ -4,6 +4,7 @@ import * as Constants from "~/common/constants"; import * as System from "~/components/system"; import { css } from "@emotion/react"; +import { dispatchCustomEvent } from "~/common/custom-events"; const STYLES_FOCUS = css` font-size: ${Constants.typescale.lvl1}; @@ -43,9 +44,15 @@ export default class SidebarWalletSendFunds extends React.Component { const currentAddress = addresses[this.props.selected.address]; if (currentAddress.address === this.state.address) { - alert( - "TODO: Proper message for not allowing poeple to send funds to the same address." - ); + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { + message: + "You cannot send funds from an address to itself. Please enter a different address", + }, + }, + }); this.setState({ loading: false }); return; diff --git a/components/system/components/Typography.js b/components/system/components/Typography.js index 8461c6c2..8288884b 100644 --- a/components/system/components/Typography.js +++ b/components/system/components/Typography.js @@ -4,6 +4,7 @@ import * as Actions from "~/common/actions"; import * as StringReplace from "~/vendor/react-string-replace"; import { css } from "@emotion/react"; +import { dispatchCustomEvent } from "~/common/custom-events"; const LINK_STYLES = ` font-family: ${Constants.font.text}; @@ -37,12 +38,38 @@ const onDeepLink = async (object) => { deeplink: true, }); - if (!response.data) { - alert("TODO: Can not find deeplink"); + if (!response) { + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { + message: + "We're having trouble connecting right now. Please try again later", + }, + }, + }); + return; } - if (!response.data.slate) { - alert("TODO: Can not find deeplink"); + if (response.error) { + dispatchCustomEvent({ + name: "create-alert", + detail: { alert: { decorator: response.decorator } }, + }); + return; + } + + if (!response.data || !response.data.slate) { + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { + message: + "We encountered issues while locating that deeplink. Please try again later", + }, + }, + }); + return; } return window.open( @@ -64,7 +91,8 @@ export const ProcessedText = ({ text }) => { css={STYLES_LINK} key={match + i} target="_blank" - href={`/${match}`.toLowerCase()}> + href={`/${match}`.toLowerCase()} + > @{match} )); @@ -73,7 +101,8 @@ export const ProcessedText = ({ text }) => { onDeepLink({ deeplink: match.toLowerCase() })}> + onClick={() => onDeepLink({ deeplink: match.toLowerCase() })} + > #{match} )); diff --git a/components/system/modules/CreateFilecoinStorageDeal.js b/components/system/modules/CreateFilecoinStorageDeal.js index 6704b2a7..207c3307 100644 --- a/components/system/modules/CreateFilecoinStorageDeal.js +++ b/components/system/modules/CreateFilecoinStorageDeal.js @@ -6,6 +6,7 @@ import { } from "~/components/system/components/Buttons"; import { css } from "@emotion/react"; +import { dispatchCustomEvent } from "~/common/custom-events"; const STYLES_CONTAINER = css` font-family: ${Constants.font.text}; @@ -53,7 +54,16 @@ const STYLES_ITEM = css` export class CreateFilecoinStorageDeal extends React.Component { static defaultProps = { - onSubmit: () => alert("onSubmit"), + onSubmit: () => { + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { + message: "Filecoin storage deals are still under development", + }, + }, + }); + }, }; state = { file: null }; @@ -63,7 +73,12 @@ export class CreateFilecoinStorageDeal extends React.Component { let file = e.target.files[0]; if (!file) { - alert("Something went wrong"); + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { message: "Something went wrong. Please try again" }, + }, + }); return; } diff --git a/pages/_/experiences/create-address.js b/pages/_/experiences/create-address.js index 1e46c9dc..c3e1e706 100644 --- a/pages/_/experiences/create-address.js +++ b/pages/_/experiences/create-address.js @@ -5,6 +5,8 @@ import SystemPage from "~/components/system/SystemPage"; import ViewSourceLink from "~/components/system/ViewSourceLink"; import CodeBlock from "~/components/system/CodeBlock"; +import { dispatchCustomEvent } from "~/common/custom-events"; + const EXAMPLE_CODE = `import * as React from "react"; import { CreateFilecoinAddress } from "slate-react-system"; import { createPow } from "@textile/powergate-client"; @@ -32,7 +34,13 @@ class Example extends React.Component { export default class SystemPageCreateAddress extends React.Component { _handleSubmit = ({ name, type, makeDefault }) => { - alert(JSON.stringify({ name, type, makeDefault })); + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { message: JSON.stringify({ name, type, makeDefault }) }, + status: "INFO", + }, + }); }; render() { diff --git a/pages/_/experiences/filecoin-settings.js b/pages/_/experiences/filecoin-settings.js index 95fddd7f..0802752a 100644 --- a/pages/_/experiences/filecoin-settings.js +++ b/pages/_/experiences/filecoin-settings.js @@ -5,6 +5,8 @@ import SystemPage from "~/components/system/SystemPage"; import ViewSourceLink from "~/components/system/ViewSourceLink"; import CodeBlock from "~/components/system/CodeBlock"; +import { dispatchCustomEvent } from "~/common/custom-events"; + const addrsList = [ { addr: @@ -82,7 +84,11 @@ class Example extends React.Component { export default class SystemPageFilecoinSettings extends React.Component { _handleSave = async (storageConfig) => { - alert("Saved"); + // TODO(jim): Send setings data to server. + dispatchCustomEvent({ + name: "create-alert", + detail: { alert: { message: "Saved!", status: "INFO" } }, + }); }; render() { diff --git a/pages/_/experiences/make-storage-deal.js b/pages/_/experiences/make-storage-deal.js index c4824e3b..7de1cf58 100644 --- a/pages/_/experiences/make-storage-deal.js +++ b/pages/_/experiences/make-storage-deal.js @@ -5,6 +5,8 @@ import SystemPage from "~/components/system/SystemPage"; import ViewSourceLink from "~/components/system/ViewSourceLink"; import CodeBlock from "~/components/system/CodeBlock"; +import { dispatchCustomEvent } from "~/common/custom-events"; + const EXAMPLE_CODE = `import * as React from "react"; import { CreateFilecoinStorageDeal } from "slate-react-system"; import { createPow } from "@textile/powergate-client"; @@ -58,7 +60,12 @@ class Example extends React.Component { export default class SystemPageMakeStorageDeal extends React.Component { _handleSubmit = async ({ file }) => { // TODO(jim): Send file data to server. - alert(file); + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { message: "Storage deals are still under development" }, + }, + }); }; render() { diff --git a/pages/_/experiences/send-address-filecoin.js b/pages/_/experiences/send-address-filecoin.js index a8d621c6..766785fd 100644 --- a/pages/_/experiences/send-address-filecoin.js +++ b/pages/_/experiences/send-address-filecoin.js @@ -5,6 +5,8 @@ import SystemPage from "~/components/system/SystemPage"; import ViewSourceLink from "~/components/system/ViewSourceLink"; import CodeBlock from "~/components/system/CodeBlock"; +import { dispatchCustomEvent } from "~/common/custom-events"; + const EXAMPLE_CODE = `import * as React from "react"; import { SendAddressFilecoin } from "slate-react-system"; import { createPow } from "@textile/powergate-client"; @@ -31,7 +33,15 @@ class Example extends React.Component { export default class SystemPageSendAddressFilecoin extends React.Component { _handleSubmit = ({ source, target, amount }) => { - alert(JSON.stringify({ source, target, amount })); + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { + message: JSON.stringify({ source, target, amount }), + status: "INFO", + }, + }, + }); }; render() { diff --git a/pages/_/integration-page.js b/pages/_/integration-page.js index 7d134623..e0362f70 100644 --- a/pages/_/integration-page.js +++ b/pages/_/integration-page.js @@ -4,6 +4,7 @@ import * as System from "~/components/system"; import * as Actions from "~/common/actions"; import { css } from "@emotion/react"; +import { dispatchCustomEvent } from "~/common/custom-events"; const STYLES_ITEM = css` font-size: 12px; @@ -53,11 +54,26 @@ export default class IntegrationPage extends React.Component { _handleUpdate = async (e) => { const response = await Actions.hydrateAuthenticatedUser(); - if (!response || response.error) { - alert("TODO: error fetching authenticated viewer"); + if (!response) { + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { + message: + "We're having trouble connecting right now. Please try again later", + }, + }, + }); return null; } + if (response.error) { + dispatchCustomEvent({ + name: "create-alert", + detail: { alert: { decorator: response.decorator } }, + }); + } + const updates = { viewer: response.data, }; diff --git a/pages/api/addresses/send.js b/pages/api/addresses/send.js index cecc0ad9..f9b66d82 100644 --- a/pages/api/addresses/send.js +++ b/pages/api/addresses/send.js @@ -7,7 +7,7 @@ export default async (req, res) => { if (!id) { return res .status(500) - .send({ decorator: "SERVER_SEND_FILECOIN", error: true }); + .send({ decorator: "SERVER_SEND_FILECOIN_NO_ID", error: true }); } const user = await Data.getUserById({ diff --git a/pages/api/users/delete.js b/pages/api/users/delete.js index e8c919cf..aa7b1471 100644 --- a/pages/api/users/delete.js +++ b/pages/api/users/delete.js @@ -56,7 +56,7 @@ export default async (req, res) => { if (!deleted) { return res - .status(200) + .status(500) .send({ decorator: "SERVER_USER_DELETE", error: true }); } diff --git a/scenes/SceneEditAccount.js b/scenes/SceneEditAccount.js index 893ca885..0cf4c461 100644 --- a/scenes/SceneEditAccount.js +++ b/scenes/SceneEditAccount.js @@ -7,6 +7,7 @@ import * as Validations from "~/common/validations"; import * as FileUtilities from "~/common/file-utilities"; import { css } from "@emotion/react"; +import { dispatchCustomEvent } from "~/common/custom-events"; import ScenePage from "~/components/core/ScenePage"; import Avatar from "~/components/core/Avatar"; @@ -48,20 +49,35 @@ export default class SceneEditAccount extends React.Component { let file = e.target.files[0]; if (!file) { - alert("TODO: Something went wrong"); + 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 (!file.type.startsWith("image/")) { - alert("TODO: Error message for not an image."); + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { message: "Upload failed. Only images and gifs are allowed" }, + }, + }); return; } const json = await FileUtilities.upload({ file }); if (json.error) { - alert("TODO: Image already exists in bucket error message"); + dispatchCustomEvent({ + name: "create-alert", + detail: { alert: { decorator: json.decorator } }, + }); this.setState({ changingAvatar: false }); return; } @@ -100,7 +116,14 @@ export default class SceneEditAccount extends React.Component { this.setState({ changingUsername: true }); if (!Validations.username(this.state.username)) { - alert("TODO: Not a valid username"); + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { + message: "Please include only letters and numbers in your username", + }, + }, + }); this.setState({ changingUsername: false }); return; } @@ -126,13 +149,21 @@ export default class SceneEditAccount extends React.Component { _handleChangePassword = async (e) => { this.setState({ changingPassword: true }); if (this.state.password !== this.state.confirm) { - alert("TODO: Error message for non-matching passwords"); + dispatchCustomEvent({ + name: "create-alert", + detail: { alert: { message: "Passwords did not match" } }, + }); this.setState({ changingPassword: false }); return; } if (!Validations.password(this.state.password)) { - alert("TODO: Not a valid password"); + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { message: "Password length must be more than 8 characters" }, + }, + }); this.setState({ changingPassword: false }); return; } diff --git a/scenes/SceneProfile.js b/scenes/SceneProfile.js index 1f0a6b85..37cfac8f 100644 --- a/scenes/SceneProfile.js +++ b/scenes/SceneProfile.js @@ -9,6 +9,7 @@ import { ButtonPrimary, ButtonSecondary, } from "~/components/system/components/Buttons"; +import { dispatchCustomEvent } from "~/common/custom-events"; import ScenePage from "~/components/core/ScenePage"; import Profile from "~/components/core/Profile"; @@ -75,8 +76,24 @@ export default class SceneProfile extends React.Component { _handleUpdate = async (e) => { let response = await this.props.onRehydrate(); - if (!response || response.error) { - alert("TODO: error fetching authenticated viewer"); + if (!response) { + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { + message: + "We're having trouble connecting right now. Please try again later", + }, + }, + }); + return null; + } + + if (response.error) { + dispatchCustomEvent({ + name: "create-alert", + detail: { alert: { decorator: response.decorator } }, + }); return null; } diff --git a/scenes/SceneSettingsDeveloper.js b/scenes/SceneSettingsDeveloper.js index c69a1a28..d28e826f 100644 --- a/scenes/SceneSettingsDeveloper.js +++ b/scenes/SceneSettingsDeveloper.js @@ -5,6 +5,7 @@ import * as System from "~/components/system"; import * as SVG from "~/common/svg"; import { css } from "@emotion/react"; +import { dispatchCustomEvent } from "~/common/custom-events"; import ScenePage from "~/components/core/ScenePage"; import ScenePageHeader from "~/components/core/ScenePageHeader"; @@ -83,7 +84,8 @@ class Key extends React.Component { onClick={this._handleToggleVisible} style={{ marginRight: 8, - }}> + }} + > this._handleDelete(this.props.data.id)} style={{ marginRight: 4, - }}> + }} + > @@ -192,9 +195,24 @@ export default class SceneSettingsDeveloper extends React.Component { this.setState({ loading: true }); const response = await Actions.generateAPIKey(); - if (response && response.error) { - // TODO(jim): Proper error message. - alert(response.decorator); + if (!response) { + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { + message: + "We're having trouble connecting right now. Please try again later", + }, + }, + }); + return this.setState({ loading: false }); + } + + if (response.error) { + dispatchCustomEvent({ + name: "create-alert", + detail: { alert: { decorator: response.decorator } }, + }); return this.setState({ loading: false }); } @@ -216,15 +234,26 @@ export default class SceneSettingsDeveloper extends React.Component { } const response = await Actions.deleteAPIKey({ id }); - if (response && response.error) { - // TODO(jim): Proper error message. - alert(response.decorator); + if (!response) { + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { + message: + "We're having trouble connecting right now. Please try again later", + }, + }, + }); return this.setState({ loading: false }); } - await this.props.onRehydrate(); - - this.setState({ loading: false }); + if (response.error) { + dispatchCustomEvent({ + name: "create-alert", + detail: { alert: { decorator: response.decorator } }, + }); + return this.setState({ loading: false }); + } }; async componentDidMount() { @@ -278,7 +307,8 @@ export default class SceneSettingsDeveloper extends React.Component {
+ loading={this.state.loading} + > Generate
diff --git a/scenes/SceneSignIn.js b/scenes/SceneSignIn.js index 932f7677..ccd9e248 100644 --- a/scenes/SceneSignIn.js +++ b/scenes/SceneSignIn.js @@ -7,6 +7,7 @@ import * as Strings from "~/common/strings"; import { css } from "@emotion/react"; import { Logo } from "~/common/logo"; +import { dispatchCustomEvent } from "~/common/custom-events"; import WebsitePrototypeHeader from "~/components/core/WebsitePrototypeHeader"; import WebsitePrototypeFooter from "~/components/core/WebsitePrototypeFooter"; @@ -123,15 +124,25 @@ export default class SceneSignIn extends React.Component { await delay(100); if (!Validations.username(this.state.username)) { - alert( - "Your username was invalid, only characters and numbers are allowed." - ); + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { + message: "Only characters and numbers are allowed in usernames", + }, + }, + }); this.setState({ loading: false }); return; } if (!Validations.password(this.state.password)) { - alert("Your password must be at least 8 characters."); + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { message: "Your password must be at least 8 characters" }, + }, + }); this.setState({ loading: false }); return; } @@ -141,8 +152,25 @@ export default class SceneSignIn extends React.Component { password: this.state.password, }); - if (!response || response.error) { - alert("We could not sign you into your account, try again later."); + if (!response) { + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { + message: + "We could not sign you into your account, 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; } diff --git a/scenes/SceneSlate.js b/scenes/SceneSlate.js index 24f66216..32cd434e 100644 --- a/scenes/SceneSlate.js +++ b/scenes/SceneSlate.js @@ -182,12 +182,23 @@ export default class SceneSlate extends React.Component { if (!response) { this.setState({ loading: false, saving: "ERROR" }); - alert("TODO: Server Error"); + System.dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { + message: + "We're having trouble connecting right now. Please try again later", + }, + }, + }); } if (response.error) { this.setState({ loading: false, saving: "ERROR" }); - alert(`TODO: ${response.decorator}`); + System.dispatchCustomEvent({ + name: "create-alert", + detail: { alert: { decorator: response.decorator } }, + }); } await this.props.onRehydrate(); @@ -297,7 +308,15 @@ export default class SceneSlate extends React.Component { name: "state-global-carousel-loading", detail: { loading: false }, }); - alert("TODO: Server Error"); + System.dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { + message: + "We're having trouble connecting right now. Please try again later", + }, + }, + }); } if (response.error) { @@ -305,7 +324,10 @@ export default class SceneSlate extends React.Component { name: "state-global-carousel-loading", detail: { loading: false }, }); - alert(`TODO: ${response.decorator}`); + System.dispatchCustomEvent({ + name: "create-alert", + detail: { alert: { decorator: response.decorator } }, + }); } this._handleUpdateCarousel({ @@ -358,13 +380,36 @@ export default class SceneSlate extends React.Component { deeplink: true, }); - if (!response.data) { - alert("Could not find Slate."); + if (!response || !response.data) { + System.dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { + message: + "We're having trouble finding that slate right now. Please try again later", + }, + }, + }); return; } + if (response.error) { + System.dispatchCustomEvent({ + name: "create-alert", + detail: { alert: { decorator: response.decorator } }, + }); + } + if (!response.data.slate) { - alert("Could not find Slate."); + System.dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { + message: + "We're having trouble finding that slate right now. Please try again later", + }, + }, + }); return; } diff --git a/scenes/SceneWallet.js b/scenes/SceneWallet.js index aba70818..88e2120c 100644 --- a/scenes/SceneWallet.js +++ b/scenes/SceneWallet.js @@ -5,6 +5,7 @@ import * as SVG from "~/common/svg"; import * as System from "~/components/system"; import { css } from "@emotion/react"; +import { dispatchCustomEvent } from "~/common/custom-events"; import Section from "~/components/core/Section"; import ScenePage from "~/components/core/ScenePage"; @@ -101,7 +102,10 @@ export default class SceneWallet extends React.Component { _handleCopy = (text) => { Strings.copyText(text); - alert(`${text} Added to clipboard.`); + dispatchCustomEvent({ + name: "create-alert", + detail: { alert: { message: "Copied to clipboard!", status: "INFO" } }, + }); }; render() {