diff --git a/common/actions.js b/common/actions.js
index 0dcd8196..3d14dfbd 100644
--- a/common/actions.js
+++ b/common/actions.js
@@ -69,7 +69,7 @@ export const sendFilecoin = async (data) => {
};
export const checkUsername = async (data) => {
- return await returnJSON(`/api/users/check`, {
+ return await returnJSON(`/api/users/check-username`, {
...DEFAULT_OPTIONS,
body: JSON.stringify({ data }),
});
@@ -91,13 +91,6 @@ export const removeFromBucket = async (data) => {
});
};
-export const getNetworkDirectory = async () => {
- await Websockets.checkWebsocket();
- return await returnJSON(`/api/directory`, {
- ...DEFAULT_OPTIONS,
- });
-};
-
export const getSlateById = async (data) => {
await Websockets.checkWebsocket();
return await returnJSON(`/api/slates/get`, {
@@ -167,25 +160,18 @@ export const search = async (data) => {
});
};
-export const createPendingFiles = async (data) => {
+export const createFile = async (data) => {
await Websockets.checkWebsocket();
- return await returnJSON(`/api/data/create-pending`, {
+ return await returnJSON(`/api/data/create`, {
...DEFAULT_OPTIONS,
body: JSON.stringify({ data }),
});
};
-export const processPendingFiles = async () => {
- await Websockets.checkWebsocket();
- return await returnJSON(`/api/data/process-pending`, {
- ...DEFAULT_OPTIONS,
- body: JSON.stringify(),
- });
-};
-
export const addFileToSlate = async (data) => {
+ console.log(data);
await Websockets.checkWebsocket();
- return await returnJSON(`/api/slates/add-url`, {
+ return await returnJSON(`/api/slates/add-file`, {
...DEFAULT_OPTIONS,
body: JSON.stringify({ data }),
});
@@ -241,12 +227,12 @@ export const updateSearch = async (data) => {
});
};
-export const checkCIDStatus = async (data) => {
- return await returnJSON(`/api/data/cid-status`, {
- ...DEFAULT_OPTIONS,
- body: JSON.stringify({ data }),
- });
-};
+// export const checkCIDStatus = async (data) => {
+// return await returnJSON(`/api/data/cid-status`, {
+// ...DEFAULT_OPTIONS,
+// body: JSON.stringify({ data }),
+// });
+// };
export const createSlate = async (data) => {
await Websockets.checkWebsocket();
@@ -264,6 +250,14 @@ export const updateSlate = async (data) => {
});
};
+export const updateSlateLayout = async (data) => {
+ await Websockets.checkWebsocket();
+ return await returnJSON(`/api/slates/update-layout`, {
+ ...DEFAULT_OPTIONS,
+ body: JSON.stringify({ data }),
+ });
+};
+
export const deleteSlate = async (data) => {
await Websockets.checkWebsocket();
return await returnJSON(`/api/slates/delete`, {
@@ -274,7 +268,7 @@ export const deleteSlate = async (data) => {
export const removeFileFromSlate = async (data) => {
await Websockets.checkWebsocket();
- return await returnJSON(`/api/slates/remove`, {
+ return await returnJSON(`/api/slates/remove-file`, {
...DEFAULT_OPTIONS,
body: JSON.stringify({ data }),
});
@@ -295,15 +289,15 @@ export const deleteAPIKey = async (data) => {
});
};
-export const addCIDToData = async (data) => {
+export const saveCopy = async (data) => {
await Websockets.checkWebsocket();
- return await returnJSON(`/api/data/add`, {
+ return await returnJSON(`/api/data/save-copy`, {
...DEFAULT_OPTIONS,
body: JSON.stringify({ data }),
});
};
-export const updateData = async (data) => {
+export const updateFile = async (data) => {
await Websockets.checkWebsocket();
return await returnJSON(`/api/data/update`, {
...DEFAULT_OPTIONS,
@@ -319,9 +313,9 @@ export const toggleFilePrivacy = async (data) => {
});
};
-export const deleteBucketItems = async (data) => {
+export const deleteFiles = async (data) => {
await Websockets.checkWebsocket();
- return await returnJSON(`/api/data/remove`, {
+ return await returnJSON(`/api/data/delete`, {
...DEFAULT_OPTIONS,
body: JSON.stringify({ data }),
});
@@ -349,7 +343,14 @@ export const createSupportMessage = async (data) => {
};
export const getActivity = async (data) => {
- return await returnJSON(`/api/activity/get`, {
+ return await returnJSON(`/api/activity/get-activity`, {
+ ...DEFAULT_OPTIONS,
+ body: JSON.stringify({ data }),
+ });
+};
+
+export const getExplore = async (data) => {
+ return await returnJSON(`/api/activity/get-explore`, {
...DEFAULT_OPTIONS,
body: JSON.stringify({ data }),
});
diff --git a/common/browser-websockets.js b/common/browser-websockets.js
index e86e966a..71216ea6 100644
--- a/common/browser-websockets.js
+++ b/common/browser-websockets.js
@@ -30,8 +30,9 @@ export const init = ({ resource = "", viewer, onUpdate, onNewActiveUser = () =>
return null;
}
- const payload = { type: "SUBSCRIBE_VIEWER", data: viewer };
-
+ const payload = { type: "SUBSCRIBE_VIEWER", data: { id: viewer.id } };
+ console.log(payload);
+ console.log("inside browser websockets init");
client.send(JSON.stringify(payload));
});
diff --git a/common/file-utilities.js b/common/file-utilities.js
index e902897e..50f7d55a 100644
--- a/common/file-utilities.js
+++ b/common/file-utilities.js
@@ -126,6 +126,7 @@ export const upload = async ({ file, context, bucketName, routes, excludeFromLib
});
}
};
+ console.log(formData);
XHR.send(formData);
});
@@ -152,7 +153,7 @@ export const upload = async ({ file, context, bucketName, routes, excludeFromLib
res = await _privateUploadMethod(`${generalRoute}${file.name}`, file);
}
- if (!res || res.error || !res.data) {
+ if (!res?.data || res.error) {
if (context) {
await context.setState({
fileLoading: {
@@ -169,43 +170,16 @@ export const upload = async ({ file, context, bucketName, routes, excludeFromLib
return !res ? { decorator: "NO_RESPONSE_FROM_SERVER", error: true } : res;
}
- if (res.data.data.type.startsWith("image/")) {
- let url = `${Constants.gateways.ipfs}/${res.data.data.cid}`;
+ let item = res.data.data;
+ if (item.data.type.startsWith("image/")) {
+ let url = Strings.getURLfromCID(item.cid);
try {
let blurhash = await encodeImageToBlurhash(url);
- res.data.data.blurhash = blurhash;
+ item.data.blurhash = blurhash;
} catch (e) {
console.log(e);
}
}
- if (!excludeFromLibrary) {
- await Actions.createPendingFiles({ data: res.data });
- }
-
- res.data = res.data.data;
-
- return { file, json: res };
-};
-
-export const uploadToSlate = async ({ responses, slate }) => {
- let added;
- let skipped;
- if (responses && responses.length) {
- const addResponse = await Actions.addFileToSlate({
- slate,
- data: responses.map((res) => {
- return { title: res.file.name, ...res.json.data };
- }),
- });
-
- if (Events.hasError(addResponse)) {
- return;
- }
-
- added = addResponse.added;
- skipped = addResponse.skipped;
- }
- let message = Strings.formatAsUploadMessage(added, skipped, true);
- Events.dispatchMessage({ message, status: !added ? null : "INFO" });
+ return item;
};
diff --git a/common/messages.js b/common/messages.js
index bdb31cc6..0d2e1071 100644
--- a/common/messages.js
+++ b/common/messages.js
@@ -1,354 +1,190 @@
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: "You already have a slate with that name. Please choose 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!",
+ //General
+ SERVER_NOT_AUTHENTICATED:
+ "You are not currently logged in. Please refresh the page and sign in to perform this action",
+ SERVER_USER_NOT_FOUND: "We're having trouble locating your information right now",
+ SERVER_NO_BUCKET_DATA: "We ran into issues while trying to locate your data",
- //Slate Add URL
- ADD_TO_SLATE_USER_NOT_FOUND: "Login to add a Slate URL",
- ADD_TO_SLATE_SLATE_NOT_FOUND: "Sorry, we couldn't find that Slate! Please try another",
- ADD_TO_SLATE_ERROR: "There was an error retriving this Slate",
+ //Activity and explore
+ SERVER_GET_ACTIVITY_NOT_FOUND: "We're having trouble loading activity right now",
+ SERVER_GET_EXPLORE_NOT_FOUND: "We're having trouble loading explore right now",
- //Slate remove file
- SERVER_REMOVE_FROM_SLATE_USER_NOT_FOUND: "Login to manage your slates",
- SERVER_REMOVE_FROM_SLATE_NO_ID_PROVIDED: "Please specify which item you would like to remove",
- SERVER_REMOVE_FROM_SLATE_SLATE_NOT_FOUND: "We're having trouble locating that slate",
- SERVER_REMOVE_FROM_SLATE_ERROR: "We're having trouble removing from this slate right now",
+ //Filecoin and archiving
+ SERVER_SEND_FILECOIN_ACTION_FAILURE: "We're having trouble sending out Filecoin right now",
+ SERVER_ARCHIVE_NO_FILES: "You have no files to archive",
+ SERVER_ARCHIVE_BUCKET_TOO_SMALL:
+ "Your deal size is too small to archive. Deals should be a minimum of 100MB",
+ SERVER_ARCHIVE_BUCKET_COUNT_VERIFICATION_FAILED:
+ "We ran into issues while verifying your ability to make storage deals",
+ SERVER_ARCHIVE_MAX_NUMBER_BUCKETS:
+ "You have reached the maximum number of storage deals for this account",
+ SERVER_ARCHIVE_ENCRYPTION_FAILED:
+ "We encountered issues while encrypting your files for archiving",
+ SERVER_ARCHIVE_BUCKET_CLONING_FAILED:
+ "We ran into issues while replicating your files for archiving",
+ SERVER_ARCHIVE_DEAL_FAILED: "The storage deal wasn't successful",
- //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!",
+ //Bucket remove
+ SERVER_BUCKET_REMOVE_NO_CID:
+ "We ran into issues while removing a file. There was no file specified",
+ SERVER_BUCKET_REMOVE_BUCKET_NOT_FOUND: "We couldn't locate your files to delete",
+ SERVER_BUCKET_REMOVE_NO_BUCKET_ITEMS: "We couldn't locate your files to delete",
+ SERVER_BUCKET_REMOVE_NO_MATCHING_CID: "There were no matching files found",
+ SERVER_BUCKET_REMOVE_FAILED: "We were not able to delete that file",
+
+ //File create
+ CREATE_FILE_NO_FILE_PROVIDED: "We ran into issues while creating a file. No file was provided",
+ CREATE_FILE_DUPLICATE: "The uploaded file(s) were duplicates and were skipped",
+ CREATE_FILE_FAILED: "We ran into issues while creating that file",
+
+ //File delete
+ SERVER_REMOVE_DATA_NO_IDS: "The file to delete was not specified",
+
+ //Save copy
+ SERVER_SAVE_COPY_NO_CIDS: "The file to save was not specified",
+
+ //Toggle file privacy
+ SERVER_TOGGLE_FILE_PRIVACY_NO_FILE:
+ "We ran into issues while editing a file's privacy. No file was specified",
+ SERVER_TOGGLE_FILE_PRIVACY_UPDATE_FAILED:
+ "We're having trouble updating the privacy of that file right now",
+
+ //Update file
+ SERVER_EDIT_DATA_NO_FILE: "We ran into issues while editing a file. No file was provided",
+ SERVER_EDIT_DATA_FAILED: "We're having trouble updating that file right now",
+
+ //Delete api key
+ SERVER_DELETE_API_KEY_NOT_FOUND:
+ "We weren't able to locate that API key. It may have already been deleted",
+ SERVER_DELETE_API_KEY_ERROR: "We weren't able to delete that API key. Please try again later",
+
+ //Create api key
+ SERVER_GENERATE_API_KEY_TOO_MANY_KEYS: "You've reached the limit for number of API keys",
+ SERVER_GENERATE_API_KEY_ERROR:
+ "We're having trouble generating an API key right now, please try again later",
+
+ //Add to slate
+ SERVER_ADD_TO_SLATE_NO_SLATE:
+ "We ran into issues while adding files to that slate. No slate was specified",
+ SERVER_ADD_TO_SLATE_SLATE_NOT_FOUND: "We're having trouble locating that slate right now",
+ SERVER_ADD_TO_SLATE_NO_FILES:
+ "We ran into issues while adding files to that slate. No files selected",
+ SERVER_ADD_TO_SLATE_FAILED: "We're having trouble adding those files to that slate right now",
+
+ //Slate create
+ SERVER_CREATE_SLATE_EXISTING_SLATE_NAME:
+ "You already have a slate with that name. Slate names must be unique",
+ SERVER_CREATE_SLATE_FAILED:
+ "We are having trouble creating that slate right now, please try again later",
+
+ //Slate delete
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",
+ "We're having difficulty locating that slate. It may have already been deleted",
+ SERVER_DELETE_SLATE_FAILED:
+ "We're having trouble deleting that slate right now, 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: "That slate could not be found. It may have been deleted",
- 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",
+ //Get slate
+ SERVER_GET_SERIALIZED_SLATE_SLATE_NOT_FOUND:
+ "We were unable to locate that slate. It may be private or it may not exist",
+ SERVER_GET_SERIALIZED_SLATE_PRIVATE_ACCESS_DENIED:
+ "We were unable to locate that slate. It may be private or it may not exist",
SERVER_GET_SLATE_NOT_FOUND:
- "We're having trouble retrieving information on that slate right now. Please try again later",
+ "We were unable to locate that slate. It may be private or it may not exist",
+ SERVER_GET_SLATE_PRIVATE_ACCESS_DENIED:
+ "We were unable to locate that slate. It may be private or it may not exist",
- //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",
- SERVER_UPDATE_SLATE_NAME_TAKEN: "You already have a slate with that name. Please choose another",
- 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",
+ //Remove from slate
+ SERVER_REMOVE_FROM_SLATE_NO_ID_PROVIDED:
+ "Unable to remove from slate because no slate was specified",
+ SERVER_REMOVE_FROM_SLATE_SLATE_NOT_FOUND: "We are having trouble locating that slate",
+ SERVER_REMOVE_FROM_SLATE_FAILED: "We are having trouble removing from that slate right now",
- //Address Send
- 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",
+ //Update slate layout
+ SERVER_UPDATE_SLATE_LAYOUT_MUST_PROVIDE_DATA: "No layout was provided to update",
+ SERVER_UPDATE_SLATE_LAYOUT_NOT_FOUND: "We are having trouble locating that slate",
+ SERVER_UPDATE_SLATE_LAYOUT:
+ "We are unable to update that slate's layout right now. Please try again later",
- //Address Create
- CREATE_FILECOIN_ADDRESS: "There was an error when creating the Filecoin address.",
+ //Update slate
+ SERVER_UPDATE_SLATE_MUST_PROVIDE_DATA:
+ "We are unable to update that slate because no data was provided",
+ SERVER_UPDATE_SLATE_NOT_FOUND: "We are having trouble locating that slate",
+ SERVER_UPDATE_SLATE_UPDATE_PRIVACY_FAILED:
+ "We are having trouble updating the privacy of that slate",
+ SERVER_UPDATE_SLATE_INVALID_NAME: "Please use a valid slate name",
+ SERVER_UPDATE_SLATE_NAME_TAKEN:
+ "You already have a slate with that name. Slate names must be unique",
+ SERVER_UPDATE_SLATE_FAILED: "We are having trouble updating that slate right now",
- //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",
- CREATE_PENDING_DATA: "We ran into issues while uploading your data, please try again later",
- CREATE_PENDING_ERROR: "We ran into issues while uploading your data, please try again later",
- PROCESS_PENDING_ERROR:
- "We ran into an error while updating your uploaded data. Please try again later",
- PROCESS_PENDING_USER_NOT_FOUND: "Please log in to upload files",
+ //Create user
+ SERVER_CREATE_USER_NOT_ALLOWED: "You can only create users while on slate.host",
+ SERVER_CREATE_USER_ACCEPT_TERMS: "You must accept the terms of service to create an account",
+ SERVER_CREATE_USER_USERNAME_TAKEN: "There is already an account with that username",
+ SERVER_CREATE_USER_INVALID_USERNAME: "Please choose a valid username",
+ SERVER_CREATE_USER_INVALID_PASSWORD: "Please chooose a valid password",
+ SERVER_CREATE_USER_BUCKET_INIT_FAILURE:
+ "We're having trouble setting up your storage, please try again later",
+ SERVER_CREATE_USER_FAILED:
+ "We're having trouble creating your account right now. Please try again later",
- //Data CID Status
- NO_CIDS_TO_CHECK: "There are no CIDs to check",
+ //Get user
+ SERVER_GET_USER_NO_USER_PROVIDED:
+ "We were not able to fetch that user because no user was specified",
+ SERVER_GET_USER_USER_NOT_FOUND: "We were not able to locate that user",
- //Data Get
- SERVER_GET_BUCKET_DATA: "We ran into an issue fetching that data. Please try again later",
+ //Get user social
+ SERVER_USER_SOCIAL_NO_USER_ID:
+ "We were not able to fetch that user's subscriptions and following because no user was specified",
+ SERVER_USER_SOCIAL_SUBSCRIPTIONS_NOT_FOUND:
+ "We were not able to locate that user's subscriptions",
+ SERVER_USER_SOCIAL_FOLLOWING_NOT_FOUND: "We were not able to locate that user's following",
+ SERVER_USER_SOCIAL_FOLLOWERS_NOT_FOUND: "We were not able to locate that user's followers",
- //Data Remove
- SERVER_REMOVE_DATA_NO_CID:
- "Slate is having trouble deleting some files right now. We're working on fixing this soon!",
- 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",
+ //Status update
+ SERVER_STATUS_UPDATE_FAILED: "We're having trouble making that change right now",
+ SERVER_STATUS_UPDATE_MUST_PROVIDE_UPDATE: "No update was provided",
- //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!",
+ //Update user
+ SERVER_USER_UPDATE_INVALID_USERNAME: "Please choose a valid username",
+ SERVER_USER_UPDATE_USERNAME_IS_TAKEN: "There is already an account with that username",
+ SERVER_USER_UPDATE_DEFAULT_ARCHIVE_CONFIG:
+ "We're having trouble updating your settings right now",
+ SERVER_USER_UPDATE_INVALID_PASSWORD: "Please chooose a valid password",
- //Archive Deal
- SERVER_REMOVE_DATA_NOT_ALLOWED: "Please login first to archive a deal!",
- SERVER_BUCKET_ARCHIVE_DEAL_USER_NOT_FOUND: "Please login first to archive a deal!",
- SERVER_BUCKET_INIT_FAILURE: "Something went wrong while locating your storage bucket",
- STORAGE_DEAL_MAKING_NO_BUCKET: "We could not locate your storage bucket",
- STORAGE_DEAL_MAKING_NO_FILES: "No file selected. Please select a file to archive then try again",
- STORAGE_BUCKET_TOO_SMALL: "Deal size too small. Deals must be 100MB or larger",
- BUCKET_SPAWN_VERIFICATION_FAILED_FOR_BUCKET_COUNT:
- "We ran into an issue while verifying how much storage space you have",
- TOO_MANY_BUCKETS: "You've reached the maximum number of storage buckets for an account",
- FORCED_ENCRYPTION_FAILED_FOR_DATA: "We ran into an issue while encrypting your data",
- BUCKET_CLONING_FAILED: "We ran into an issue while creating a storage bucket for you",
- STORAGE_DEAL_MAKING_NOT_SANITARY: "We ran into an issue while creating that storage deal",
-
- //CID Status
- SERVER_NO_CIDS_TO_CHECK: "No CIDs were entered, please check your input",
-
- //Users Create
- SIGN_UP_RATE_LIMITED: "Too many sign up attempts. Please try again in 10 minutes",
- SERVER_EXISTING_USER_ALREADY: "That username is taken. Please try another one",
- EXISTING_USER_ALREADY: "That username is 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",
- 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're having trouble connecting right now",
- 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!",
- 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",
- 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",
- SERVER_STATUS_UPDATE: "Please log in first to access this page",
- SERVER_STATUS_UPDATE_USER_NOT_FOUND: "We're having trouble locating your information right now",
- SERVER_STATUS_UPDATE_MUST_PROVIDE_UPDATE:
- "We're having trouble updating your information right now",
- SERVER_USERNAME_IS_TAKEN: "That username is taken",
-
- //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",
- SERVER_USER_SUBSCRIPTIONS_NOT_FOUND:
- "We weren't able to fetch information on that user. Please try again later",
- SERVER_USER_SUBSCRIBERS_NOT_FOUND:
- "We weren't able to fetch information on that user. Please try again later",
+ //Zip files
+ GET_ZIP_FILES_PATHS_BUCKET_CHECK_FAILED: "We're having trouble locating those files right now",
//Hydrate
- 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",
+ "We're having trouble fetching your information right now, please refresh the page",
- //Sign-in
- SIGN_IN_RATE_LIMITED: "Too many sign in attempts. Please try again in 10 minutes",
- SIGN_IN: "Your username/password can't be blank",
- SERVER_SIGN_IN: "Your username/password can't be blank",
- SIGN_IN_USER_NOT_FOUND: "We're having trouble logging you in right now, please try again later",
- SERVER_SIGN_IN_USER_NOT_FOUND: "That username and password do not match", //no one with that username
- SERVER_SIGN_IN_ERROR: "We're having trouble connecting right now. Please try again later",
- SERVER_SIGN_IN_AUTH: "That username and password do not match", //incorrect password
+ //Get deals
+ SERVER_FILECOIN_NETWORK_DEALS_ERROR:
+ "We're having trouble fetching your deal information right now",
+ SERVER_FILECOIN_NETWORK_ERROR: "We're having trouble fetching your storage information right now",
- //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",
- SERVER_GET_ACTIVITY_NOT_FOUND: "We're having trouble fetching your feed right now",
- SERVER_GET_ACTIVITY_USER_NOT_FOUND: "Please login to view your feed",
+ //Sign in
+ SERVER_SIGN_IN_NOT_ALLOWED: "You can only sign in to an account while on slate.host",
+ SERVER_SIGN_IN_NO_USERNAME: "Please provide a username to sign in",
+ SERVER_SIGN_IN_NO_PASSWORD: "Please provide a password to sign in",
+ SERVER_SIGN_IN_USER_NOT_FOUND: "We were unable to locate that account with those credentials",
+ SERVER_SIGN_IN_WRONG_PASSWORD: "We were unable to locate that account with those credentials",
- //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",
+ //Subscribe
+ SERVER_SUBSCRIBE_MUST_PROVIDE_SLATE_OR_USER: "No slate or user to follow specified",
+ SERVER_SUBSCRIBE_CAN_NOT_SUBSCRIBE_TO_YOURSELF: "You cannot follow yourself",
+ SERVER_SUBSCRIBE_TARGET_USER_NOT_FOUND: "We are unable to locate that user",
+ SERVER_SUBSCRIBE_TARGET_SLATE_NOT_FOUND: "We are unable to locate that slate",
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: "This slate or profile does not exist",
- SERVER_DEEPLINK_ERROR: "This slate or profile does not exist",
- SERVER_SEARCH_NO_QUERY: "No query was entered. Please enter a query and try again",
-
- // Storage Deals
- SERVER_BUCKET_INIT_FAILURE: "Something went wrong with our infrastructure. Check in later.",
- STORAGE_DEAL_MAKING_NO_BUCKET: "Something went wrong with our infrastructure. Check in later.",
- STORAGE_DEAL_MAKING_NO_FILES: "You must provide files before you make a deal.",
+ "We are having trouble editing that subscription right now",
+ SERVER_UNSUBSCRIBE_FAILED: "We were unable to unsubscribe, please try again later",
+ SERVER_SUBSCRIBE_FAILED: "We were unable to subscribe, please try again later",
//Support
- SERVER_SUPPORT: "You must be logged in to send a support message. Please try logging in again",
- SERVER_SUPPORT_USER_NOT_FOUND: "We're having difficulty locating your information right now",
- SERVER_SUPPORT_NO_DATA_PROVIDED: "We're having trouble transmitting your message right now",
- SERVER_SUPPORT_MUST_PROVIDE_EMAIL: "Please provide an email where we can contact you",
- SERVER_SUPPORT_MUST_PROVIDE_MESSAGE: "Please provide a message to send",
- SERVER_SUPPORT: "We're having trouble sending your support message to the team right now",
-
- // Unity game download
+ SERVER_SUPPORT_NO_DATA_PROVIDED: "Please include details for us to send a support message",
+ SERVER_SUPPORT_MUST_PROVIDE_EMAIL: "Please include an email where we can reach you",
+ SERVER_SUPPORT_MUST_PROVIDE_MESSAGE: "Please include a support message",
+ SERVER_SUPPORT_NO_USERNAME_PROVIDED: "Please include a username",
UNITY_ZIP_DOWNLOAD_FAILED:
- "We're having trouble downloading you Unity game file. Please try again",
-
- // Delete tag
- SERVER_DELETE_TAG_USER_NOT_FOUND:
- "We're having trouble retrieving that slate's owner right now. Please try again",
- SERVER_DELETE_TAG_SLATES_NOT_FOUND: "We weren't able to locate the slates for that user",
+ "We're having trouble downloading your Unity game file. Please try again later",
};
diff --git a/common/navigation-data.js b/common/navigation-data.js
index af44e5e9..40a09613 100644
--- a/common/navigation-data.js
+++ b/common/navigation-data.js
@@ -88,23 +88,6 @@ export const navigation = [
pageTitle: "Slate",
ignore: true,
},
- /*
- {
- id: "V1_NAVIGATION_LOCAL",
- decorator: "LOCAL_DATA",
- name: "Local",
- pageTitle: "Your local data",
- children: [],
- ignore: false,
- },
- {
- id: "V1_NAVIGATION_NETWORK",
- decorator: "NETWORK",
- name: "Network",
- pageTitle: "The Filecoin Network",
- children: null,
- },
- */
{
id: "NAV_FILECOIN",
decorator: "FILECOIN",
diff --git a/common/schema.js b/common/schema.js
new file mode 100644
index 00000000..526d81b5
--- /dev/null
+++ b/common/schema.js
@@ -0,0 +1,133 @@
+//NOTE(martina): update this file anytime you add a new item to the user, file, or slate data blobs
+
+export const userSchema = {
+ id: true,
+ username: true,
+ data: {
+ photo: true,
+ body: true,
+ name: true,
+ tokens: true,
+ settings: true,
+ onboarding: true,
+ status: true,
+ },
+};
+
+export const coverImageSchema = {
+ id: true,
+ cid: true,
+ createdAt: true,
+ data: {
+ file: true,
+ name: true,
+ size: true,
+ type: true,
+ blurhash: true,
+ },
+};
+
+//add: downloads, tags
+export const fileSchema = {
+ id: true,
+ ownerId: true,
+ cid: true,
+ isPublic: true,
+ createdAt: true,
+ filename: true,
+ data: {
+ name: true,
+ size: true,
+ type: true,
+ blurhash: true,
+ coverImage: coverImageSchema,
+ body: true,
+ source: true,
+ author: true,
+ unity: {
+ config: true,
+ loader: true,
+ },
+ downloads: true,
+ tags: true,
+ link: true,
+ },
+};
+
+//add: tags
+export const slateSchema = {
+ id: true,
+ slatename: true,
+ ownerId: true,
+ isPublic: true,
+ data: {
+ name: true,
+ body: true,
+ layouts: true,
+ preview: true,
+ tags: true,
+ },
+};
+
+/*
+Users
+[
+ 'body',
+ 'photo',
+ 'tokens',
+ 'library',
+ 'settings_deals_auto_approve',
+ 'allow_automatic_data_storage',
+ 'allow_encrypted_data_storage',
+ 'allow_filecoin_directory_listing',
+ 'name',
+ 'status',
+ 'onboarding',
+ 'description'
+]
+[
+ 'id', 'cid',
+ 'date', 'file',
+ 'icon', 'ipfs',
+ 'name', 'size',
+ 'type', 'decorator',
+ 'blurhash', 'unityGameConfig',
+ 'unityGameLoader', 'url',
+ 'public', 'previewImage',
+ 'coverImage', 'settings',
+ 'job', 'storage',
+ 'networks', 'retrieval'
+]
+[
+ 'id', 'cid',
+ 'url', 'date',
+ 'file', 'name',
+ 'size', 'type',
+ 'blurhash', 'decorator'
+]
+
+Slates
+[
+ 'body', 'name',
+ 'public', 'objects',
+ 'ownerId', 'layouts',
+ 'preview'
+]
+[
+ 'id', 'url',
+ 'name', 'type',
+ 'title', 'ownerId',
+ 'cid', 'body',
+ 'author', 'source',
+ 'size', 'deeplink',
+ 'blurhash', 'unityGameConfig',
+ 'unityGameLoader', 'coverImage'
+]
+[
+ 'id', 'cid',
+ 'url', 'date',
+ 'file', 'name',
+ 'size', 'type',
+ 'blurhash', 'decorator'
+]
+*/
diff --git a/common/strings.js b/common/strings.js
index 69ef01ff..70627af4 100644
--- a/common/strings.js
+++ b/common/strings.js
@@ -40,7 +40,7 @@ export const zeroPad = (num, places) => {
return Array(+(zero > 0 && zero)).join("0") + num;
};
-export const getCIDGatewayURL = (cid) => {
+export const getURLfromCID = (cid) => {
return `${Constants.gateways.ipfs}/${cid}`;
};
@@ -55,15 +55,15 @@ export const toDateSinceEpoch = (epoch) => {
return toDate(new Date().getTime() - epoch);
};
-export const getCIDGatewayURLWithExtension = (cid, name) => {
- const url = getCIDGatewayURL(cid);
- const extension = getFileExtension(name);
- if (!isEmpty(extension)) {
- return `${url}.${getFileExtension(name)}`;
- }
+// export const getURLfromCIDWithExtension = (cid, name) => {
+// const url = getURLfromCID(cid);
+// const extension = getFileExtension(name);
+// if (!isEmpty(extension)) {
+// return `${url}.${getFileExtension(name)}`;
+// }
- return url;
-};
+// return url;
+// };
export const getURLFromPath = (path) => {
return `${window.location.protocol}//${window.location.hostname}${
@@ -210,6 +210,7 @@ export const urlToCid = (url) => {
return url
.replace(`${Constants.gateways.ipfs}/`, "")
.replace("https://", "")
+ .replace("undefined", "")
.replace(".ipfs.slate.textile.io", "")
.replace("hub.textile.io/ipfs/", "");
};
diff --git a/common/user-behaviors.js b/common/user-behaviors.js
index 4944aadb..b989c504 100644
--- a/common/user-behaviors.js
+++ b/common/user-behaviors.js
@@ -146,7 +146,6 @@ export const formatDroppedFiles = async ({ dataTransfer }) => {
file = new File(blob, `data-${uuid()}`);
file.name = `data-${uuid()}`;
- console.log(file);
} catch (e) {
Events.dispatchMessage({
message: "File type not supported. Please try a different file",
@@ -209,30 +208,26 @@ export const uploadImage = async (file, resources, excludeFromLibrary) => {
return;
}
- const response = await FileUtilities.upload({ file, routes: resources, excludeFromLibrary });
+ const response = await FileUtilities.upload({ file, routes: resources });
if (Events.hasError(response)) {
return false;
}
- delete response.json.data.icon;
- delete response.json.data.ipfs;
-
- return response.json;
+ return response;
};
-export const deleteFiles = async (fileCids, fileIds = [], noAlert) => {
- let cids = Array.isArray(fileCids) ? fileCids : [fileCids];
+export const deleteFiles = async (fileIds = [], noAlert) => {
let ids = Array.isArray(fileIds) ? fileIds : [fileIds];
- const response = await Actions.deleteBucketItems({ cids, ids });
+ const response = await Actions.deleteFiles({ ids });
if (!noAlert) {
if (Events.hasError(response)) {
return false;
}
- // Events.dispatchMessage({ message: "Files successfully deleted!", status: "INFO" });
+ Events.dispatchMessage({ message: "Files successfully deleted!", status: "INFO" });
return response;
}
@@ -251,19 +246,8 @@ export const removeFromSlate = async ({ slate, ids }) => {
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,
- });
+export const addToSlate = async ({ slate, files }) => {
+ const addResponse = await Actions.addFileToSlate({ slate, files });
if (Events.hasError(addResponse)) {
return false;
@@ -275,14 +259,8 @@ export const addToSlate = async ({ slate, files, fromSlate }) => {
return true;
};
-export const addToDataFromSlate = async ({ files }) => {
- let items = files.map((file) => {
- return {
- ownerId: file.ownerId,
- cid: file.cid,
- };
- });
- let response = await Actions.addCIDToData({ items });
+export const saveCopy = async ({ files }) => {
+ let response = await Actions.saveCopy({ files });
if (Events.hasError(response)) {
return false;
}
@@ -292,22 +270,16 @@ export const addToDataFromSlate = async ({ files }) => {
};
export const download = (file) => {
- const filename = file.file || file.name || file.title;
- let uri;
- if (file.url) {
- uri = file.url;
- } else {
- uri = Strings.getCIDGatewayURL(file.cid);
- }
- Window.saveAs(uri, filename);
+ let uri = Strings.getURLfromCID(file.cid);
+ Window.saveAs(uri, file.filename);
};
export const downloadZip = async (file) => {
try {
const { data } = await Actions.getZipFilePaths(file);
const filesPaths = data.filesPaths.map((item) => item.replace(`/${file.id}/`, ""));
- const baseUrl = file.url;
- const zipFileName = file.file;
+ const baseUrl = Strings.getURLfromCID(file.cid);
+ const zipFileName = file.filename;
let zip = new JSZip();
@@ -363,8 +335,8 @@ export const compressAndDownloadFiles = async ({ files, name = "slate.zip", reso
if (file.type === "application/unity") {
const { data } = await Actions.getZipFilePaths(file);
const unityFiles = data.filesPaths.map((item) => ({
- url: item.replace(`/${file.id}/`, `${file.url || Strings.getCIDGatewayURL(file.cid)}/`),
- name: item.replace(`/${file.id}/`, `/${file.name}/`),
+ url: item.replace(`/${file.id}/`, `${Strings.getURLfromCID(file.cid)}/`),
+ name: item.replace(`/${file.id}/`, `/${file.filename}/`),
}));
downloadFiles = downloadFiles.concat(unityFiles);
@@ -372,8 +344,8 @@ export const compressAndDownloadFiles = async ({ files, name = "slate.zip", reso
}
downloadFiles.push({
- name: file.file || file.name,
- url: file.url || Strings.getCIDGatewayURL(file.cid),
+ name: file.filename,
+ url: Strings.getURLfromCID(file.cid),
});
}
@@ -395,7 +367,7 @@ export const compressAndDownloadFiles = async ({ files, name = "slate.zip", reso
// export const createSlate = async (data) => {
// let response = await Actions.createSlate({
// name: data.name,
-// public: data.public,
+// isPublic: data.isPublic,
// body: data.body,
// });
// return response;
diff --git a/common/utilities.js b/common/utilities.js
index 96da400a..b33d0ac5 100644
--- a/common/utilities.js
+++ b/common/utilities.js
@@ -5,16 +5,16 @@
export const getPublicAndPrivateFiles = ({ viewer }) => {
let publicFileIds = [];
for (let slate of viewer.slates) {
- if (slate.data.public) {
- publicFileIds.push(...slate.data.objects.map((obj) => obj.id));
+ if (slate.isPublic) {
+ publicFileIds.push(...slate.objects.map((obj) => obj.id));
}
}
let publicFiles = [];
let privateFiles = [];
- let library = viewer.library[0]?.children || [];
+ let library = viewer.library || [];
for (let file of library) {
- if (file.public || publicFileIds.includes(file.id)) {
+ if (file.isPublic || publicFileIds.includes(file.id)) {
publicFiles.push(file);
} else {
privateFiles.push(file);
diff --git a/common/validations.js b/common/validations.js
index 3103a7b8..4dfe72c5 100644
--- a/common/validations.js
+++ b/common/validations.js
@@ -149,6 +149,36 @@ export const isPreviewableImage = (type = "") => {
return type.startsWith("image/");
};
+export const isImageType = (type) => {
+ if (type.startsWith("image/")) {
+ return true;
+ }
+};
+
+export const isAudioType = (type) => {
+ if (type.startsWith("audio/")) {
+ return true;
+ }
+};
+
+export const isVideoType = (type) => {
+ if (type.startsWith("video/")) {
+ return true;
+ }
+};
+
+export const isPdfType = (type) => {
+ if (type.startsWith("application/pdf")) {
+ return true;
+ }
+};
+
+export const isEpubType = (type) => {
+ if (type.startsWith("application/epub")) {
+ return true;
+ }
+};
+
export const isUnityFile = async (file) => {
try {
const zip = new JSZip();
diff --git a/common/window.js b/common/window.js
index 2b48682b..50d72899 100644
--- a/common/window.js
+++ b/common/window.js
@@ -94,7 +94,7 @@ export const isIOS = (userAgent) => {
export const isMobileBrowser = (userAgent) => {
const navigatorAgent = getNavigatorAgent(userAgent);
- const mobile =
+ const isMobile =
/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ipad|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(
navigatorAgent
) ||
@@ -102,7 +102,7 @@ export const isMobileBrowser = (userAgent) => {
navigatorAgent.substr(0, 4)
);
- return !!mobile;
+ return !!isMobile;
};
//NOTE(toast): this can be switched to regex pattern matching if
@@ -116,12 +116,13 @@ export const isMac = (userAgent) => {
export const debounce = (func, wait) => {
let timeout;
- return function passedInFunction(...args) {
- const later = () => {
- func(...args);
- };
+ return function passedInFunction(params) {
+ if (params?.cancel) {
+ clearTimeout(timeout);
+ return;
+ }
clearTimeout(timeout);
- timeout = setTimeout(later, wait);
+ timeout = setTimeout(func, wait);
};
};
diff --git a/components/core/Alert.js b/components/core/Alert.js
index a966b5cc..c895408a 100644
--- a/components/core/Alert.js
+++ b/components/core/Alert.js
@@ -115,7 +115,12 @@ export class Alert extends React.Component {
_handleDismissPrivacyAlert = (e) => {
Actions.updateStatus({ status: { hidePrivacyAlert: true } });
- this.props.onUpdateViewer({ status: { ...this.props.viewer.status, hidePrivacyAlert: true } });
+ this.props.onUpdateViewer({
+ data: {
+ ...this.props.viewer.data,
+ status: { ...this.props.viewer.data.status, hidePrivacyAlert: true },
+ },
+ });
};
render() {
diff --git a/components/core/Application.js b/components/core/Application.js
index 462f23b7..7d0a763e 100644
--- a/components/core/Application.js
+++ b/components/core/Application.js
@@ -20,7 +20,6 @@ import SceneFile from "~/scenes/SceneFile";
import SceneFilesFolder from "~/scenes/SceneFilesFolder";
import SceneSettings from "~/scenes/SceneSettings";
import SceneSlates from "~/scenes/SceneSlates";
-import SceneLocalData from "~/scenes/SceneLocalData";
import SceneSettingsDeveloper from "~/scenes/SceneSettingsDeveloper";
import SceneSignIn from "~/scenes/SceneSignIn";
import SceneSlate from "~/scenes/SceneSlate";
@@ -87,7 +86,6 @@ const SCENES = {
SETTINGS: ,
SLATES: ,
SLATES_FOLLOWING: ,
- LOCAL_DATA: ,
DIRECTORY: ,
DIRECTORY_FOLLOWERS: ,
FILECOIN: ,
@@ -105,7 +103,7 @@ export default class ApplicationPage extends React.Component {
data: null,
sidebar: null,
online: null,
- mobile: this.props.mobile,
+ isMobile: this.props.isMobile,
loaded: false,
activeUsers: null,
};
@@ -172,10 +170,7 @@ export default class ApplicationPage extends React.Component {
const current = NavigationData.getCurrent(page);
let slate = null;
- if (
- current.target.id === "NAV_SLATE" &&
- this.state.data?.data?.ownerId === this.state.viewer?.id
- ) {
+ if (current.target.id === "NAV_SLATE" && this.state.data?.ownerId === this.state.viewer?.id) {
slate = this.state.data;
}
@@ -186,7 +181,7 @@ export default class ApplicationPage extends React.Component {
});
};
- _handleUpdateViewer = (newViewerState) => {
+ _handleUpdateViewer = (newViewerState, callback) => {
// let setAsyncState = (newState) =>
// new Promise((resolve) =>
// this.setState(
@@ -207,7 +202,7 @@ export default class ApplicationPage extends React.Component {
if (!page || !page.id) {
page = { id: "NAV_DATA", scrollTop: 0, data: null };
}
- if (page.id === "NAV_SLATE" && this.state.data?.data?.ownerId === this.state.viewer.id) {
+ if (page.id === "NAV_SLATE" && this.state.data?.ownerId === this.state.viewer.id) {
let data = this.state.data;
for (let slate of newViewerState.slates) {
if (slate.id === data.id) {
@@ -215,21 +210,39 @@ export default class ApplicationPage extends React.Component {
break;
}
}
- this.setState({
- viewer: { ...this.state.viewer, ...newViewerState, type: "VIEWER" },
- data,
- });
+ this.setState(
+ {
+ viewer: { ...this.state.viewer, ...newViewerState },
+ data,
+ },
+ () => {
+ if (callback) {
+ callback();
+ }
+ }
+ );
return;
}
}
- this.setState({
- viewer: { ...this.state.viewer, ...newViewerState, type: "VIEWER" },
- });
+ this.setState(
+ {
+ viewer: { ...this.state.viewer, ...newViewerState },
+ },
+ () => {
+ if (callback) {
+ callback();
+ }
+ }
+ );
};
- _handleUpdateData = ({ data }) => {
+ _handleUpdateData = (data, callback) => {
//TODO(martina): maybe add a default window.history.replacestate where it pushes the new data to browser?
- this.setState({ data });
+ this.setState({ data }, () => {
+ if (callback) {
+ callback();
+ }
+ });
};
_handleSetupWebsocket = async () => {
@@ -243,7 +256,7 @@ export default class ApplicationPage extends React.Component {
console.log("WEBSOCKET: NOT AUTHENTICATED");
return;
}
-
+ console.log("inside handle setup websocket in application.js");
wsclient = Websockets.init({
resource: this.props.resources.pubsub,
viewer: this.state.viewer,
@@ -269,12 +282,12 @@ export default class ApplicationPage extends React.Component {
// (1) is Window.isMobileBrowser checks, that one holds.
// (2) then if the viewport is smaller than the width
- let mobile = width > Constants.sizes.mobile ? this.props.mobile : true;
+ let isMobile = width > Constants.sizes.mobile ? this.props.isMobile : true;
// only change if necessary.
- if (this.state.mobile !== mobile) {
- console.log("changing to mobile?", mobile);
- this.setState({ mobile });
+ if (this.state.isMobile !== isMobile) {
+ console.log("changing to mobile?", isMobile);
+ this.setState({ isMobile });
}
};
@@ -308,10 +321,7 @@ export default class ApplicationPage extends React.Component {
const current = NavigationData.getCurrent(page);
let slate = null;
- if (
- current.target.id === "NAV_SLATE" &&
- this.state.data?.data?.ownerId === this.state.viewer?.id
- ) {
+ if (current.target.id === "NAV_SLATE" && this.state.data?.ownerId === this.state.viewer?.id) {
slate = this.state.data;
}
@@ -331,9 +341,10 @@ export default class ApplicationPage extends React.Component {
});
};
- _handleUpload = async ({ files, slate, keys, numFailed }) => {
+ _handleUpload = async ({ files, slate, keys, numFailed = 0 }) => {
if (!files || !files.length) {
- return null;
+ this._handleRegisterLoadingFinished({ keys });
+ return;
}
const resolvedFiles = [];
@@ -346,7 +357,7 @@ export default class ApplicationPage extends React.Component {
await Window.delay(3000);
// NOTE(jim): Sends XHR request.
- let response = null;
+ let response;
try {
response = await FileUtilities.upload({
file: files[i],
@@ -364,34 +375,53 @@ export default class ApplicationPage extends React.Component {
}
if (!resolvedFiles.length) {
- this.setState({ fileLoading: {} });
- return null;
- }
-
- let responses = await Promise.allSettled(resolvedFiles);
- let succeeded = responses
- .filter((res) => {
- return res.status === "fulfilled" && res.value && !res.value.error;
- })
- .map((res) => res.value);
-
- if (slate && slate.id) {
- await FileUtilities.uploadToSlate({ responses: succeeded, slate });
- }
-
- let processResponse = await Actions.processPendingFiles();
- if (Events.hasError(processResponse)) {
+ this._handleRegisterLoadingFinished({ keys });
return;
}
+ //NOTE(martina): this commented out portion is only for if parallel uploading
+ // let responses = await Promise.allSettled(resolvedFiles);
+ // let succeeded = responses
+ // .filter((res) => {
+ // return res.status === "fulfilled" && res.value && !res.value.error;
+ // })
+ // .map((res) => res.value);
- if (!slate) {
- const { added, skipped } = processResponse.data;
- let message = Strings.formatAsUploadMessage(added, skipped + numFailed);
- Events.dispatchMessage({ message, status: !added ? null : "INFO" });
+ let createResponse = await Actions.createFile({ files: resolvedFiles });
+
+ if (Events.hasError(createResponse)) {
+ this._handleRegisterLoadingFinished({ keys });
+ return;
+ }
+ console.log("no error in actions.createFile");
+
+ console.log(createResponse);
+ let uploadedFiles = createResponse.data;
+
+ let added, skipped;
+ if (slate && slate.id) {
+ console.log(slate);
+ console.log(uploadedFiles);
+ const addResponse = await Actions.addFileToSlate({
+ slate,
+ files: uploadedFiles,
+ });
+
+ if (Events.hasError(addResponse)) {
+ this._handleRegisterLoadingFinished({ keys });
+ return;
+ }
+
+ added = addResponse.added;
+ skipped = addResponse.skipped;
+ } else {
+ added = resolvedFiles.length;
+ skipped = files.length - resolvedFiles.length;
}
+ let message = Strings.formatAsUploadMessage(added, skipped + numFailed);
+ Events.dispatchMessage({ message, status: !added ? null : "INFO" });
+
this._handleRegisterLoadingFinished({ keys });
- return null;
};
_handleRegisterFileLoading = ({ fileLoading }) => {
@@ -473,10 +503,11 @@ export default class ApplicationPage extends React.Component {
let unseenAnnouncements = [];
for (let feature of announcements) {
- if (!Object.keys(viewer.onboarding).includes(feature)) {
+ if (!viewer.data.onboarding || !Object.keys(viewer.data.onboarding).includes(feature)) {
unseenAnnouncements.push(feature);
}
}
+ console.log(unseenAnnouncements);
if (newAccount || unseenAnnouncements.length) {
Events.dispatchCustomEvent({
@@ -622,6 +653,7 @@ export default class ApplicationPage extends React.Component {
};
render() {
+ console.log(this.state.viewer);
// NOTE(jim): Not authenticated.
if (!this.state.viewer) {
return (
@@ -661,8 +693,8 @@ export default class ApplicationPage extends React.Component {
navigation={NavigationData.navigation}
activeIds={current.activeIds}
onAction={this._handleAction}
- mobile={this.state.mobile}
- mac={this.props.mac}
+ isMobile={this.state.isMobile}
+ isMac={this.props.isMac}
/>
);
@@ -679,8 +711,8 @@ export default class ApplicationPage extends React.Component {
onUpdateData: this._handleUpdateData,
onUpdateViewer: this._handleUpdateViewer,
sceneId: current.target.id,
- mobile: this.state.mobile,
- mac: this.props.mac,
+ isMobile: this.state.isMobile,
+ isMac: this.props.isMac,
resources: this.props.resources,
activeUsers: this.state.activeUsers,
userBucketCID: this.state.userBucketCID,
@@ -737,8 +769,8 @@ export default class ApplicationPage extends React.Component {
onDismissSidebar={this._handleDismissSidebar}
fileLoading={this.state.fileLoading}
filecoin={current.target.filecoin}
- mobile={this.state.mobile}
- mac={this.props.mac}
+ isMobile={this.state.isMobile}
+ isMac={this.props.isMac}
viewer={this.state.viewer}
onUpdateViewer={this._handleUpdateViewer}
>
@@ -748,7 +780,7 @@ export default class ApplicationPage extends React.Component {
{!this.state.loaded ? (
diff --git a/components/core/ApplicationHeader.js b/components/core/ApplicationHeader.js
index d33c2a64..c9dbc44e 100644
--- a/components/core/ApplicationHeader.js
+++ b/components/core/ApplicationHeader.js
@@ -128,7 +128,7 @@ const STYLES_STATIC = css`
export default class ApplicationHeader extends React.Component {
keysPressed = {};
- searchModKey = this.props.mac ? (
+ searchModKey = this.props.isMac ? (
) : (
Ctrl
diff --git a/components/core/ApplicationLayout.js b/components/core/ApplicationLayout.js
index 9cc4af4a..bc6b69fc 100644
--- a/components/core/ApplicationLayout.js
+++ b/components/core/ApplicationLayout.js
@@ -113,13 +113,13 @@ export default class ApplicationLayout extends React.Component {
componentDidMount = () => {
this.prevScrollPos = window.pageYOffset;
- if (this.props.mobile) {
+ if (this.props.isMobile) {
window.addEventListener("scroll", this._handleScroll);
}
};
componentWillUnmount = () => {
- if (this.props.mobile) {
+ if (this.props.isMobile) {
window.removeEventListener("scroll", this._handleScroll);
}
};
@@ -166,20 +166,23 @@ export default class ApplicationLayout extends React.Component {
{/* */}
-
+
{this.props.header}
{
+ if (props.type) {
+ if (Validations.isVideoType(type)) {
+ return DEFAULT_VIDEO;
+ } else if (Validations.isAudioType(type)) {
+ return DEFAULT_AUDIO;
+ } else if (Validations.isPdfType(type)) {
+ return DEFAULT_DOCUMENT;
+ } else if (Validations.isEpubType(type)) {
+ return DEFAULT_BOOK;
+ }
+ }
+ return DEFAULT_DATA;
+};
+
+class CarouselSidebar extends React.Component {
+ state = {
+ name: this.props.data.data.name || this.props.data.filename,
+ body: this.props.data.data.body,
+ source: this.props.data.data.source,
+ author: this.props.data.data.author,
+ tags: this.props.data.data.tags || [],
+ suggestions: this.props.viewer?.tags || [],
+ selected: {},
+ isPublic: false,
+ inPublicSlates: 0,
+ isUploading: false,
+ isDownloading: false,
+ showSavedMessage: false,
+ showConnectedSection: false,
+ showFileSection: true,
+ };
+
+ componentDidMount = () => {
+ const editingAllowed = !this.props.external && this.props.isOwner && !this.props.isRepost;
+ if (editingAllowed) {
+ this.debounceInstance = Window.debounce(() => this._handleSave(), 3000);
+ this.calculateSelected();
+ }
+ };
+
+ componentDidUpdate = (prevProps, prevState) => {
+ if (!isEqual(prevState.tags, this.state.tags)) {
+ this.updateSuggestions();
+ }
+ };
+
+ updateSuggestions = () => {
+ let newSuggestions = new Set([...this.state.suggestions, ...this.state.tags]);
+ this.setState({ suggestions: Array.from(newSuggestions) });
+ };
+
+ calculateSelected = () => {
+ console.log("calculate selected");
+ let inPublicSlates = 0;
+ let selected = {};
+ const id = this.props.data.id;
+ for (let slate of this.props.viewer.slates) {
+ if (slate.objects.some((obj) => obj.id === id)) {
+ if (slate.isPublic) {
+ inPublicSlates += 1;
+ }
+ selected[slate.id] = true;
+ }
+ }
+ this.setState({ selected, inPublicSlates, isPublic: this.props.data.isPublic });
+ };
+
+ _handleToggleAccordion = (tab) => {
+ this.setState({ [tab]: !this.state[tab] });
+ };
+
+ _handleDarkMode = async (e) => {
+ Events.dispatchCustomEvent({
+ name: "set-slate-theme",
+ detail: { darkmode: e.target.value },
+ });
+ };
+
+ _handleChange = (e) => {
+ if (this.props.external || !this.props.isOwner) return;
+ this.debounceInstance();
+ this.setState(
+ {
+ [e.target.name]: e.target.value,
+ showSavedMessage: false,
+ },
+ () => {
+ if (e.target.name === "Tags") {
+ this.updateSuggestions();
+ }
+ }
+ );
+ };
+
+ _handleCapitalization(str) {
+ return str.charAt(0).toUpperCase() + str.slice(1);
+ }
+
+ _handleSave = async () => {
+ if (this.props.external || !this.props.isOwner) return;
+ this.props.onUpdateViewer({ tags: this.state.suggestions });
+ const response = await Actions.updateFile({
+ id: this.props.data.id,
+ data: {
+ name: this.state.name,
+ body: this.state.body,
+ source: this.state.source,
+ author: this.state.author,
+ tags: this.state.tags,
+ },
+ });
+ Events.hasError(response);
+ this.setState({ showSavedMessage: true });
+ };
+
+ _handleSaveCopy = async (data) => {
+ this.setState({ loading: "savingCopy" });
+ console.log(data);
+ await UserBehaviors.saveCopy({ files: [data] });
+ this.setState({ loading: false });
+ };
+
+ _handleUpload = async (e) => {
+ if (this.props.external || !this.props.isOwner) return;
+ e.persist();
+ this.setState({ isUploading: true });
+ let previousCoverId = this.props.data.data.coverImage?.id;
+ if (!e || !e.target) {
+ this.setState({ isUploading: false });
+ return;
+ }
+ let file = await UserBehaviors.uploadImage(e.target.files[0], this.props.resources, true);
+ if (!file) {
+ this.setState({ isUploading: false });
+ return;
+ }
+
+ let coverImage = file;
+
+ //TODO(martina): create an endpoint specifically for cover images instead of this, which will delete original cover image etc
+
+ let updateReponse = await Actions.updateFile({
+ id: this.props.data.id,
+ data: {
+ coverImage,
+ },
+ });
+
+ if (previousCoverId) {
+ if (!this.props.viewer.library.some((obj) => obj.id === previousCoverId)) {
+ await UserBehaviors.deleteFiles(previousCoverId, true);
+ }
+ }
+
+ Events.hasError(updateReponse);
+ this.setState({ isUploading: false });
+ };
+
+ _handleDownload = () => {
+ if (this.props.data.data.type === "application/unity") {
+ this.setState({ isDownloading: true }, async () => {
+ const response = await UserBehaviors.downloadZip(this.props.data);
+ this.setState({ isDownloading: false });
+ Events.hasError(response);
+ });
+ } else {
+ UserBehaviors.download(this.props.data);
+ }
+ };
+
+ _handleCreateSlate = async () => {
+ if (this.props.external) return;
+ this.props.onClose();
+ this.props.onAction({
+ type: "SIDEBAR",
+ value: "SIDEBAR_CREATE_SLATE",
+ data: { files: [this.props.data] },
+ });
+ };
+
+ _handleDelete = () => {
+ if (this.props.external || !this.props.isOwner) return;
+ const message =
+ "Are you sure you want to delete this? It will be removed from your slates as well";
+ if (!window.confirm(message)) {
+ return;
+ }
+ const id = this.props.data.id;
+
+ let updatedLibrary = this.props.viewer.library.filter((obj) => obj.id !== id);
+ if (this.props.carouselType === "SLATE") {
+ const slateId = this.props.current.id;
+ let slates = this.props.viewer.slates;
+ for (let slate of slates) {
+ if (slate.id === slateId) {
+ slate.objects = slate.objects.filter((obj) => obj.id !== id);
+ break;
+ }
+ }
+ this.props.onUpdateViewer({ library: updatedLibrary, slates });
+ } else {
+ this.props.onUpdateViewer({ library: updatedLibrary });
+ }
+
+ UserBehaviors.deleteFiles(id);
+ };
+
+ _handleAdd = async (slate) => {
+ let inPublicSlates = this.state.inPublicSlates;
+ if (this.state.selected[slate.id]) {
+ if (slate.isPublic) {
+ inPublicSlates -= 1;
+ }
+ UserBehaviors.removeFromSlate({ slate, ids: [this.props.data.id] });
+ } else {
+ if (slate.isPublic) {
+ inPublicSlates += 1;
+ }
+ UserBehaviors.addToSlate({
+ slate,
+ files: [this.props.data],
+ });
+ }
+ this.setState({
+ selected: {
+ ...this.state.selected,
+ [slate.id]: !this.state.selected[slate.id],
+ },
+ inPublicSlates,
+ });
+ };
+
+ _handleRemove = async () => {
+ if (!this.props.carouselType === "SLATE" || this.props.external || !this.props.isOwner) {
+ return;
+ }
+
+ const id = this.props.data.id;
+ const slateId = this.props.current.id;
+ let slates = this.props.viewer.slates;
+ for (let slate of slates) {
+ if (slate.id === slateId) {
+ slate.objects = slate.objects.filter((obj) => obj.id !== id);
+ break;
+ }
+ }
+ this.props.onUpdateViewer({ slates });
+
+ UserBehaviors.removeFromSlate({ slate: this.props.current, ids: [this.props.data.id] });
+ };
+
+ _handleToggleVisibility = async (e) => {
+ if (this.props.external || !this.props.isOwner) return;
+ const isVisible = this.state.isPublic || this.state.inPublicSlates > 0;
+ let selected = cloneDeep(this.state.selected);
+ if (this.state.inPublicSlates) {
+ const slateIds = Object.entries(this.state.selected)
+ .filter((entry) => entry[1])
+ .map((entry) => entry[0]);
+ const publicSlateIds = [];
+ const publicSlateNames = [];
+ for (let slate of this.props.viewer.slates) {
+ if (slate.isPublic && slateIds.includes(slate.id)) {
+ publicSlateNames.push(slate.data.name);
+ publicSlateIds.push(slate.id);
+ selected[slate.id] = false;
+ }
+ }
+ const slateNames = publicSlateNames.join(", ");
+ const message = `Making this file private will remove it from the following public slates: ${slateNames}. Do you wish to continue?`;
+ if (!window.confirm(message)) {
+ return;
+ }
+ }
+
+ if (this.props.carouselType === "SLATE" && this.props.current.isPublic) {
+ const slateId = this.props.current.id;
+ let slates = this.props.viewer.slates;
+ for (let slate of slates) {
+ if (slate.id === slateId) {
+ slate.objects = slate.objects.filter((obj) => obj.id !== id);
+ break;
+ }
+ }
+ this.props.onUpdateViewer({ slates });
+ }
+
+ let response = await Actions.toggleFilePrivacy(this.props.data);
+ Events.hasError(response);
+ if (isVisible) {
+ this.setState({ inPublicSlates: 0, isPublic: false, selected });
+ } else {
+ this.setState({ isPublic: true });
+ }
+ };
+
+ render() {
+ const isVisible = this.state.isPublic || this.state.inPublicSlates > 0 ? true : false;
+ const file = this.props.data;
+ const { coverImage, type, size } = file.data;
+ const editingAllowed = this.props.isOwner && !this.props.isRepost && !this.props.external;
+
+ const isUnityGame = type === "application/unity";
+
+ const elements = [];
+ if (editingAllowed && !isUnityGame) {
+ elements.push(
+
+ );
+ } else {
+ const hasName = !Strings.isEmpty(file.data.name || file.filename);
+ const hasBody = !Strings.isEmpty(file.data.body);
+ const hasSource = !Strings.isEmpty(file.data.source);
+ const hasAuthor = !Strings.isEmpty(file.data.author);
+
+ if (hasName) {
+ elements.push(
+
+ );
+ }
+
+ if (hasBody) {
+ elements.push(
+
+ );
+ }
+
+ if (hasSource) {
+ elements.push(
+
+ );
+ }
+
+ if (hasAuthor) {
+ elements.push(
+
+ );
+ }
+ }
+
+ let actions = [];
+
+ {
+ this.props.carouselType === "ACTIVITY"
+ ? actions.push(
+
+ this.props.onAction({
+ type: "NAVIGATE",
+ value: "NAV_SLATE",
+ data: file.slate,
+ })
+ }
+ >
+
+ Go to slate
+
+ )
+ : null;
+ }
+
+ actions.push(
+
+ {this.state.isDownloading ? (
+ <>
+
+ Downloading
+ >
+ ) : (
+ <>
+
+ Download
+ >
+ )}
+
+ );
+
+ if (!this.props.external && (!this.props.isOwner || this.props.isRepost)) {
+ actions.push(
+ this._handleSaveCopy(file)}>
+
+
+ {this.state.loading === "savingCopy" ? (
+
+ ) : (
+ Save copy
+ )}
+
+
+ );
+ }
+
+ if (this.props.carouselType === "SLATE" && !this.props.external && this.props.isOwner) {
+ actions.push(
+
+
+ Remove from slate
+
+ );
+ }
+
+ if (editingAllowed) {
+ actions.push(
+
+
+ Delete
+
+ );
+ }
+
+ let uploadCoverImage;
+ if (editingAllowed && type && !Validations.isPreviewableImage(type)) {
+ uploadCoverImage = (
+
+
+ Preview image
+
+ {coverImage ? (
+ <>
+
This is the preview image of your file.
+
+
+
+ >
+ ) : (
+
Add a preview image for your file.
+ )}
+
+
+
+ Upload preview image
+
+
+
+ );
+ }
+
+ let privacy;
+ if (editingAllowed) {
+ privacy = (
+
+
+ Privacy
+
+
+ {isVisible
+ ? "This file is currently visible to everyone and searchable within Slate. It may appear in activity feeds and explore."
+ : "This file is currently not visible to others unless they have the link."}
+
+
+
+ Public
+
+ ),
+ },
+ {
+ value: false,
+ label: (
+
+
+ Private
+
+ ),
+ },
+ ]}
+ dark={true}
+ style={{ marginTop: 12 }}
+ labelStyle={{ fontFamily: Constants.font.medium }}
+ selected={isVisible}
+ onChange={this._handleToggleVisibility}
+ />
+
+ );
+ }
+
+ return (
+
+ {this.state.showSavedMessage && (
+
+
+ Changes saved
+
+ )}
+
+
+
+
+
+ {elements}
+
+ {!this.props.external &&
{actions}
}
+ {privacy}
+ {uploadCoverImage}
+ {!this.props.external && (
+ <>
+
this._handleToggleAccordion("showConnectedSection")}
+ >
+
+
+
+ Add to slate
+
+ {this.state.showConnectedSection && (
+
+
+
+ )}
+ >
+ )}
+
+ {this.props.data.filename.endsWith(".md") ? (
+ <>
+
+ Settings
+
+
+ >
+ ) : null}
+
+
+ );
+ }
+}
+
+export default withTheme(CarouselSidebar);
+
+{
+ /* <>
+
+ Visibility
+
+
+
{isVisible ? "Everyone" : "Link only"}
+
+
+
+ {isVisible
+ ? "This file is currently visible to everyone and searchable within Slate. It may appear in activity feeds and explore."
+ : "This file is currently not visible to others unless they have the link."}
+
+ > */
+}
diff --git a/components/core/CarouselSidebarData.js b/components/core/CarouselSidebarData.js
index 76977c58..b57965f4 100644
--- a/components/core/CarouselSidebarData.js
+++ b/components/core/CarouselSidebarData.js
@@ -362,7 +362,7 @@ class CarouselSidebarData extends React.Component {
json.data.url = Strings.getCIDGatewayURL(json.data.cid);
- let updateReponse = await Actions.updateData({
+ let updateReponse = await Actions.updateFile({
data: {
id: this.props.data.id,
coverImage: json.data,
diff --git a/components/core/DataView.js b/components/core/DataView.js
index 2c554a56..b075c7ae 100644
--- a/components/core/DataView.js
+++ b/components/core/DataView.js
@@ -474,37 +474,29 @@ export default class DataView extends React.Component {
this.setState({ checked: {} });
};
- _handleDelete = (cid, id) => {
+ _handleDelete = (id) => {
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;
}
- let cids;
let ids;
- if (cid) {
- cids = [cid];
+ if (id) {
ids = [id];
} else {
- cids = Object.keys(this.state.checked).map((id) => {
- let index = parseInt(id);
- let item = this.props.viewer.library[0].children[index];
- return item.cid;
- });
ids = Object.keys(this.state.checked).map((id) => {
let index = parseInt(id);
- let item = this.props.viewer.library[0].children[index];
+ let item = this.props.viewer.library[index];
return item.id;
});
}
- let library = this.props.viewer.library;
- library[0].children = library[0].children.filter(
+ let library = this.props.viewer.library.filter(
(obj) => !ids.includes(obj.id) && !cids.includes(obj.cid)
);
this.props.onUpdateViewer({ library });
- UserBehaviors.deleteFiles(cids, ids);
+ UserBehaviors.deleteFiles(ids);
this.setState({ checked: {} });
};
@@ -545,7 +537,7 @@ export default class DataView extends React.Component {
};
_handleAddToSlate = (e) => {
- let userFiles = this.props.viewer.library[0].children;
+ let userFiles = this.props.viewer.library;
let files = Object.keys(this.state.checked).map((index) => userFiles[index]);
this.props.onAction({
type: "SIDEBAR",
@@ -576,9 +568,9 @@ export default class DataView extends React.Component {
};
_handleDragToDesktop = (e, object) => {
- const url = Strings.getCIDGatewayURL(object.cid);
- const title = object.file || object.name;
- const type = object.type;
+ const url = Strings.getURLfromCID(object.cid);
+ const title = object.filename || object.data.name;
+ const type = object.data.type;
console.log(e.dataTransfer, e.dataTransfer.setData);
e.dataTransfer.setData("DownloadURL", `${type}:${title}:${url}`);
};
@@ -690,13 +682,15 @@ export default class DataView extends React.Component {
>
{Strings.pluralize("Download file", numChecked)}
- this._handleDelete()}
- >
- {Strings.pluralize("Delete file", numChecked)}
-
+ {this.props.isOwner && (
+ this._handleDelete()}
+ >
+ {Strings.pluralize("Delete file", numChecked)}
+
+ )}
{
@@ -743,13 +737,7 @@ export default class DataView extends React.Component {
onMouseLeave={() => this._handleCheckBoxMouseLeave(i)}
>
{numChecked || this.state.hover === i || this.state.menu === each.id ? (
@@ -785,7 +773,7 @@ export default class DataView extends React.Component {
{
text: "Copy link",
onClick: (e) =>
- this._handleCopy(e, Strings.getCIDGatewayURL(cid)),
+ this._handleCopy(e, Strings.getURLfromCID(cid)),
},
{
text: "Delete",
@@ -812,7 +800,7 @@ export default class DataView extends React.Component {
{
text: "Copy link",
onClick: (e) =>
- this._handleCopy(e, Strings.getCIDGatewayURL(cid)),
+ this._handleCopy(e, Strings.getURLfromCID(cid)),
},
]}
/>
@@ -938,12 +926,12 @@ export default class DataView extends React.Component {
}}
onDragEnd={this._enableDragAndDropUploadEvent}
>
-
+
this._handleSelect(index)}>
-
+
-
{each.file || each.name}
+
{each.filename || each.data.name}
@@ -979,13 +967,13 @@ export default class DataView extends React.Component {
},
// {
// text: "Copy link",
- // onClick: (e) => this._handleCopy(e, Strings.getCIDGatewayURL(cid)),
+ // onClick: (e) => this._handleCopy(e, Strings.getURLfromCID(cid)),
// },
{
text: "Delete",
onClick: (e) => {
e.stopPropagation();
- this.setState({ menu: null }, () => this._handleDelete(cid, each.id));
+ this.setState({ menu: null }, () => this._handleDelete(each.id));
},
},
]}
diff --git a/components/core/FilePreviewBubble.js b/components/core/FilePreviewBubble.js
index 15dfd43f..c6dd79c6 100644
--- a/components/core/FilePreviewBubble.js
+++ b/components/core/FilePreviewBubble.js
@@ -55,7 +55,7 @@ export const FilePreviewBubble = (props) => {
{showPreview && (
-
+
)}
diff --git a/components/core/FontFrame/Views/FontObjectPreview.js b/components/core/FontFrame/Views/FontObjectPreview.js
index 5322d776..22daf39b 100644
--- a/components/core/FontFrame/Views/FontObjectPreview.js
+++ b/components/core/FontFrame/Views/FontObjectPreview.js
@@ -1,7 +1,7 @@
import * as React from "react";
import { css } from "@emotion/react";
-import { useFont } from "../hooks";
+import { useFont } from "~/components/core/FontFrame/hooks";
const withView = (Component) => (props) => {
const ref = React.useRef(null);
@@ -35,7 +35,7 @@ const STYLES_LETTER = (theme) => css`
const FontObjectPreview = React.memo(
({ url, cid, fallback }) => {
- const { isFontLoading, error, fontName } = useFont({ url, name: cid }, [cid]);
+ const { isFontLoading, error, fontName } = useFont({ cid }, [cid]);
if (error || isFontLoading) {
return fallback;
}
diff --git a/components/core/FontFrame/hooks.js b/components/core/FontFrame/hooks.js
index 84184caf..0f958c64 100644
--- a/components/core/FontFrame/hooks.js
+++ b/components/core/FontFrame/hooks.js
@@ -1,15 +1,17 @@
import * as React from "react";
import * as Events from "~/common/custom-events";
import * as Content from "./Views/content";
+import * as Strings from "~/common/strings";
import { generateNumberByStep } from "~/common/utilities";
-export const useFont = ({ url, name }, deps) => {
+export const useFont = ({ cid }, deps) => {
+ const url = Strings.getURLfromCID(cid);
const [fetchState, setFetchState] = React.useState({ loading: false, error: null });
- const prevName = React.useRef(name);
+ const prevName = React.useRef(cid);
if (!window.$SLATES_LOADED_FONTS) window.$SLATES_LOADED_FONTS = [];
- const alreadyLoaded = window.$SLATES_LOADED_FONTS.includes(name);
+ const alreadyLoaded = window.$SLATES_LOADED_FONTS.includes(cid);
React.useEffect(() => {
if (alreadyLoaded) {
@@ -18,15 +20,15 @@ export const useFont = ({ url, name }, deps) => {
}
setFetchState((prev) => ({ ...prev, error: null, loading: true }));
- const customFonts = new FontFace(name, `url(${url})`);
+ const customFonts = new FontFace(cid, `url(${url})`);
customFonts
.load()
.then((loadedFont) => {
document.fonts.add(loadedFont);
- prevName.current = name;
+ prevName.current = cid;
setFetchState((prev) => ({ ...prev, loading: false }));
- window.$SLATES_LOADED_FONTS.push(name);
+ window.$SLATES_LOADED_FONTS.push(cid);
})
.catch((err) => {
setFetchState({ loading: false, error: err });
@@ -37,7 +39,7 @@ export const useFont = ({ url, name }, deps) => {
isFontLoading: fetchState.loading,
error: fetchState.error,
// NOTE(Amine): show previous font while we load the new one.
- fontName: alreadyLoaded ? name : prevName.current,
+ fontName: alreadyLoaded ? cid : prevName.current,
};
};
diff --git a/components/core/FontFrame/index.js b/components/core/FontFrame/index.js
index f957a34b..dce6db14 100644
--- a/components/core/FontFrame/index.js
+++ b/components/core/FontFrame/index.js
@@ -1,4 +1,5 @@
import * as React from "react";
+import * as Strings from "~/common/strings";
import { css } from "@emotion/react";
@@ -44,8 +45,9 @@ const FontLoader = () => (
loading...
);
-export default function FontFrame({ cid, url, fallback, ...props }) {
- const { isFontLoading, error, fontName } = useFont({ url, name: cid }, [cid, url]);
+export default function FontFrame({ cid, fallback, ...props }) {
+ const url = Strings.getURLfromCID(cid);
+ const { isFontLoading, error, fontName } = useFont({ cid }, [cid, url]);
const [
currentState,
diff --git a/components/core/OnboardingModal.js b/components/core/OnboardingModal.js
index f6978f09..2b74368b 100644
--- a/components/core/OnboardingModal.js
+++ b/components/core/OnboardingModal.js
@@ -65,7 +65,9 @@ export class OnboardingModal extends React.Component {
};
componentDidMount = () => {
- Actions.updateStatus({ onboarding: this.props.unseenAnnouncements });
+ Actions.updateStatus({
+ onboarding: this.props.unseenAnnouncements,
+ });
let slides = [];
if (this.props.newAccount) {
slides = this.onboardingCopy;
diff --git a/components/core/Profile.js b/components/core/Profile.js
index 457c60ea..0d50df79 100644
--- a/components/core/Profile.js
+++ b/components/core/Profile.js
@@ -4,6 +4,7 @@ import * as Strings from "~/common/strings";
import * as SVG from "~/common/svg";
import * as Actions from "~/common/actions";
import * as Utilities from "~/common/utilities";
+import * as Events from "~/common/custom-events";
import * as Window from "~/common/window";
import { GlobalCarousel } from "~/components/system/components/GlobalCarousel";
@@ -85,8 +86,8 @@ const STYLES_STATUS_INDICATOR = css`
width: 12px;
height: 12px;
border-radius: 50%;
- border: 2px solid ${Constants.system.gray50};
- background-color: ${Constants.system.white};
+ border: 2px solid ${Constants.system.active};
+ background-color: ${Constants.system.active};
`;
const STYLES_NAME = css`
@@ -211,8 +212,8 @@ const STYLES_DIRECTORY_STATUS_INDICATOR = css`
width: 7px;
height: 7px;
border-radius: 50%;
- border: 1.2px solid ${Constants.system.gray50};
- background-color: ${Constants.system.white};
+ border: 1.2px solid ${Constants.system.active};
+ background-color: ${Constants.system.active};
`;
const STYLES_MESSAGE = css`
@@ -258,15 +259,7 @@ function UserEntry({
css={STYLES_DIRECTORY_PROFILE_IMAGE}
style={{ backgroundImage: `url(${user.data.photo})` }}
>
- {showStatusIndicator && (
-
- )}
+ {showStatusIndicator && isOnline &&
}
{user.data.name || `@${user.username}`}
@@ -279,13 +272,7 @@ function UserEntry({
css={STYLES_DIRECTORY_PROFILE_IMAGE}
style={{ backgroundImage: `url(${user.data.photo})` }}
>
-
+ {isOnline &&
}
{user.data.name || `@${user.username}`}
@@ -307,23 +294,23 @@ export default class Profile extends React.Component {
peerTab: 0,
// copyValue: "",
contextMenu: null,
- publicFiles: this.props.creator.library[0].children,
- slates: this.props.creator.slates,
+ slates: this.props.user.slates,
subscriptions: [],
- subscribers: [],
- isFollowing: this.props.external
- ? false
- : !!this.props.viewer.subscriptions.filter((entry) => {
- return entry.target_user_id === this.props.creator.id;
- }).length,
+ followers: [],
+ following: [],
+ isFollowing:
+ this.props.external || this.props.user.id === this.props.viewer?.id
+ ? false
+ : !!this.props.viewer?.following.some((entry) => {
+ return entry.id === this.props.user.id;
+ }),
fetched: false,
- tab: this.props.tab,
+ tab: this.props.tab || 0,
};
componentDidMount = () => {
- console.log(this.props.creator);
+ console.log(this.props.user);
this._handleUpdatePage();
- // this.filterByVisibility();
};
componentDidUpdate = (prevProps) => {
@@ -333,22 +320,30 @@ export default class Profile extends React.Component {
};
fetchSocial = async () => {
- let query = { userId: this.props.creator.id };
- const { subscribers, subscriptions } = await Actions.getSocial(query);
- this.setState({ subscribers: subscribers, subscriptions: subscriptions, fetched: true });
+ if (this.state.fetched) return;
+ let following, followers, subscriptions;
+ if (this.props.user.id === this.props.viewer?.id) {
+ following = this.props.viewer?.following;
+ followers = this.props.viewer?.followers;
+ subscriptions = this.props.viewer?.subscriptions;
+ } else {
+ const query = { id: this.props.user.id };
+ let response = await Actions.getSocial(query);
+ if (Events.hasError(response)) {
+ return;
+ }
+ following = response.following;
+ followers = response.followers;
+ subscriptions = response.subscriptions;
+ }
+ this.setState({
+ following: following,
+ followers: followers,
+ subscriptions: subscriptions,
+ fetched: true,
+ });
};
- // filterByVisibility = () => {
- // let publicFiles = [];
- // if (this.props.isOwner) {
- // const res = Utilities.getPublicAndPrivateFiles({ viewer: this.props.creator });
- // publicFiles = res.publicFiles;
- // } else {
- // publicFiles = this.props.creator.library[0].children;
- // }
- // this.setState({ publicFiles: publicFiles });
- // };
-
// _handleCopy = (e, value) => {
// e.stopPropagation();
// this.setState({ copyValue: value }, () => {
@@ -417,148 +412,88 @@ export default class Profile extends React.Component {
};
render() {
- let tab = typeof this.state.tab === "undefined" || this.state.tab === null ? 1 : this.state.tab;
+ let tab = this.state.tab || 0;
+ let publicFiles = this.props.user.library;
let isOwner = this.props.isOwner;
- let creator = this.props.creator;
- let username = this.state.slateTab === 0 ? creator.username : null;
- let subscriptions = this.state.subscriptions;
- let subscribers = this.state.subscribers;
+ let user = this.props.user;
+ let username = this.state.slateTab === 0 ? user.username : null;
let slates = [];
if (tab === 1) {
if (this.state.slateTab === 0) {
- slates = isOwner
- ? creator.slates.filter((slate) => slate.data.public === true)
- : creator.slates;
+ slates = user.slates
+ ? isOwner
+ ? user.slates.filter((slate) => slate.isPublic === true)
+ : user.slates
+ : null;
} else {
- slates = subscriptions
- .filter((relation) => {
- return !!relation.target_slate_id;
- })
- .map((relation) => relation.slate);
+ slates = this.state.subscriptions;
}
}
let exploreSlates = this.props.exploreSlates;
- let peers = [];
+ let peers = this.state.peerTab === 0 ? this.state.following : this.state.followers;
if (tab === 2) {
- if (this.state.peerTab === 0) {
- peers = subscriptions
- .filter((relation) => {
- return !!relation.target_user_id;
- })
- .map((relation) => {
- let button = (
- this._handleClick(e, relation.id)}>
-
- {this.state.contextMenu === relation.id ? (
-
this._handleClick(e, relation.id)}
- >
- {
- return subscription.target_user_id === relation.target_user_id;
- }).length
- ? "Unfollow"
- : "Follow",
- onClick: this.props.viewer
- ? (e) => this._handleFollow(e, relation.target_user_id)
- : () => this.setState({ visible: true }),
- },
- ]}
- />
-
- ) : null}
-
- );
+ peers = peers.map((relation) => {
+ let button = (
+ this._handleClick(e, relation.id)}>
+
+ {this.state.contextMenu === relation.id ? (
+
this._handleClick(e, relation.id)}
+ >
+ {
+ return subscription.id === relation.id;
+ }).length
+ ? "Unfollow"
+ : "Follow",
+ onClick: this.props.viewer
+ ? (e) => this._handleFollow(e, relation.id)
+ : () => this.setState({ visible: true }),
+ },
+ ]}
+ />
+
+ ) : null}
+
+ );
- return (
- {
- this.props.onAction({
- type: "NAVIGATE",
- value: this.props.sceneId,
- scene: "PROFILE",
- data: relation.user,
- });
- }}
- external={this.props.external}
- url={`/${relation.user.username}`}
- />
- );
- });
- } else {
- peers = subscribers.map((relation) => {
- let button = (
- this._handleClick(e, relation.id)}>
-
- {this.state.contextMenu === relation.id ? (
-
this._handleClick(e, relation.id)}
- >
- {
- return subscription.target_user_id === relation.owner_user_id;
- }).length
- ? "Unfollow"
- : "Follow",
- onClick: this.props.viewer
- ? (e) => this._handleFollow(e, relation.owner_user_id)
- : () => this.setState({ visible: true }),
- },
- ]}
- />
-
- ) : null}
-
- );
- return (
- {
- this.props.onAction({
- type: "NAVIGATE",
- value: this.props.sceneId,
- scene: "PROFILE",
- data: relation.owner,
- });
- }}
- external={this.props.external}
- url={`/${relation.owner.username}`}
- />
- );
- });
- }
+ return (
+ {
+ this.props.onAction({
+ type: "NAVIGATE",
+ value: this.props.sceneId,
+ scene: "PROFILE",
+ data: relation,
+ });
+ }}
+ external={this.props.external}
+ url={`/${relation.username}`}
+ />
+ );
+ });
}
- let total = creator.slates.reduce((total, slate) => {
- return total + slate.data?.objects?.length || 0;
- }, 0);
+ let total = 0;
+ if (user.slates) {
+ total = user.slates.reduce((total, slate) => {
+ return total + slate.data?.objects?.length || 0;
+ }, 0);
+ }
const showStatusIndicator = this.props.isAuthenticated;
@@ -569,10 +504,10 @@ export default class Profile extends React.Component {
onUpdateViewer={this.props.onUpdateViewer}
resources={this.props.resources}
viewer={this.props.viewer}
- objects={this.state.publicFiles}
- isOwner={false}
+ objects={publicFiles}
+ isOwner={this.props.isOwner}
onAction={this.props.onAction}
- mobile={this.props.mobile}
+ isMobile={this.props.isMobile}
external={this.props.external}
/>
@@ -580,30 +515,22 @@ export default class Profile extends React.Component {
- {showStatusIndicator && (
-
+ {showStatusIndicator && this.checkStatus({ id: user.id }) && (
+
)}
-
{Strings.getPresentationName(creator)}
+
{Strings.getPresentationName(user)}
{!isOwner && (
{this.state.isFollowing ? (
{
this.setState({ isFollowing: false });
- this._handleFollow(e, this.props.creator.id);
+ this._handleFollow(e, this.props.user.id);
}}
>
Unfollow
@@ -612,7 +539,7 @@ export default class Profile extends React.Component {
{
this.setState({ isFollowing: true });
- this._handleFollow(e, this.props.creator.id);
+ this._handleFollow(e, this.props.user.id);
}}
>
Follow
@@ -620,9 +547,9 @@ export default class Profile extends React.Component {
)}
)}
- {creator.data.body ? (
+ {user.data.body ? (
) : null}
@@ -633,7 +560,7 @@ export default class Profile extends React.Component {
- {creator.slates.length}{" "}
+ {user.slates?.length || 0}{" "}
Slates
@@ -649,7 +576,7 @@ export default class Profile extends React.Component {
open={this.state.visible}
redirectURL={`/_${Strings.createQueryParams({
scene: "NAV_PROFILE",
- user: creator.username,
+ user: user.username,
})}`}
/>
@@ -664,7 +591,7 @@ export default class Profile extends React.Component {
/>
{tab === 0 ? (
- {this.props.mobile ? null : (
+ {this.props.isMobile ? null : (
)}
- {this.state.publicFiles.length ? (
+ {publicFiles.length ? (
diff --git a/components/core/SearchModal.js b/components/core/SearchModal.js
index 06ffb20a..ec85217b 100644
--- a/components/core/SearchModal.js
+++ b/components/core/SearchModal.js
@@ -204,26 +204,22 @@ const STYLES_EMPTY_SLATE_PREVIEW = css`
const SlatePreview = ({ slate, user }) => {
let preview;
- for (let obj of slate.data.objects) {
- if (obj.type && Validations.isPreviewableImage(obj.type)) {
- preview = obj;
- break;
+ if (slate.objects?.length) {
+ for (let obj of slate.objects) {
+ if (obj.type && Validations.isPreviewableImage(obj.type)) {
+ preview = obj;
+ break;
+ }
+ }
+ if (!preview) {
+ preview = slate.objects[0];
}
- }
- if (!slate && slate.data.objects && slate.data.objects.length) {
- preview = slate.data.objects[0];
}
return (
{preview ? (
-
+
) : (
@@ -233,9 +229,11 @@ const SlatePreview = ({ slate, user }) => {
{user ? (
Created by: {user.data.name || `@${user.username}`}
) : null}
-
- {slate.data.objects.length} File{slate.data.objects.length === 1 ? "" : "s"}
-
+ {slate.objects && (
+
+ {slate.objects.length} File{slate.objects.length === 1 ? "" : "s"}
+
+ )}
);
};
@@ -248,16 +246,10 @@ const FileEntry = ({ file }) => {
-
{file.title || file.name || file.file}
- {file.file ? (
-
- {Strings.getFileExtension(file.file)}
-
- ) : file.name ? (
-
- {Strings.getFileExtension(file.name)}
-
- ) : null}
+
{file.data.name || file.filename}
+
+ {Strings.getFileExtension(file.filename)}
+
@@ -268,15 +260,7 @@ const FilePreview = ({ file, slate, user, viewerId }) => {
return (
-
+
{user ? (
Owner: {user.data.name || `@${user.username}`}
@@ -520,16 +504,6 @@ export class SearchModal extends React.Component {
slateIds.push(sub.target_slate_id);
}
}
- // for (let sub of this.props.viewer.trusted) {
- // if (sub.target_user_id) {
- // networkIds.push(sub.target_user_id);
- // }
- // }
- // for (let sub of this.props.viewer.pendingTrusted) {
- // if (sub.owner_user_id) {
- // networkIds.push(sub.owner_user_id);
- // }
- // }
this.networkIds = networkIds;
this.slateIds = slateIds;
};
@@ -545,35 +519,21 @@ export class SearchModal extends React.Component {
fuzzy: 0.15,
},
});
- let files = this.props.viewer.library[0].children.map((file, i) => {
+ let files = this.props.viewer.library.map((file, i) => {
return {
+ ...file,
type: "DATA_FILE",
- id: file.id,
- name: file.title,
- title: file.file,
- data: {
- file: {
- ...file,
- url: Strings.getCIDGatewayURL(file.cid),
- },
- },
};
});
this.localSearch.addAll(files);
- let privateSlates = this.props.viewer.slates.filter((slate) => !slate.data.public);
+ let privateSlates = this.props.viewer.slates.filter((slate) => !slate.isPublic);
let privateFiles = [];
for (let slate of privateSlates) {
privateFiles.push(
- ...slate.data.objects.map((file, i) => {
+ ...slate.objects.map((file, i) => {
return {
+ ...file,
type: "FILE",
- id: `${file.id}-${slate.id}`,
- name: file.name,
- title: file.title,
- data: {
- file,
- slate,
- },
};
})
);
@@ -581,8 +541,6 @@ export class SearchModal extends React.Component {
privateSlates = privateSlates.map((slate) => {
return {
...slate,
- name: slate.slatename,
- title: slate.data.name,
type: "SLATE",
};
});
@@ -663,7 +621,7 @@ export class SearchModal extends React.Component {
};
_handleChange = (e) => {
- this.debounceInstance(e);
+ this.debounceInstance();
this.setState({ inputValue: e.target.value });
};
@@ -743,6 +701,7 @@ export class SearchModal extends React.Component {
query: this.state.inputValue,
type: this.state.typeFilter,
});
+ console.log(response);
this.setState({ unfilteredResults: response.data.results });
res = response.data.results;
} else {
@@ -751,8 +710,8 @@ export class SearchModal extends React.Component {
searchResults = this.processResults(res);
for (let res of searchResults) {
if (res.type === "USER") {
- let id = res.user.id;
- if (ids.has(id)) continue;
+ let id = res.user?.id;
+ if (!id || ids.has(id)) continue;
ids.add(id);
results.push({
id,
@@ -762,8 +721,8 @@ export class SearchModal extends React.Component {
preview:
,
});
} else if (res.type === "SLATE") {
- let id = res.user.id;
- if (ids.has(id)) continue;
+ let id = res.slate?.id;
+ if (!id || ids.has(id)) continue;
ids.add(id);
results.push({
id,
@@ -773,8 +732,8 @@ export class SearchModal extends React.Component {
preview:
,
});
} else if (res.type === "FILE") {
- let id = res.user.id;
- if (ids.has(id)) continue;
+ let id = res.file?.id;
+ if (!id || ids.has(id)) continue;
ids.add(id);
results.push({
id,
@@ -858,26 +817,23 @@ export class SearchModal extends React.Component {
value: "NAV_SLATE",
data: res.data.slate,
});
- }
- if (res.type === "USER") {
+ } else if (res.type === "USER") {
this.props.onAction({
type: "NAVIGATE",
value: "NAV_PROFILE",
data: res.data.user,
});
- }
- if (res.type === "DATA_FILE") {
+ } else if (res.type === "DATA_FILE" || res.data.file.ownerId === this.props.viewer.id) {
await this.props.onAction({
type: "NAVIGATE",
value: "NAV_DATA",
fileId: res.data.file.id,
});
- }
- if (res.type === "FILE") {
+ } else if (res.type === "FILE") {
await this.props.onAction({
type: "NAVIGATE",
- value: "NAV_SLATE",
- data: res.data.slate,
+ value: "NAV_PROFILE",
+ data: res.data.user,
fileId: res.data.file.id,
});
}
@@ -1194,7 +1150,7 @@ export class SearchModal extends React.Component {
paddingRight: selectedIndex === i ? "88px" : "4px",
}}
onClick={() => {
- selectedIndex === i || this.props.mobile
+ selectedIndex === i || this.props.isMobile
? this._handleSelect(each)
: this.setState({ selectedIndex: i });
}}
diff --git a/components/core/SlateLayout.js b/components/core/SlateLayout.js
index da7c5f4c..ece589e1 100644
--- a/components/core/SlateLayout.js
+++ b/components/core/SlateLayout.js
@@ -52,7 +52,7 @@ const generateLayout = (items) => {
w: SIZE,
h: 0,
z: 0,
- id: item.id,
+ id: item.id.replace("data-", ""),
};
}) || []
);
@@ -60,7 +60,7 @@ const generateLayout = (items) => {
const preload = (item) =>
new Promise((resolve, reject) => {
- if (!item.type || !Validations.isPreviewableImage(item.type)) {
+ if (!item.data.type || !Validations.isPreviewableImage(item.data.type)) {
resolve(200);
}
const img = new Image();
@@ -68,7 +68,7 @@ const preload = (item) =>
resolve((200 * img.height) / img.width);
};
img.onerror = reject;
- const url = item.url;
+ const url = Strings.getURLfromCID(item.cid);
img.src = url;
});
@@ -431,7 +431,7 @@ export class SlateLayout extends React.Component {
let defaultLayout = layouts ? layouts.defaultLayout : this.state.defaultLayout;
let fileNames = layouts ? layouts.fileNames : this.state.fileNames;
let layout = layouts ? this.cloneLayout(layouts.layout) : this.cloneLayout(this.state.layout);
- let layoutIds = layout.map((pos) => pos.id);
+ let layoutIds = layout.map((pos) => pos.id.replace("data-", ""));
let repairNeeded = false;
if (items.length !== layout.length) {
repairNeeded = true;
@@ -444,7 +444,7 @@ export class SlateLayout extends React.Component {
}
}
if (!repairNeeded && items.length === layout.length) {
- let itemIds = items.map((item) => item.id);
+ let itemIds = items.map((item) => item.id.replace("data-", ""));
for (let i = 0; i < itemIds.length; i++) {
if (itemIds[i] !== layoutIds[i]) {
repairNeeded = true;
@@ -457,7 +457,7 @@ export class SlateLayout extends React.Component {
}
let newLayout = new Array(items.length);
for (let i = 0; i < items.length; i++) {
- let layoutIndex = layoutIds.indexOf(items[i].id);
+ let layoutIndex = layoutIds.indexOf(items[i].id.replace("data-", ""));
if (layoutIndex === -1) {
continue;
} else if (defaultLayout && layoutIndex >= 5 && !layout[layoutIndex].y) {
@@ -509,7 +509,7 @@ export class SlateLayout extends React.Component {
h: height,
w: SIZE,
z: 0,
- id: items[i].id,
+ id: items[i].id.replace("data-", ""),
};
h += 1;
}
@@ -544,7 +544,7 @@ export class SlateLayout extends React.Component {
w: SIZE,
h: oldLayout && oldLayout.length > i ? oldLayout[i].h || height : height,
z: 0,
- id: this.state.items[i].id,
+ id: this.state.items[i].id.replace("data-", ""),
};
}
return layout;
@@ -957,7 +957,7 @@ export class SlateLayout extends React.Component {
_handleSetPreview = (e, i) => {
e.stopPropagation();
e.preventDefault();
- let url = this.state.items[i].url;
+ let url = Strings.getURLfromCID(this.state.items[i].cid);
if (this.props.preview === url) return;
this.props.onSavePreview(url);
};
@@ -982,7 +982,7 @@ export class SlateLayout extends React.Component {
items.push(this.state.items[i]);
}
}
- UserBehaviors.addToDataFromSlate({ files: items });
+ UserBehaviors.saveCopy({ files: items });
};
_handleAddToSlate = (e, i) => {
@@ -1009,10 +1009,10 @@ export class SlateLayout extends React.Component {
e.preventDefault();
let ids = [];
if (i !== undefined) {
- ids = [this.state.items[i].id];
+ ids = [this.state.items[i].id.replace("data-", "")];
} else {
for (let index of Object.keys(this.state.checked)) {
- ids.push(this.state.items[index].id);
+ ids.push(this.state.items[index].id.replace("data-", ""));
}
this.setState({ checked: {} });
}
@@ -1021,7 +1021,7 @@ export class SlateLayout extends React.Component {
let slateId = this.props.current.id;
for (let slate of slates) {
if (slate.id === slateId) {
- slate.data.objects = slate.data.objects.filter((obj) => !ids.includes(obj.id));
+ slate.objects = slate.objects.filter((obj) => !ids.includes(obj.id.replace("data-", "")));
this.props.onUpdateViewer({ slates });
break;
}
@@ -1043,9 +1043,9 @@ export class SlateLayout extends React.Component {
};
_handleDragToDesktop = (e, object) => {
- const url = Strings.getCIDGatewayURL(object.cid);
- const title = object.file || object.name;
- const type = object.type;
+ const url = Strings.getURLfromCID(object.cid);
+ const title = object.filename || object.data.name;
+ const type = object.data.type;
console.log(e.dataTransfer, e.dataTransfer.setData);
e.dataTransfer.setData("DownloadURL", `${type}:${title}:${url}`);
};
@@ -1060,32 +1060,25 @@ export class SlateLayout extends React.Component {
e.preventDefault();
let ids = [];
if (i !== undefined) {
- ids = [this.state.items[i].id];
+ ids = [this.state.items[i].id.replace("data-", "")];
} else {
for (let index of Object.keys(this.state.checked)) {
- ids.push(this.state.items[index].id);
+ ids.push(this.state.items[index].id.replace("data-", ""));
}
}
- let cids = [];
- for (let file of this.props.viewer.library[0].children) {
- if (ids.includes(file.id)) {
- cids.push(file.cid);
- }
- }
-
let slates = this.props.viewer.slates;
let slateId = this.props.current.id;
for (let slate of slates) {
if (slate.id === slateId) {
- slate.data.objects = slate.data.objects.filter(
- (obj) => !ids.includes(obj.id) && !cids.includes(obj.cid)
+ slate.objects = slate.objects.filter(
+ (obj) => !ids.includes(obj.id.replace("data-", "")) && !cids.includes(obj.cid)
);
this.props.onUpdateViewer({ slates });
break;
}
}
- await UserBehaviors.deleteFiles(cids, ids);
+ await UserBehaviors.deleteFiles(ids);
this.setState({ checked: {} });
};
@@ -1305,16 +1298,9 @@ export class SlateLayout extends React.Component {
}}
>
) : null}
@@ -1565,34 +1551,6 @@ export class SlateLayout extends React.Component {
: "24px",
}}
>
- {/* {
- this._handleCopy(e, this.state.items[i].url);
- }}
- onMouseDown={this._stopProp}
- onMouseUp={this._stopProp}
- onMouseEnter={() => this.setState({ tooltip: `${i}-copy` })}
- onMouseLeave={() => this.setState({ tooltip: null })}
- successState={
-
- }
- style={{
- height: 24,
- width: 24,
- borderRadius: "50%",
- backgroundColor: "rgba(248, 248, 248, 0.6)",
- color: "#4b4a4d",
- display: "flex",
- alignItems: "center",
- justifyContent: "center",
- cursor: "pointer",
- margin: "0 8px",
- WebkitBackdropFilter: "blur(25px)",
- backdropFilter: "blur(25px)",
- }}
- >
-
- */}
this._handleSetPreview(e, i)
: () => {}
}
style={
- this.props.preview === this.state.items[i].url
+ this.props.preview ===
+ Strings.getURLfromCID(this.state.items[i].cid)
? {
backgroundColor: "rgba(0, 97, 187, 0.75)",
}
- : this.state.items[i].type &&
- Validations.isPreviewableImage(this.state.items[i].type) &&
- this.state.items[i].size &&
- this.state.items[i].size < SIZE_LIMIT
+ : this.state.items[i].data.type &&
+ Validations.isPreviewableImage(
+ this.state.items[i].data.type
+ ) &&
+ this.state.items[i].data.size &&
+ this.state.items[i].data.size < SIZE_LIMIT
? {}
: {
color: "#999999",
@@ -1643,10 +1606,7 @@ export class SlateLayout extends React.Component {
}
>
{this.props.preview ===
- this.state.items[i].url.replace(
- "https://undefined",
- "https://"
- ) ? (
+ Strings.getURLfromCID(this.state.items[i].cid) ? (
- {this.state.items[i].title || this.state.items[i].name}
+ {this.state.items[i].data.name || this.state.items[i].filename}
- {Strings.getFileExtension(this.state.items[i].file)}
+ {Strings.getFileExtension(this.state.items[i].filename)}
) : null}
diff --git a/components/core/SlateLayoutMobile.js b/components/core/SlateLayoutMobile.js
index 1341e3b5..bec2bc94 100644
--- a/components/core/SlateLayoutMobile.js
+++ b/components/core/SlateLayoutMobile.js
@@ -33,14 +33,9 @@ export class SlateLayoutMobile extends React.Component {
onClick={() => this.props.onSelect(i)}
>
{
- let { isMobile, data } = this.props;
- const isPDF = data.type && data.type.startsWith("application/pdf");
-
- if (isPDF && isMobile) {
- window.open(url, "_blank");
- Events.dispatchCustomEvent({ name: "slate-global-close-carousel", detail: {} });
-
- return;
- }
+ window.open(url, "_blank");
};
componentDidMount() {
- const url = this.props.data.url;
- this.openLink(url);
+ if (this.props.isMobile) {
+ const file = this.props.file;
+ if (file.data.type && file.data.type.startsWith("application/pdf")) {
+ const url = Strings.getURLfromCID(file.cid);
+ this.openLink(url);
+ }
+ }
}
render() {
- const url = this.props.data.url;
- const type = this.props.data.type ? this.props.data.type : "LEGACY_NO_TYPE";
+ const { file, isMobile } = this.props;
+ const url = Strings.getURLfromCID(file.cid);
+ const type = file.data.type || "";
const playType = typeMap[type] ? typeMap[type] : type;
- let { isMobile } = this.props;
-
let element = No Preview
;
if (type.startsWith("application/pdf")) {
return (
<>
- {!isMobile && (
+ {isMobile ? (
+
+ Tap to open PDF in new tab
+
+ ) : (
- {/** Note(Amine): fallback if video type isn't supported (example .mov) */}
+ {/** NOTE(amine): fallback if video type isn't supported (example .mov) */}
);
@@ -155,12 +155,11 @@ export default class SlateMediaObject extends React.Component {
return ;
}
- if (endsWithAny([".ttf", ".otf", ".woff", ".woff2"], this.props.data.name)) {
+ if (endsWithAny([".ttf", ".otf", ".woff", ".woff2"], file.filename)) {
return (
{
e.stopPropagation();
@@ -169,8 +168,8 @@ export default class SlateMediaObject extends React.Component {
);
}
- if (this.props.data.name.endsWith(".md") || type.startsWith("text/plain")) {
- return ;
+ if (file.filename.endsWith(".md") || type.startsWith("text/plain")) {
+ return ;
}
if (Validations.isPreviewableImage(type)) {
@@ -189,17 +188,9 @@ export default class SlateMediaObject extends React.Component {
// TODO(jim): We will need to revisit this later.
if (type.startsWith("application/unity")) {
- const unityGameConfig = this.props.data.unityGameConfig;
- const unityGameLoader = this.props.data.unityGameLoader;
+ const { config, loader } = file.data.unity;
- return (
-
- );
+ return ;
}
return element;
diff --git a/components/core/SlateMediaObjectPreview.js b/components/core/SlateMediaObjectPreview.js
index e79b67c0..3a2a5169 100644
--- a/components/core/SlateMediaObjectPreview.js
+++ b/components/core/SlateMediaObjectPreview.js
@@ -69,7 +69,7 @@ const STYLES_BLUR_CONTAINER = css`
export default class SlateMediaObjectPreview extends React.Component {
static defaultProps = {
- charCap: 30,
+ charCap: 70,
};
state = {
@@ -78,39 +78,48 @@ export default class SlateMediaObjectPreview extends React.Component {
};
componentDidMount = () => {
- if (this.props.type && Validations.isPreviewableImage(this.props.type)) {
- this.loadImage(this.props.url);
- } else if (this.props.coverImage) {
- this.loadImage(this.props.coverImage.url);
- }
+ this.setImage();
};
componentDidUpdate = (prevProps) => {
- if (prevProps.coverImage?.url !== this.props.coverImage?.url && this.props.coverImage?.url) {
- this.loadImage(this.props.coverImage.url);
+ if (prevProps.coverImage?.cid !== this.props.coverImage?.cid) {
+ this.setImage();
}
};
- loadImage = async (url) => {
- const img = new Image();
- img.onload = () => this.setState({ showImage: true });
- img.src = url;
+ setImage = () => {
+ let type = this.props.file.data.type;
+ let coverImage = this.props.file.data.coverImage;
+ let url;
+ if (type && Validations.isPreviewableImage(type)) {
+ url = Strings.getURLfromCID(this.props.file.cid);
+ } else if (coverImage) {
+ url = Strings.getURLfromCID(coverImage.cid);
+ }
+ if (url) {
+ const img = new Image();
+ img.onload = () => this.setState({ showImage: true });
+ img.src = url;
+ }
};
render() {
+ const file = this.props.file;
+ const type = this.props.file.data.type;
+ const coverImage = this.props.file.data.coverImage;
let url;
- if (this.props.type && Validations.isPreviewableImage(this.props.type)) {
- url = this.props.url;
- } else if (this.props.coverImage) {
- url = this.props.coverImage.url;
+ if (type && Validations.isPreviewableImage(type)) {
+ url = Strings.getURLfromCID(this.props.file.cid);
+ } else if (coverImage) {
+ url = Strings.getURLfromCID(coverImage.cid);
}
if (url) {
- let blurhash =
- this.props.blurhash && isBlurhashValid(this.props.blurhash)
- ? this.props.blurhash
- : this.props.coverImage?.blurhash && isBlurhashValid(this.props.coverImage?.blurhash)
- ? this.props.coverImage?.blurhash
+ const blurhash =
+ file.data.blurhash && isBlurhashValid(file.data.blurhash)
+ ? file.data.blurhash
+ : coverImage?.data.blurhash && isBlurhashValid(coverImage?.data.blurhash)
+ ? coverImage?.data.blurhash
: null;
if (this.state.error) {
return (
@@ -177,23 +186,20 @@ export default class SlateMediaObjectPreview extends React.Component {
);
}
- const title = this.props.title;
- // this.props.title && this.props.title.length > this.props.charCap
- // ? this.props.title.substring(0, this.props.charCap) + "..."
- // : this.props.title;
- let extension = Strings.getFileExtension(this.props.title);
+ let name = (file.data.name || file.filename).substring(0, this.charCap);
+ let extension = Strings.getFileExtension(file.filename);
if (extension && extension.length) {
extension = extension.toUpperCase();
}
let element = (
);
- if (endsWithAny([".ttf", ".otf", ".woff", ".woff2"], this.props.title)) {
+ if (endsWithAny([".ttf", ".otf", ".woff", ".woff2"], file.filename)) {
return (
{element}
- {this.props.title && !this.props.iconOnly && !this.props.previewPanel ? (
+ {!this.props.iconOnly && !this.props.previewPanel ? (
-
{title}
+
{name}
{extension ? (
- {slate.data.public ? (
+ {slate.isPublic ? (
diff --git a/components/core/SlatePreviewBlock.js b/components/core/SlatePreviewBlock.js
index f5f0e231..ebe66e77 100644
--- a/components/core/SlatePreviewBlock.js
+++ b/components/core/SlatePreviewBlock.js
@@ -48,9 +48,10 @@ const STYLES_PLACEHOLDER = css`
export class SlatePreviewRow extends React.Component {
render() {
let numItems = this.props.numItems || 4;
- let objects;
- if (this.props.slate.data.objects.length === 0) {
- objects = [
+ let objects = this.props.slate.objects;
+ let components;
+ if (objects.length === 0) {
+ components = [
numItems
- ? this.props.slate.data.objects.slice(1, numItems)
- : this.props.slate.data.objects.slice(1, this.props.slate.data.objects.length);
- objects = trimmed.map((each) => (
+ objects.length > numItems ? objects.slice(1, numItems) : objects.slice(1, objects.length);
+ components = trimmed.map((each) => (
));
}
return (
- {objects}
+ {components}
);
}
@@ -251,11 +245,11 @@ export class SlatePreviewBlock extends React.Component {
render() {
let count = 0;
- const { objects } = this.props.slate.data;
- if (objects.length >= 4) {
- const set = this.props.slate.data.objects.slice(0, 4);
+ const objects = this.props.slate.objects || [];
+ if (objects && objects.length >= 4) {
+ const set = objects.slice(0, 4);
for (let object of set) {
- if (object.type.startsWith("image/") && !object.type.startsWith("image/svg")) {
+ if (object.data.type.startsWith("image/") && !object.data.type.startsWith("image/svg")) {
count++;
}
}
@@ -299,9 +293,9 @@ export class SlatePreviewBlock extends React.Component {
{this.props.slate.data.name}
- {this.props.isOwner && !this.props.isPublic && (
-
-
+ {this.props.isOwner && !this.props.slate.isPublic && (
+
+
)}
@@ -335,15 +329,7 @@ export class SlatePreviewBlock extends React.Component {
height: 320,
}}
>
-
+
) : first ? (
@@ -353,16 +339,7 @@ export class SlatePreviewBlock extends React.Component {
height: 320,
}}
>
-
+
{this.props.slate.data.name}
- {this.props.isOwner && (
+ {this.props.isOwner && !this.props.slate.isPublic && (
- {this.props.isPublic ? null : (
-
- )}
+
)}
@@ -409,13 +384,10 @@ export class SlatePreviewBlock extends React.Component {
>
{first ? (
) : (
))
@@ -489,7 +460,6 @@ export default class SlatePreviewBlocks extends React.Component {
username={this.props.username}
slate={slate}
external={this.props.external}
- isPublic={slate.data.public}
/>
))}
diff --git a/components/core/CircleButtonGray.js b/components/core/SquareButtonGray.js
similarity index 90%
rename from components/core/CircleButtonGray.js
rename to components/core/SquareButtonGray.js
index a2cfb484..437e4f8f 100644
--- a/components/core/CircleButtonGray.js
+++ b/components/core/SquareButtonGray.js
@@ -30,8 +30,8 @@ const STYLES_BUTTON = css`
}
`;
-export const CircleButtonGray = (props) => {
+export const SquareButtonGray = (props) => {
return
;
};
-export default CircleButtonGray;
+export default SquareButtonGray;
diff --git a/components/core/CircleButtonLight.js b/components/core/SquareButtonLight.js
similarity index 89%
rename from components/core/CircleButtonLight.js
rename to components/core/SquareButtonLight.js
index 9864631a..523ce8ae 100644
--- a/components/core/CircleButtonLight.js
+++ b/components/core/SquareButtonLight.js
@@ -25,8 +25,8 @@ const STYLES_BUTTON = css`
}
`;
-export const CircleButtonLight = (props) => {
+export const SquareButtonLight = (props) => {
return
;
};
-export default CircleButtonLight;
+export default SquareButtonLight;
diff --git a/components/sidebars/SidebarAddFileToSlate.js b/components/sidebars/SidebarAddFileToSlate.js
index aeb6c20e..86bc1027 100644
--- a/components/sidebars/SidebarAddFileToSlate.js
+++ b/components/sidebars/SidebarAddFileToSlate.js
@@ -61,7 +61,6 @@ export default class SidebarAddFileToSlate extends React.Component {
await UserBehaviors.addToSlate({
slate,
files: this.props.sidebarData.files,
- fromSlate: this.props.sidebarData.fromSlate,
});
}
};
diff --git a/components/sidebars/SidebarCreateSlate.js b/components/sidebars/SidebarCreateSlate.js
index 8589cfcb..7c8b4bcf 100644
--- a/components/sidebars/SidebarCreateSlate.js
+++ b/components/sidebars/SidebarCreateSlate.js
@@ -10,8 +10,6 @@ import * as SVG from "~/common/svg";
import { RadioGroup } from "~/components/system/components/RadioGroup";
import { css } from "@emotion/react";
-const SLATE_LIMIT = 50;
-
const STYLES_TEXT = css`
color: ${Constants.system.textGray};
font-size: ${Constants.typescale.lvl0};
@@ -33,7 +31,7 @@ const STYLES_GROUPING = css`
export default class SidebarCreateSlate extends React.Component {
state = {
name: "",
- public: true,
+ isPublic: true,
body: "",
tags: [],
suggestions: this.props.viewer?.tags || [],
@@ -41,11 +39,6 @@ export default class SidebarCreateSlate extends React.Component {
};
_handleSubmit = async () => {
- if (this.props.viewer.slates.length >= SLATE_LIMIT) {
- Events.dispatchMessage({ message: `You have reached the limit of ${SLATE_LIMIT} Slates!` });
- return;
- }
-
this.setState({ loading: true });
if (!Validations.slatename(this.state.name)) {
@@ -56,7 +49,7 @@ export default class SidebarCreateSlate extends React.Component {
const response = await Actions.createSlate({
name: this.state.name,
- public: this.state.public,
+ isPublic: this.state.isPublic,
body: this.state.body,
tags: this.state.tags,
});
@@ -67,13 +60,9 @@ export default class SidebarCreateSlate extends React.Component {
}
if (this.props.sidebarData && this.props.sidebarData.files) {
- let data = this.props.sidebarData.files.map((file) => {
- return { title: file.title || file.name, ...file };
- });
const addResponse = await Actions.addFileToSlate({
slate: response.slate,
- data,
- fromSlate: this.props.sidebarData.fromSlate,
+ files: this.props.sidebarData.files,
});
if (Events.hasError(addResponse)) {
@@ -213,7 +202,7 @@ export default class SidebarCreateSlate extends React.Component {
on the internet. If you make it private, only you will be able to see it.
diff --git a/components/sidebars/SidebarEditTags.js b/components/sidebars/SidebarEditTags.js
index bbae9c1c..77b7b914 100644
--- a/components/sidebars/SidebarEditTags.js
+++ b/components/sidebars/SidebarEditTags.js
@@ -77,7 +77,7 @@ export default class SidebarEditTags extends React.Component {
return { id: this.props.viewer.id, data: objects[checkedIndex] };
});
- const response = await Actions.updateData(update);
+ const response = await Actions.updateFile(update);
Events.hasError(response);
};
diff --git a/components/sidebars/SidebarFileStorageDeal.js b/components/sidebars/SidebarFileStorageDeal.js
index 2fbc61e7..20ca4ae0 100644
--- a/components/sidebars/SidebarFileStorageDeal.js
+++ b/components/sidebars/SidebarFileStorageDeal.js
@@ -41,7 +41,7 @@ export default class SidebarFileStorageDeal extends React.Component {
};
async componentDidMount() {
- if (!this.props.viewer.settings_deals_auto_approve) {
+ if (!this.props.viewer.settings?.settings_deals_auto_approve) {
return null;
}
diff --git a/components/sidebars/SidebarSingleSlateSettings.js b/components/sidebars/SidebarSingleSlateSettings.js
index 6ce77e9e..2b7ee3f0 100644
--- a/components/sidebars/SidebarSingleSlateSettings.js
+++ b/components/sidebars/SidebarSingleSlateSettings.js
@@ -47,7 +47,7 @@ const STYLES_GROUPING = css`
export default class SidebarSingleSlateSettings extends React.Component {
state = {
slatename: this.props.data.slatename,
- public: this.props.data.data.public,
+ isPublic: this.props.data.isPublic,
body: this.props.data.data.body,
name: this.props.data.data.name,
tags: this.props.data.data?.tags || [],
@@ -68,7 +68,7 @@ export default class SidebarSingleSlateSettings extends React.Component {
for (let slate of slates) {
if (slate.id === this.props.data.id) {
slate.data.name = this.state.name;
- slate.data.public = this.state.public;
+ slate.isPublic = this.state.isPublic;
slate.data.body = this.state.body;
slate.data.tags = this.state.tags;
@@ -82,9 +82,9 @@ export default class SidebarSingleSlateSettings extends React.Component {
this.props.onCancel();
const response = await Actions.updateSlate({
id: this.props.data.id,
+ isPublic: this.state.isPublic,
data: {
name: this.state.name,
- public: this.state.public,
body: this.state.body,
tags: this.state.tags,
},
@@ -100,6 +100,7 @@ export default class SidebarSingleSlateSettings extends React.Component {
};
_handleChange = (e) => {
+ console.log("inside single slate settings toggle privacy");
this.setState({ [e.target.name]: e.target.value });
if (e.target.name === "tags") {
@@ -135,14 +136,14 @@ export default class SidebarSingleSlateSettings extends React.Component {
const url = `/${this.props.viewer.username}/${slug}`;
let preview = this.props.data.data.preview;
if (!preview) {
- for (let object of this.props.data.data.objects) {
+ for (let object of this.props.data.objects) {
if (
- object.type &&
- Validations.isPreviewableImage(object.type) &&
- object.size &&
- object.size < SIZE_LIMIT
+ object.data.type &&
+ Validations.isPreviewableImage(object.data.type) &&
+ object.data.size &&
+ object.data.size < SIZE_LIMIT
) {
- preview = object.url;
+ preview = Strings.getURLfromCID(object.cid);
break;
}
}
@@ -228,7 +229,6 @@ export default class SidebarSingleSlateSettings extends React.Component {
- {this.state.public ? (
-
-
Preview image
+
+
Cover image
-
- This is the image that shows when you share a link to your slate.
-
+
+ This is the cover image for your slate. You can select a different cover image using the
+ "Make cover image" button.
+
-
-
-
+
+
- ) : null}
+
@@ -269,7 +268,7 @@ export default class SidebarSingleSlateSettings extends React.Component {
on the internet. If you make it private, only you will be able to see it.
diff --git a/components/system/components/GlobalCarousel.js b/components/system/components/GlobalCarousel.js
index 809a0b43..1661f353 100644
--- a/components/system/components/GlobalCarousel.js
+++ b/components/system/components/GlobalCarousel.js
@@ -8,8 +8,7 @@ import * as Events from "~/common/custom-events";
import { css } from "@emotion/react";
import { Alert } from "~/components/core/Alert";
-import CarouselSidebarSlate from "~/components/core/CarouselSidebarSlate";
-import CarouselSidebarData from "~/components/core/CarouselSidebarData";
+import CarouselSidebar from "~/components/core/CarouselSidebar";
import SlateMediaObject from "~/components/core/SlateMediaObject";
const STYLES_ROOT = css`
@@ -27,7 +26,9 @@ const STYLES_ROOT = css`
z-index: ${Constants.zindex.modal};
background-color: rgba(0, 0, 0, 0.8);
- // Note(Amine): we're using the blur filter to fix a weird backdrop-filter's bug in chrome
+ ${
+ "" /* Note(Amine): we're using the blur filter to fix a weird backdrop-filter's bug in chrome */
+ }
filter: blur(0px);
@supports ((-webkit-backdrop-filter: blur(15px)) or (backdrop-filter: blur(15px))) {
-webkit-backdrop-filter: blur(15px);
@@ -134,8 +135,8 @@ export class GlobalCarousel extends React.Component {
componentDidUpdate = (prevProps) => {
if (
- !this.props.objects?.length ||
- this.state.index < 0 ||
+ !this.props.objects ||
+ this.props.objects.length == 0 ||
this.state.index >= this.props.objects.length
) {
this._handleClose();
@@ -144,15 +145,15 @@ export class GlobalCarousel extends React.Component {
_handleKeyDown = (e) => {
const inputs = document.querySelectorAll("input");
- for (let i = 0; i < inputs.length; i++) {
- if (document.activeElement === inputs[i]) {
+ for (let elem of inputs) {
+ if (document.activeElement === elem) {
return;
}
}
const textareas = document.querySelectorAll("textarea");
- for (let i = 0; i < textareas.length; i++) {
- if (document.activeElement === textareas[i]) {
+ for (let elem of textareas) {
+ if (document.activeElement === elem) {
return;
}
}
@@ -172,69 +173,55 @@ export class GlobalCarousel extends React.Component {
}
};
- setWindowState = (data) => {
+ setWindowState = (data = {}) => {
+ const cid = data?.cid;
if (this.props.carouselType === "ACTIVITY") {
window.history.replaceState(
- { ...window.history.state, cid: data && data.cid },
+ { ...window.history.state, cid: cid },
null,
- data && data.cid
- ? `/${data.owner}/${data.slate.slatename}/cid:${data.cid}`
- : `/_?scene=NAV_ACTIVITY`
+ cid ? `/${data.owner}/${data.slate.slatename}/cid:${cid}` : `/_?scene=NAV_ACTIVITY`
);
-
return;
}
let baseURL = window.location.pathname.split("/");
-
if (this.props.carouselType === "SLATE") {
baseURL.length = 3;
- baseURL = baseURL.join("/");
- window.history.replaceState(
- { ...window.history.state, cid: data && data.cid },
- null,
- data && data.cid ? `${baseURL}/cid:${data.cid}` : baseURL
- );
- return;
- }
-
- if (this.props.carouselType === "PROFILE") {
+ } else if (this.props.carouselType === "PROFILE") {
baseURL.length = 2;
- baseURL = baseURL.join("/");
- window.history.replaceState(
- { ...window.history.state, cid: data && data.cid },
- null,
- data && data.cid ? `${baseURL}/cid:${data.cid}` : baseURL
- );
- return;
- }
-
- if (this.props.carouselType === "DATA") {
+ } else if (this.props.carouselType === "DATA") {
baseURL.length = 2;
- if (data && data.cid) {
+ if (cid) {
baseURL[1] = this.props.viewer.username;
} else {
- baseURL[1] = "_";
+ baseURL[1] = "_?scene=NAV_DATA";
}
- baseURL = baseURL.join("/");
- window.history.replaceState(
- { ...window.history.state, cid: data && data.cid },
- null,
- data && data.cid ? `${baseURL}/cid:${data.cid}` : baseURL
- );
- return;
}
+ baseURL = baseURL.join("/");
+
+ window.history.replaceState(
+ { ...window.history.state, cid: cid },
+ null,
+ cid ? `${baseURL}/cid:${cid}` : baseURL
+ );
};
_handleOpen = (e) => {
- if (e.detail.index < 0 || e.detail.index >= this.props.objects.length) {
+ let index = e.detail.index;
+ const objects = this.props.objects;
+ if (e.detail.index === null) {
+ if (e.detail.id !== null) {
+ index = objects.findIndex((obj) => obj.id === e.detail.id);
+ }
+ }
+ if (index === null || index < 0 || index >= objects.length) {
return;
}
this.setState({
visible: true,
- index: e.detail.index || 0,
+ index: e.detail.index,
});
- const data = this.props.objects[e.detail.index];
+ const data = objects[e.detail.index];
this.setWindowState(data);
};
@@ -245,15 +232,17 @@ export class GlobalCarousel extends React.Component {
e.preventDefault();
}
this.setState({ visible: false, index: 0 });
-
this.setWindowState();
}
};
- _handleNext = () => {
+ _handleNext = (e) => {
+ if (e) {
+ e.stopPropagation();
+ }
let index = this.state.index + 1;
if (index >= this.props.objects.length) {
- index = 0;
+ return;
}
this.setState({ index });
@@ -261,10 +250,13 @@ export class GlobalCarousel extends React.Component {
this.setWindowState(data);
};
- _handlePrevious = () => {
+ _handlePrevious = (e) => {
+ if (e) {
+ e.stopPropagation();
+ }
let index = this.state.index - 1;
if (index < 0) {
- index = this.props.objects.length - 1;
+ return;
}
this.setState({ index });
@@ -272,51 +264,40 @@ export class GlobalCarousel extends React.Component {
this.setWindowState(data);
};
- _handleSave = async (details, index) => {
- let objects = this.props.objects;
- if (!this.props.isOwner || this.props.external) return;
- if (this.props.carouselType === "SLATE") {
- objects[index] = { ...objects[index], ...details };
- const response = await Actions.updateSlate({
- id: this.props.current.id,
- data: { objects },
- });
- Events.hasError(response);
- }
- if (this.props.carouselType === "DATA") {
- objects[index] = { ...objects[index], ...details };
- const response = await Actions.updateData({
- id: this.props.viewer.id,
- data: objects[index],
- });
- Events.hasError(response);
+ _handleToggleSidebar = (e) => {
+ if (e) {
+ e.stopPropagation();
}
+ this.setState({ showSidebar: !this.state.showSidebar });
};
render() {
- if (!this.state.visible || !this.props.carouselType || this.state.index < 0) {
+ if (
+ !this.state.visible ||
+ !this.props.carouselType ||
+ this.state.index < 0 ||
+ this.state.index >= this.props.objects.length
+ ) {
return null;
}
let data = this.props.objects[this.state.index];
- let isOwner = this.props.isOwner;
- let isRepost;
+ let { isMobile, isOwner } = this.props;
+
+ let isRepost = false;
if (this.props.carouselType === "SLATE") {
- isRepost = this.props.external ? false : this.props.current.data.ownerId !== data.ownerId;
- } else if (this.props.carouselType === "DATA" || this.props.carouselType === "PROFILE") {
- data.url = Strings.getCIDGatewayURL(data.cid);
+ isRepost = this.props.current?.ownerId !== data.ownerId;
}
- let { mobile } = this.props;
- let slide =
;
+ let slide =
;
return (
-
{
- e.stopPropagation();
- this._handlePrevious(e);
- }}
- style={{ top: 0, left: 16, bottom: 0 }}
- >
-
-
-
{
- e.stopPropagation();
- this._handleNext(e);
- }}
- style={{ top: 0, right: 16, bottom: 0 }}
- >
-
-
+ {this.state.index > 0 && (
+
+
+
+ )}
+ {this.state.index < this.props.objects.length - 1 && (
+
+
+
+ )}
{slide}
@@ -355,24 +334,12 @@ export class GlobalCarousel extends React.Component {
{this.state.showSidebar ? (
- {
- e.stopPropagation();
- this.setState({ showSidebar: !this.state.showSidebar });
- }}
- >
+
) : (
-
{
- e.stopPropagation();
- this.setState({ showSidebar: !this.state.showSidebar });
- }}
- >
+
@@ -383,42 +350,14 @@ export class GlobalCarousel extends React.Component {
- {this.props.carouselType === "DATA" || this.props.carouselType === "PROFILE" ? (
-
- ) : (
-
- )}
+
);
diff --git a/components/system/components/RadioGroup.js b/components/system/components/RadioGroup.js
index 0152afd5..6a47db05 100644
--- a/components/system/components/RadioGroup.js
+++ b/components/system/components/RadioGroup.js
@@ -102,14 +102,25 @@ export class RadioGroup extends React.Component {
return (
{radio.label}
-
-
+
+
{
diff --git a/components/system/components/fragments/Boundary.js b/components/system/components/fragments/Boundary.js
index 2cc30eb4..92d64cc3 100644
--- a/components/system/components/fragments/Boundary.js
+++ b/components/system/components/fragments/Boundary.js
@@ -98,7 +98,6 @@ export class Boundary extends React.PureComponent {
};
_handleOutsideRectEvent = (e) => {
- // console.log("outside rect event");
this.props.onOutsideRectEvent(e);
};
diff --git a/components/system/modules/CreateFilecoinStorageDeal.js b/components/system/modules/CreateFilecoinStorageDeal.js
index 64973169..1ac383f9 100644
--- a/components/system/modules/CreateFilecoinStorageDeal.js
+++ b/components/system/modules/CreateFilecoinStorageDeal.js
@@ -81,12 +81,12 @@ export class CreateFilecoinStorageDeal extends React.Component {
{this.state.file ? (
-
{this.state.file.name}
+
{this.state.file.data.name}
Name
-
{this.state.file.size}
+
{this.state.file.data.size}
File size
diff --git a/components/system/modules/FriendsList.js b/components/system/modules/FriendsList.js
index 1f33c8f7..4e1be0fe 100644
--- a/components/system/modules/FriendsList.js
+++ b/components/system/modules/FriendsList.js
@@ -7,7 +7,7 @@ import { css } from "@emotion/react";
import { Table } from "~/components/system/components/Table";
import { StatUpload, StatDownload } from "~/components/system/components/Stat";
-let genericImg = Strings.getCIDGatewayURL(
+let genericImg = Strings.getURLfromCID(
"bafybeiblly23jomdjjiq7ilth667npcfm5llqb5xfstodbbfa5pxtoek7u"
);
diff --git a/node_common/data/index.js b/node_common/data/index.js
index 60c5b721..c6a12ccf 100644
--- a/node_common/data/index.js
+++ b/node_common/data/index.js
@@ -2,15 +2,28 @@
// User postgres queries
import createUser from "~/node_common/data/methods/create-user";
import updateUserById from "~/node_common/data/methods/update-user-by-id";
-import deleteUserByUsername from "~/node_common/data/methods/delete-user-by-username";
+import deleteUserById from "~/node_common/data/methods/delete-user-by-id";
import getUserByUsername from "~/node_common/data/methods/get-user-by-username";
import getUserById from "~/node_common/data/methods/get-user-by-id";
//NOTE(martina):
-// Pending user upload queries
-import getPendingDataForUserId from "~/node_common/data/methods/get-pending-data-for-user-id";
-import deletePendingDataByUserId from "~/node_common/data/methods/delete-pending-data-by-user-id";
-import createPendingData from "~/node_common/data/methods/create-pending-data";
+// File postgres queries
+import createFile from "~/node_common/data/methods/create-file";
+import getFileByCid from "~/node_common/data/methods/get-file-by-cid";
+import getFilesByCids from "~/node_common/data/methods/get-files-by-cids";
+import getFileById from "~/node_common/data/methods/get-file-by-id";
+import getFilesByIds from "~/node_common/data/methods/get-files-by-ids";
+import getFilesByUserId from "~/node_common/data/methods/get-files-by-user-id";
+import deleteFilesByIds from "~/node_common/data/methods/delete-files-by-ids";
+import deleteFilesByUserId from "~/node_common/data/methods/delete-files-by-user-id";
+import updateFileById from "~/node_common/data/methods/update-file-by-id";
+import updateFilePrivacy from "~/node_common/data/methods/update-file-privacy";
+
+//NOTE(martina):
+// Slate file postgres queries
+import createSlateFiles from "~/node_common/data/methods/create-slate-files";
+import deleteSlateFiles from "~/node_common/data/methods/delete-slate-files";
+import getSlateFilesByCids from "~/node_common/data/methods/get-slate-files-by-cids";
// NOTE(jim):
// Slate postgres queries
@@ -19,16 +32,15 @@ import getSlateByName from "~/node_common/data/methods/get-slate-by-name";
import getSlateById from "~/node_common/data/methods/get-slate-by-id";
import getSlatesByUserId from "~/node_common/data/methods/get-slates-by-user-id";
import getSlatesByIds from "~/node_common/data/methods/get-slates-by-ids";
-import getSlateObjectsByCID from "~/node_common/data/methods/get-slate-objects-by-cid";
import updateSlateById from "~/node_common/data/methods/update-slate-by-id";
-import deleteSlatesForUserId from "~/node_common/data/methods/delete-slates-for-user-id";
+import updateSlatePrivacy from "~/node_common/data/methods/update-slate-privacy";
+import deleteSlatesByUserId from "~/node_common/data/methods/delete-slates-by-user-id";
import deleteSlateById from "~/node_common/data/methods/delete-slate-by-id";
// NOTE(jim):
// API postgres queries
-import createAPIKeyForUserId from "~/node_common/data/methods/create-api-key-for-user-id";
+import createAPIKey from "~/node_common/data/methods/create-api-key";
import deleteAPIKeyById from "~/node_common/data/methods/delete-api-key-by-id";
-import deleteAPIKeysForUserId from "~/node_common/data/methods/delete-api-keys-for-user-id";
import getAPIKey from "~/node_common/data/methods/get-api-key";
import getAPIKeyByKey from "~/node_common/data/methods/get-api-key-by-key";
import getAPIKeysByUserId from "~/node_common/data/methods/get-api-keys-by-user-id";
@@ -36,107 +48,83 @@ import getAPIKeysByUserId from "~/node_common/data/methods/get-api-keys-by-user-
// NOTE(jim):
// Subscription postgres queries
import createSubscription from "~/node_common/data/methods/create-subscription";
-import getSubscriptionById from "~/node_common/data/methods/get-subscription-by-id";
+import getSubscription from "~/node_common/data/methods/get-subscription";
+import getSubscribersBySlateId from "~/node_common/data/methods/get-subscribers-by-slate-id";
import getSubscriptionsByUserId from "~/node_common/data/methods/get-subscriptions-by-user-id";
-import getSubscriptionsToUserId from "~/node_common/data/methods/get-subscriptions-to-user-id";
-import getSubscriptionsToSlateId from "~/node_common/data/methods/get-subscriptions-to-slate-id";
-import getSubscribersByUserId from "~/node_common/data/methods/get-subscribers-by-user-id";
+import getFollowersByUserId from "~/node_common/data/methods/get-followers-by-user-id";
+import getFollowingByUserId from "~/node_common/data/methods/get-following-by-user-id";
import deleteSubscriptionById from "~/node_common/data/methods/delete-subscription-by-id";
-// NOTE(jim):
-// Trust postgres queries
-import createTrustedRelationship from "~/node_common/data/methods/create-trusted-relationship";
-import updateTrustedRelationshipById from "~/node_common/data/methods/update-trusted-relationship-by-id";
-import getTrustedRelationshipsByUserId from "~/node_common/data/methods/get-trusted-relationships-by-user-id";
-import getPendingTrustedRelationshipsByUserId from "~/node_common/data/methods/get-pending-trusted-relationships-by-user-id";
-import getTrustedRelationshipByUserIds from "~/node_common/data/methods/get-trusted-relationship-by-ids";
-import getTrustedRelationshipById from "~/node_common/data/methods/get-trusted-relationship-by-id";
-import deleteTrustedRelationshipById from "~/node_common/data/methods/delete-trusted-relationship-by-id";
-
// NOTE(jim):
// Activity postgres queries
import createActivity from "~/node_common/data/methods/create-activity";
-import getActivityForUserId from "~/node_common/data/methods/get-activity-for-user-id";
-import getActivityForSlateId from "~/node_common/data/methods/get-activity-for-slate-id";
-import getActivityById from "~/node_common/data/methods/get-activity-by-id";
-import deleteActivityById from "~/node_common/data/methods/delete-activity-by-id";
+import getActivity from "~/node_common/data/methods/get-activity";
+import getExplore from "~/node_common/data/methods/get-explore";
// NOTE(jim):
// Search postgres queries
-import querySlates from "~/node_common/data/methods/query-slates";
-import queryUsers from "~/node_common/data/methods/query-users";
import getEverySlate from "~/node_common/data/methods/get-every-slate";
import getEveryUser from "~/node_common/data/methods/get-every-user";
+import getEveryFile from "~/node_common/data/methods/get-every-file";
// NOTE(jim):
// one-offs
-import getAllStats from "~/node_common/data/methods/get-all-stats";
-import getAllDeals from "~/node_common/data/methods/get-all-deals";
-import getAllActivity from "~/node_common/data/methods/get-all-activity";
-import createOrUpdateStats from "~/node_common/data/methods/create-or-update-stats";
-import getOrCreateGlobalStats from "~/node_common/data/methods/get-or-create-global-stats";
import createOrphan from "~/node_common/data/methods/create-orphan";
export {
// NOTE(jim): One-offs
- createOrUpdateStats,
- getOrCreateGlobalStats,
createOrphan,
- getAllDeals,
- getAllActivity,
- getAllStats,
// NOTE(jim): User operations
createUser,
updateUserById,
- deleteUserByUsername,
+ deleteUserById,
getUserByUsername,
getUserById,
- // NOTE(martina): Pending user upload operations
- getPendingDataForUserId,
- deletePendingDataByUserId,
- createPendingData,
+ //NOTE(martina): File operations
+ createFile,
+ getFileByCid,
+ getFilesByCids,
+ getFileById,
+ getFilesByIds,
+ getFilesByUserId,
+ deleteFilesByIds,
+ deleteFilesByUserId,
+ updateFileById,
+ updateFilePrivacy,
+ //NOTE(martina): Slate file operations
+ createSlateFiles,
+ deleteSlateFiles,
+ getSlateFilesByCids,
// NOTE(jim): Slate operations
createSlate,
getSlateByName,
getSlateById,
getSlatesByUserId,
getSlatesByIds,
- getSlateObjectsByCID,
updateSlateById,
- deleteSlatesForUserId,
+ updateSlatePrivacy,
+ deleteSlatesByUserId,
deleteSlateById,
// NOTE(jim): API key operations
- createAPIKeyForUserId,
+ createAPIKey,
deleteAPIKeyById,
- deleteAPIKeysForUserId,
getAPIKey,
getAPIKeyByKey,
getAPIKeysByUserId,
// NOTE(jim): Subscription operations
createSubscription,
- getSubscriptionById,
+ getSubscription,
+ getSubscribersBySlateId,
getSubscriptionsByUserId,
- getSubscriptionsToSlateId,
- getSubscriptionsToUserId,
- getSubscribersByUserId,
+ getFollowersByUserId,
+ getFollowingByUserId,
deleteSubscriptionById,
- // NOTE(jim): Trust operations
- createTrustedRelationship,
- updateTrustedRelationshipById,
- getPendingTrustedRelationshipsByUserId,
- getTrustedRelationshipsByUserId,
- getTrustedRelationshipByUserIds,
- getTrustedRelationshipById,
- deleteTrustedRelationshipById,
// NOTE(jim): Activity operations
createActivity,
- getActivityForUserId,
- getActivityForSlateId,
- getActivityById,
- deleteActivityById,
+ getActivity,
+ getExplore,
// NOTE(jim): Search
- queryUsers,
- querySlates,
getEverySlate,
getEveryUser,
+ getEveryFile,
};
diff --git a/node_common/data/methods/create-activity.js b/node_common/data/methods/create-activity.js
index 9281b4ff..39f2cacc 100644
--- a/node_common/data/methods/create-activity.js
+++ b/node_common/data/methods/create-activity.js
@@ -1,20 +1,20 @@
import { runQuery } from "~/node_common/data/utilities";
-export default async ({ slateId, userId, data }) => {
+//NOTE(martina): can be single activity item (an object) or multiple activity items (an array of objects)
+export default async (activityItems) => {
return await runQuery({
label: "CREATE_ACTIVITY",
queryFn: async (DB) => {
- const query = await DB.insert({
- owner_slate_id: slateId,
- owner_user_id: userId,
- data,
- })
- .into("activity")
- .returning("*");
+ //TODO(martina): optimization. check for whether something with the same file exists already, so we don't repeat frequently
+ let query = await DB.insert(activityItems).into("activity").returning("*");
- const index = query ? query.pop() : null;
- index.type = "ACTIVITY";
- return JSON.parse(JSON.stringify(index));
+ if (!query) {
+ return null;
+ }
+ if (!Array.isArray(activityItems)) {
+ query = query.pop();
+ }
+ return JSON.parse(JSON.stringify(query));
},
errorFn: async (e) => {
return {
diff --git a/node_common/data/methods/create-api-key-for-user-id.js b/node_common/data/methods/create-api-key.js
similarity index 72%
rename from node_common/data/methods/create-api-key-for-user-id.js
rename to node_common/data/methods/create-api-key.js
index 9fd497e4..1412595d 100644
--- a/node_common/data/methods/create-api-key-for-user-id.js
+++ b/node_common/data/methods/create-api-key.js
@@ -2,10 +2,10 @@ import { runQuery } from "~/node_common/data/utilities";
export default async ({ userId, key, level = 1 }) => {
return await runQuery({
- label: "CREATE_API_KEY_FOR_USER_ID",
+ label: "CREATE_API_KEY",
queryFn: async (DB) => {
const query = await DB.insert({
- owner_id: userId,
+ ownerId: userId,
level,
key,
})
@@ -13,13 +13,12 @@ export default async ({ userId, key, level = 1 }) => {
.returning("*");
const index = query ? query.pop() : null;
- index.type = "API_KEY";
- return index;
+ return JSON.parse(JSON.stringify(index));
},
errorFn: async (e) => {
return {
error: true,
- decorator: "CREATE_API_KEY_FOR_USER_ID",
+ decorator: "CREATE_API_KEY",
};
},
});
diff --git a/node_common/data/methods/create-file.js b/node_common/data/methods/create-file.js
new file mode 100644
index 00000000..8b993b47
--- /dev/null
+++ b/node_common/data/methods/create-file.js
@@ -0,0 +1,30 @@
+import * as Serializers from "~/node_common/serializers";
+
+import { runQuery } from "~/node_common/data/utilities";
+
+//NOTE(martina): remember to include an ownerId for the file
+export default async (files) => {
+ const cleanedFiles = files.map((file) => Serializers.cleanFile(file));
+
+ return await runQuery({
+ label: "CREATE_FILE",
+ queryFn: async (DB) => {
+ let query = await DB.insert(cleanedFiles).into("files").returning("*");
+
+ if (!query) {
+ return null;
+ }
+
+ if (!Array.isArray(files)) {
+ query = query.pop();
+ }
+ return JSON.parse(JSON.stringify(query));
+ },
+ errorFn: async (e) => {
+ return {
+ error: true,
+ decorator: "CREATE_FILE",
+ };
+ },
+ });
+};
diff --git a/node_common/data/methods/create-or-update-stats.js b/node_common/data/methods/create-or-update-stats.js
deleted file mode 100644
index 31963fdd..00000000
--- a/node_common/data/methods/create-or-update-stats.js
+++ /dev/null
@@ -1,88 +0,0 @@
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async (date, data) => {
- return await runQuery({
- label: "CREATE_OR_UPDATE_STATS",
- queryFn: async (DB) => {
- date.setHours(0, 0, 0, 0);
-
- let end = new Date();
- end.setHours(23, 59, 59, 999);
-
- const query = await DB.select("*")
- .from("stats")
- .where("created_at", ">=", date)
- .where("created_at", "<", end)
- .first();
-
- if (query && query.id) {
- let updates = { ...query.data };
-
- if (data.deals) {
- updates.deals = updates.deals + data.deals;
- }
-
- if (data.users) {
- updates.users = updates.users + data.users;
- }
-
- if (data.slates) {
- updates.slates = updates.slates + data.slates;
- }
-
- if (data.objects) {
- updates.objects = updates.objects + data.objects;
- }
-
- if (data.subscribeUser) {
- updates.subscribeUsers = updates.subscribeUsers + data.subscribeUser;
- }
-
- if (data.subscribeSlate) {
- updates.subscribeSlates = updates.subscribeSlates + data.subscribeSlate;
- }
-
- const changes = await DB.from("stats")
- .where("id", query.id)
- .update({ data: updates })
- .returning("*");
-
- if (!changes || changes.error) {
- return null;
- }
-
- const updateIndex = changes ? changes.pop() : null;
- return updateIndex;
- }
-
- const insert = await DB.insert({
- created_at: date,
- data: {
- deals: 0,
- users: 0,
- slates: 0,
- objects: 0,
- subscribeUsers: 0,
- subscribeSlates: 0,
- ...data,
- },
- })
- .into("stats")
- .returning("*");
- const index = insert ? insert.pop() : null;
-
- if (!index) {
- return null;
- }
-
- return JSON.parse(JSON.stringify(index));
- },
- errorFn: async (e) => {
- console.log(e);
- return {
- error: true,
- decorator: "CREATE_OR_UPDATE_STATS",
- };
- },
- });
-};
diff --git a/node_common/data/methods/create-orphan.js b/node_common/data/methods/create-orphan.js
index 7df69c47..a5b4fd3b 100644
--- a/node_common/data/methods/create-orphan.js
+++ b/node_common/data/methods/create-orphan.js
@@ -5,7 +5,7 @@ export default async ({ data }) => {
label: "CREATE_ORPHAN",
queryFn: async (DB) => {
const query = await DB.insert({
- created_at: new Date(),
+ createdAt: new Date(),
data,
})
.into("orphans")
diff --git a/node_common/data/methods/create-pending-data.js b/node_common/data/methods/create-pending-data.js
deleted file mode 100644
index 224f8044..00000000
--- a/node_common/data/methods/create-pending-data.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async ({ data, owner_user_id }) => {
- return await runQuery({
- label: "CREATE_PENDING_DATA",
- queryFn: async (DB) => {
- const query = await DB.insert({
- data,
- owner_user_id,
- })
- .into("pending")
- .returning("*");
-
- const index = query ? query.pop() : null;
- return index;
- },
- errorFn: async (e) => {
- return {
- error: true,
- decorator: "CREATE_PENDING_DATA",
- };
- },
- });
-};
diff --git a/node_common/data/methods/create-slate-files.js b/node_common/data/methods/create-slate-files.js
new file mode 100644
index 00000000..adab355e
--- /dev/null
+++ b/node_common/data/methods/create-slate-files.js
@@ -0,0 +1,23 @@
+import { runQuery } from "~/node_common/data/utilities";
+
+//NOTE(martina): this is the endpoint used when adding an existing file to a slate. Creates a slate_files entry
+export default async (slateFiles) => {
+ return await runQuery({
+ label: "CREATE_SLATE_FILES",
+ queryFn: async (DB) => {
+ const query = await DB.insert(slateFiles).into("slate_files").returning("*");
+
+ if (!query) {
+ return null;
+ }
+
+ return JSON.parse(JSON.stringify(query));
+ },
+ errorFn: async (e) => {
+ return {
+ error: true,
+ decorator: "CREATE_SLATE_FILES",
+ };
+ },
+ });
+};
diff --git a/node_common/data/methods/create-slate.js b/node_common/data/methods/create-slate.js
index b36a5831..4a7d707e 100644
--- a/node_common/data/methods/create-slate.js
+++ b/node_common/data/methods/create-slate.js
@@ -1,19 +1,20 @@
import { runQuery } from "~/node_common/data/utilities";
-export default async ({ slatename, data = {} }) => {
+export default async ({ ownerId, slatename, isPublic, data = {} }) => {
return await runQuery({
label: "CREATE_SLATE",
queryFn: async (DB) => {
const query = await DB.insert({
+ ownerId,
slatename,
+ isPublic,
data,
})
.into("slates")
.returning("*");
const index = query ? query.pop() : null;
- index.type = "SLATE";
- return index;
+ return JSON.parse(JSON.stringify(index));
},
errorFn: async (e) => {
return {
diff --git a/node_common/data/methods/create-subscription.js b/node_common/data/methods/create-subscription.js
index 4523c909..0fa3e5db 100644
--- a/node_common/data/methods/create-subscription.js
+++ b/node_common/data/methods/create-subscription.js
@@ -1,19 +1,23 @@
import { runQuery } from "~/node_common/data/utilities";
-export default async ({ subscriberUserId, slateId, userId }) => {
+export default async ({ ownerId, slateId, userId }) => {
return await runQuery({
label: "CREATE_SUBSCRIPTION",
queryFn: async (DB) => {
+ console.log({
+ ownerId,
+ slateId,
+ userId,
+ });
const query = await DB.insert({
- owner_user_id: subscriberUserId,
- target_slate_id: slateId,
- target_user_id: userId,
+ ownerId,
+ slateId,
+ userId,
})
.into("subscriptions")
.returning("*");
const index = query ? query.pop() : null;
- index.type = "SUBSCRIPTION";
return JSON.parse(JSON.stringify(index));
},
errorFn: async (e) => {
diff --git a/node_common/data/methods/create-trusted-relationship.js b/node_common/data/methods/create-trusted-relationship.js
deleted file mode 100644
index 1912fb94..00000000
--- a/node_common/data/methods/create-trusted-relationship.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async ({ ownerUserId, targetUserId }) => {
- return await runQuery({
- label: "CREATE_TRUSTED_RELATIONSHIP",
- queryFn: async (DB) => {
- const query = await DB.insert({
- owner_user_id: ownerUserId,
- target_user_id: targetUserId,
- data: { verified: false },
- })
- .into("trusted")
- .returning("*");
-
- const index = query ? query.pop() : null;
- index.type = "TRUSTED_RELATIONSHIP";
- return JSON.parse(JSON.stringify(index));
- },
- errorFn: async (e) => {
- return {
- error: true,
- decorator: "CREATE_TRUSTED_RELATIONSHIP",
- };
- },
- });
-};
diff --git a/node_common/data/methods/create-user.js b/node_common/data/methods/create-user.js
index dfd63560..e2f961c0 100644
--- a/node_common/data/methods/create-user.js
+++ b/node_common/data/methods/create-user.js
@@ -14,8 +14,7 @@ export default async ({ password, username, salt, data = {} }) => {
.returning("*");
const index = query ? query.pop() : null;
- index.type = "USER";
- return index;
+ return JSON.parse(JSON.stringify(index));
},
errorFn: async (e) => {
return {
diff --git a/node_common/data/methods/delete-activity-by-id.js b/node_common/data/methods/delete-activity-by-id.js
deleted file mode 100644
index 7c017d69..00000000
--- a/node_common/data/methods/delete-activity-by-id.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async ({ id }) => {
- return await runQuery({
- label: "DELETE_ACTIVITY_BY_ID",
- queryFn: async (DB) => {
- const data = await DB.from("activity").where({ id }).del();
-
- return 1 === data;
- },
- errorFn: async (e) => {
- return {
- error: true,
- decorator: "DELETE_ACTIVITY_BY_ID",
- };
- },
- });
-};
diff --git a/node_common/data/methods/delete-api-keys-for-user-id.js b/node_common/data/methods/delete-api-keys-for-user-id.js
deleted file mode 100644
index 5d924c99..00000000
--- a/node_common/data/methods/delete-api-keys-for-user-id.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async ({ userId }) => {
- return await runQuery({
- label: "DELETE_API_KEYS_FOR_USER_ID",
- queryFn: async (DB) => {
- const data = await DB.from("keys").where({ owner_id: userId }).del();
-
- return 1 === data;
- },
- errorFn: async (e) => {
- return {
- error: true,
- decorator: "DELETE_API_KEYS_FOR_USER_ID",
- };
- },
- });
-};
diff --git a/node_common/data/methods/delete-files-by-ids.js b/node_common/data/methods/delete-files-by-ids.js
new file mode 100644
index 00000000..147813a0
--- /dev/null
+++ b/node_common/data/methods/delete-files-by-ids.js
@@ -0,0 +1,37 @@
+import { runQuery } from "~/node_common/data/utilities";
+
+export default async ({ ids, ownerId }) => {
+ return await runQuery({
+ label: "DELETE_FILES_BY_IDS",
+ queryFn: async (DB) => {
+ // const repostedSlateFiles = await DB.from("slate_files")
+ // .join("slates", "slates.id", "=", "slate_files.slateId")
+ // .whereNot("slates.ownerId", "=", ownerId)
+ // .whereIn("slate_files.fileId", ids)
+ // .update({ "slate_files.fileId": null });
+ const repostedSlateFiles = await DB.from("slate_files")
+ .whereIn("id", function () {
+ this.select("slate_files.id")
+ .from("slate_files")
+ .join("slates", "slates.id", "=", "slate_files.slateId")
+ .whereIn("slate_files.fileId", ids)
+ .whereNot("slates.ownerId", "=", ownerId);
+ })
+ .del();
+
+ const slateFiles = await DB("slate_files").whereIn("fileId", ids).del();
+
+ const activity = await DB("activity").whereIn("fileId", ids).del();
+
+ const files = await DB("files").whereIn("id", ids).del();
+
+ return files === ids.length;
+ },
+ errorFn: async (e) => {
+ return {
+ error: true,
+ decorator: "DELETE_FILES_BY_IDS",
+ };
+ },
+ });
+};
diff --git a/node_common/data/methods/delete-files-by-user-id.js b/node_common/data/methods/delete-files-by-user-id.js
new file mode 100644
index 00000000..13b3d2fb
--- /dev/null
+++ b/node_common/data/methods/delete-files-by-user-id.js
@@ -0,0 +1,48 @@
+import { runQuery } from "~/node_common/data/utilities";
+
+export default async ({ ownerId }) => {
+ return await runQuery({
+ label: "DELETE_FILES_BY_USER_ID",
+ queryFn: async (DB) => {
+ const selected = await DB.select("id").from("files").where({ ownerId });
+
+ if (!selected || selected.error) {
+ return false;
+ }
+
+ let fileIds = selected.map((file) => file.id);
+
+ //NOTE(martina): so that reposted versions of the file can be displayed as "deleted" rather than just disappearing
+ // const repostedSlateFiles = await DB.from("slate_files")
+ // .join("slates", "slates.id", "=", "slate_files.slateId")
+ // .whereNot("slates.ownerId", "=", ownerId)
+ // .whereIn("slate_files.fileId", fileIds)
+ // .update({ "slate_files.fileId": null });
+ //TODO(martina): send out a notification for this instead
+ const repostedSlateFiles = await DB.from("slate_files")
+ .whereIn("id", function () {
+ this.select("slate_files.id")
+ .from("slate_files")
+ .join("slates", "slates.id", "=", "slate_files.slateId")
+ .whereIn("slate_files.fileId", fileIds)
+ .whereNot("slates.ownerId", "=", ownerId);
+ })
+ .del();
+ // .update({ fileId: null });
+
+ const slateFiles = await DB("slate_files").whereIn("fileId", fileIds).del();
+
+ const activity = await DB("activity").whereIn("fileId", fileIds).del();
+
+ const files = await DB("files").whereIn("id", fileIds).del();
+
+ return true;
+ },
+ errorFn: async (e) => {
+ return {
+ error: true,
+ decorator: "DELETE_FILES_BY_USER_ID",
+ };
+ },
+ });
+};
diff --git a/node_common/data/methods/delete-pending-data-by-user-id.js b/node_common/data/methods/delete-pending-data-by-user-id.js
deleted file mode 100644
index 0a855ec1..00000000
--- a/node_common/data/methods/delete-pending-data-by-user-id.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import * as Data from "~/node_common/data";
-
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async ({ owner_user_id }) => {
- return await runQuery({
- label: "REMOVE_PENDING_DATA_FOR_USER",
- queryFn: async (DB) => {
- const pending = await DB.from("pending").where({ owner_user_id }).returning("*").del();
-
- return pending;
- },
- errorFn: async (e) => {
- return {
- decorator: "REMOVE_PENDING_DATA_FOR_USER",
- error: true,
- };
- },
- });
-};
diff --git a/node_common/data/methods/delete-slate-by-id.js b/node_common/data/methods/delete-slate-by-id.js
index 8cd3b786..5de6c031 100644
--- a/node_common/data/methods/delete-slate-by-id.js
+++ b/node_common/data/methods/delete-slate-by-id.js
@@ -4,13 +4,15 @@ export default async ({ id }) => {
return await runQuery({
label: "DELETE_SLATE_BY_ID",
queryFn: async (DB) => {
- const subscriptions = await DB.from("subscriptions")
- .where({ target_slate_id: id })
- .del();
+ const subscriptions = await DB("subscriptions").where({ slateId: id }).del();
- const data = await DB.from("slates").where({ id }).del();
+ const slateFiles = await DB("slate_files").where({ slateId: id }).del();
- return 1 === data;
+ const activity = await DB("activity").where({ slateId: id }).del();
+
+ const slates = await DB("slates").where({ id }).del();
+
+ return 1 === slates;
},
errorFn: async (e) => {
return {
diff --git a/node_common/data/methods/delete-slate-files.js b/node_common/data/methods/delete-slate-files.js
new file mode 100644
index 00000000..8ee55886
--- /dev/null
+++ b/node_common/data/methods/delete-slate-files.js
@@ -0,0 +1,23 @@
+import { runQuery } from "~/node_common/data/utilities";
+
+export default async ({ slateId, ids }) => {
+ return await runQuery({
+ label: "DELETE_SLATE_FILES",
+ queryFn: async (DB) => {
+ const slateFiles = await DB("slate_files")
+ .where("slateId", slateId)
+ .whereIn("fileId", ids)
+ .del();
+
+ const activity = await DB("activity").whereIn("fileId", ids).where("slateId", slateId).del();
+
+ return true;
+ },
+ errorFn: async (e) => {
+ return {
+ error: true,
+ decorator: "DELETE_SLATE_FILES",
+ };
+ },
+ });
+};
diff --git a/node_common/data/methods/delete-slates-by-user-id.js b/node_common/data/methods/delete-slates-by-user-id.js
new file mode 100644
index 00000000..900d23bd
--- /dev/null
+++ b/node_common/data/methods/delete-slates-by-user-id.js
@@ -0,0 +1,32 @@
+import { runQuery } from "~/node_common/data/utilities";
+
+export default async ({ ownerId }) => {
+ return await runQuery({
+ label: "DELETE_SLATES_BY_USER_ID",
+ queryFn: async (DB) => {
+ const selected = await DB.select("id").from("slates").where({ ownerId });
+
+ if (!selected || selected.error) {
+ return false;
+ }
+
+ let slateIds = selected.map((slate) => slate.id);
+
+ const subscriptions = await DB("subscriptions").whereIn("slateId", slateIds).del();
+
+ const slateFiles = await DB("slate_files").whereIn("slateId", slateIds).del();
+
+ const activity = await DB("activity").whereIn("slateId", slateIds).del();
+
+ const slates = await DB("slates").whereIn("id", slateIds).del();
+
+ return true;
+ },
+ errorFn: async (e) => {
+ return {
+ error: true,
+ decorator: "DELETE_SLATES_BY_USER_ID",
+ };
+ },
+ });
+};
diff --git a/node_common/data/methods/delete-slates-for-user-id.js b/node_common/data/methods/delete-slates-for-user-id.js
deleted file mode 100644
index ee8e99c9..00000000
--- a/node_common/data/methods/delete-slates-for-user-id.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async ({ userId }) => {
- return await runQuery({
- label: "DELETE_SLATES_FOR_USER_ID",
- queryFn: async (DB) => {
- const hasUser = (id) =>
- DB.raw(`?? @> ?::jsonb`, ["data", JSON.stringify({ ownerId: id })]);
-
- const slates = await DB.select("id")
- .from("slates")
- .where(hasUser(userId));
-
- if (!slates || slates.error) {
- return false;
- }
-
- let slateIds = slates.map((slate) => slate.id);
-
- const subscriptions = await DB.from("subscriptions")
- .whereIn("target_slate_id", slateIds)
- .del();
-
- const data = await DB.from("slates").where(hasUser(userId)).del();
-
- return 1 === data;
- },
- errorFn: async (e) => {
- return {
- error: true,
- decorator: "DELETE_SLATES_FOR_USER_ID",
- };
- },
- });
-};
diff --git a/node_common/data/methods/delete-trusted-relationship-by-id.js b/node_common/data/methods/delete-trusted-relationship-by-id.js
deleted file mode 100644
index af0ed8dd..00000000
--- a/node_common/data/methods/delete-trusted-relationship-by-id.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async ({ id }) => {
- return await runQuery({
- label: "DELETE_TRUSTED_RELATIONSHIP_BY_ID",
- queryFn: async (DB) => {
- const data = await DB.from("trusted").where({ id }).del();
-
- return 1 === data;
- },
- errorFn: async (e) => {
- return {
- decorator: "DELETE_TRUSTED_RELATIONSHIP_BY_ID",
- error: true,
- };
- },
- });
-};
diff --git a/node_common/data/methods/delete-user-by-id.js b/node_common/data/methods/delete-user-by-id.js
new file mode 100644
index 00000000..dbd3b3a2
--- /dev/null
+++ b/node_common/data/methods/delete-user-by-id.js
@@ -0,0 +1,30 @@
+import { runQuery } from "~/node_common/data/utilities";
+
+export default async ({ id }) => {
+ return await runQuery({
+ label: "DELETE_USER_BY_ID",
+ queryFn: async (DB) => {
+ const keys = await DB.from("keys").where({ ownerId: id }).del();
+
+ const subscriptions = await DB.from("subscriptions")
+ .where({ ownerId: id })
+ .orWhere({ userId: id })
+ .del();
+
+ const activity = await DB.from("activity")
+ .where({ ownerId: id })
+ .orWhere({ userId: id })
+ .del();
+
+ const data = await DB.from("users").where({ id }).del();
+
+ return 1 === data;
+ },
+ errorFn: async (e) => {
+ return {
+ error: true,
+ decorator: "DELETE_USER_BY_ID",
+ };
+ },
+ });
+};
diff --git a/node_common/data/methods/delete-user-by-username.js b/node_common/data/methods/delete-user-by-username.js
deleted file mode 100644
index 8df5d368..00000000
--- a/node_common/data/methods/delete-user-by-username.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async ({ username }) => {
- return await runQuery({
- label: "DELETE_USER_BY_USERNAME",
- queryFn: async (DB) => {
- const query = await DB.select("id")
- .from("users")
- .where({ username })
- .first();
-
- if (!query || query.error || !query.id) {
- return false;
- }
-
- const id = query.id;
-
- const deletedSubscriptions = await DB.from("subscriptions")
- .where({ owner_user_id: id })
- .orWhere({ target_user_id: id })
- .del();
- const deletedTrusted = await DB.from("trusted")
- .where({ owner_user_id: id })
- .orWhere({ target_user_id: id })
- .del();
-
- const data = await DB.from("users").where({ username }).del();
-
- return 1 === data;
- },
- errorFn: async (e) => {
- return {
- error: true,
- decorator: "DELETE_USER_BY_USERNAME",
- };
- },
- });
-};
diff --git a/node_common/data/methods/get-activity-by-id.js b/node_common/data/methods/get-activity-by-id.js
deleted file mode 100644
index d2689c2d..00000000
--- a/node_common/data/methods/get-activity-by-id.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async ({ id }) => {
- return await runQuery({
- label: "GET_ACTIVITY_BY_ID",
- queryFn: async (DB) => {
- const query = await DB.select("*").from("activity").where({ id }).first();
-
- if (!query || query.error) {
- return null;
- }
-
- if (query.id) {
- query.type = "ACTIVITY";
- return JSON.parse(JSON.stringify(query));
- }
-
- return null;
- },
- errorFn: async (e) => {
- return {
- error: true,
- decorator: "GET_ACTIVITY_BY_ID",
- };
- },
- });
-};
diff --git a/node_common/data/methods/get-activity-for-slate-id.js b/node_common/data/methods/get-activity-for-slate-id.js
deleted file mode 100644
index 78ec27b5..00000000
--- a/node_common/data/methods/get-activity-for-slate-id.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async ({ slateId }) => {
- return await runQuery({
- label: "GET_ACTIVITY_FOR_SLATE_ID",
- queryFn: async (DB) => {
- const query = await DB.select("*")
- .from("activity")
- .where({ owner_slate_id: slateId })
- .orderBy("created_at", "desc");
-
- if (!query || query.error) {
- return [];
- }
-
- return JSON.parse(JSON.stringify(query));
- },
- errorFn: async (e) => {
- console.log({
- error: true,
- decorator: "GET_ACTIVITY_FOR_SLATE_ID",
- });
-
- return [];
- },
- });
-};
diff --git a/node_common/data/methods/get-activity-for-user-id.js b/node_common/data/methods/get-activity-for-user-id.js
deleted file mode 100644
index ffa6785b..00000000
--- a/node_common/data/methods/get-activity-for-user-id.js
+++ /dev/null
@@ -1,56 +0,0 @@
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async ({ userId, earliestTimestamp, latestTimestamp }) => {
- return await runQuery({
- label: "GET_ACTIVITY_FOR_USER_ID",
- queryFn: async (DB) => {
- let query;
- if (earliestTimestamp) {
- //NOTE(martina): for pagination, fetching the "next 100" results
- let date = new Date(earliestTimestamp);
- let s = date.getSeconds();
- if (s < 0) {
- s = 60 + s;
- }
- date.setSeconds(s - 1);
- query = await DB.select("*")
- .from("activity")
- .where({ owner_user_id: userId })
- .where("created_at", "<", date.toISOString())
- .orderBy("created_at", "desc")
- .limit(100);
- } else if (latestTimestamp) {
- //NOTE(martina): for fetching new updates since the last time they loaded
- let date = new Date(latestTimestamp);
- date.setSeconds(date.getSeconds() + 1);
- query = await DB.select("*")
- .from("activity")
- .where({ owner_user_id: userId })
- .where("created_at", ">", date.toISOString())
- .orderBy("created_at", "desc")
- .limit(100);
- } else {
- //NOTE(martina): for the first fetch they make, when they have not loaded any explore events yet
- query = await DB.select("*")
- .from("activity")
- .where({ owner_user_id: userId })
- .orderBy("created_at", "desc")
- .limit(100);
- }
-
- if (!query || query.error) {
- return [];
- }
-
- return JSON.parse(JSON.stringify(query));
- },
- errorFn: async (e) => {
- console.log({
- error: true,
- decorator: "GET_ACTIVITY_FOR_USER_ID",
- });
-
- return [];
- },
- });
-};
diff --git a/node_common/data/methods/get-activity.js b/node_common/data/methods/get-activity.js
new file mode 100644
index 00000000..3ab5ae23
--- /dev/null
+++ b/node_common/data/methods/get-activity.js
@@ -0,0 +1,103 @@
+import { runQuery } from "~/node_common/data/utilities";
+
+export default async ({
+ following = [],
+ subscriptions = [],
+ earliestTimestamp,
+ latestTimestamp,
+}) => {
+ return await runQuery({
+ label: "GET_ACTIVITY_FOR_USER_ID",
+ queryFn: async (DB) => {
+ const users = () => DB.raw("row_to_json(??) as ??", ["users", "owner"]);
+
+ const slates = () => DB.raw("row_to_json(??) as ??", ["slates", "slate"]);
+
+ const files = () => DB.raw("row_to_json(??) as ??", ["files", "file"]);
+
+ let query;
+ if (earliestTimestamp) {
+ //NOTE(martina): for pagination, fetching the "next 100" results
+ let date = new Date(earliestTimestamp);
+ let s = date.getSeconds();
+ if (s < 0) {
+ s = 60 + s;
+ }
+ date.setSeconds(s - 1);
+ query = await DB.select(
+ "activity.id",
+ "activity.type",
+ "activity.createdAt",
+ users(),
+ slates(),
+ files()
+ )
+ .from("activity")
+ .join("users", "users.id", "=", "activity.ownerId")
+ .leftJoin("files", "files.id", "=", "activity.fileId")
+ .leftJoin("slates", "slates.id", "=", "activity.slateId")
+ .where("activity.type", "CREATE_SLATE_OBJECT")
+ .where("activity.createdAt", "<", date.toISOString())
+ .whereIn("activity.ownerId", following)
+ .orWhereIn("activity.slateId", subscriptions)
+ .orderBy("activity.createdAt", "desc")
+ .limit(100);
+ } else if (latestTimestamp) {
+ //NOTE(martina): for fetching new updates since the last time they loaded
+ let date = new Date(latestTimestamp);
+ date.setSeconds(date.getSeconds() + 1);
+ query = await DB.select(
+ "activity.id",
+ "activity.type",
+ "activity.createdAt",
+ users(),
+ slates(),
+ files()
+ )
+ .from("activity")
+ .join("users", "users.id", "=", "activity.ownerId")
+ .leftJoin("files", "files.id", "=", "activity.fileId")
+ .leftJoin("slates", "slates.id", "=", "activity.slateId")
+ .where("activity.createdAt", ">", date.toISOString())
+ .where("activity.type", "CREATE_SLATE_OBJECT")
+ .whereIn("activity.ownerId", following)
+ .orWhereIn("activity.slateId", subscriptions)
+ .orderBy("activity.createdAt", "desc")
+ .limit(100);
+ } else {
+ //NOTE(martina): for the first fetch they make, when they have not loaded any explore events yet
+ query = await DB.select(
+ "activity.id",
+ "activity.type",
+ "activity.createdAt",
+ users(),
+ slates(),
+ files()
+ )
+ .from("activity")
+ .join("users", "users.id", "=", "activity.ownerId")
+ .leftJoin("files", "files.id", "=", "activity.fileId")
+ .leftJoin("slates", "slates.id", "=", "activity.slateId")
+ .where("activity.type", "CREATE_SLATE_OBJECT")
+ .whereIn("activity.ownerId", following)
+ .orWhereIn("activity.slateId", subscriptions)
+ .orderBy("activity.createdAt", "desc")
+ .limit(100);
+ }
+
+ if (!query) {
+ return [];
+ }
+
+ return JSON.parse(JSON.stringify(query));
+ },
+ errorFn: async (e) => {
+ console.log({
+ error: true,
+ decorator: "GET_ACTIVITY_FOR_USER_ID",
+ });
+
+ return [];
+ },
+ });
+};
diff --git a/node_common/data/methods/get-all-activity.js b/node_common/data/methods/get-all-activity.js
deleted file mode 100644
index f106042b..00000000
--- a/node_common/data/methods/get-all-activity.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import * as Serializers from "~/node_common/serializers";
-
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async () => {
- return await runQuery({
- label: "GET_ALL_ACTIVITY",
- queryFn: async (DB) => {
- const r = await DB.select("*").from("activity");
-
- if (!r || r.error) {
- return [];
- }
-
- return JSON.parse(JSON.stringify(r));
- },
- errorFn: async (e) => {
- console.log({
- error: true,
- decorator: "GET_ALL_ACTIVITY",
- });
-
- return [];
- },
- });
-};
diff --git a/node_common/data/methods/get-all-deals.js b/node_common/data/methods/get-all-deals.js
deleted file mode 100644
index 91b7a26d..00000000
--- a/node_common/data/methods/get-all-deals.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import * as Serializers from "~/node_common/serializers";
-
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async () => {
- return await runQuery({
- label: "GET_ALL_DEALS",
- queryFn: async (DB) => {
- const r = await DB.select("*").from("deals");
-
- if (!r || r.error) {
- return [];
- }
-
- return JSON.parse(JSON.stringify(r));
- },
- errorFn: async (e) => {
- console.log({
- error: true,
- decorator: "GET_ALL_DEALS",
- });
-
- return [];
- },
- });
-};
diff --git a/node_common/data/methods/get-all-stats.js b/node_common/data/methods/get-all-stats.js
deleted file mode 100644
index d7e1aba6..00000000
--- a/node_common/data/methods/get-all-stats.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import * as Serializers from "~/node_common/serializers";
-
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async () => {
- return await runQuery({
- label: "GET_ALL_STATS",
- queryFn: async (DB) => {
- const r = await DB.select("*").from("stats").orderBy("created_at", "desc");
-
- if (!r || r.error) {
- return [];
- }
-
- return JSON.parse(JSON.stringify(r));
- },
- errorFn: async (e) => {
- console.log({
- error: true,
- decorator: "GET_ALL_STATS",
- });
-
- return [];
- },
- });
-};
diff --git a/node_common/data/methods/get-api-keys-by-user-id.js b/node_common/data/methods/get-api-keys-by-user-id.js
index 67012503..948fb282 100644
--- a/node_common/data/methods/get-api-keys-by-user-id.js
+++ b/node_common/data/methods/get-api-keys-by-user-id.js
@@ -4,9 +4,7 @@ export default async ({ userId }) => {
return await runQuery({
label: "GET_API_KEYS_BY_USER_ID",
queryFn: async (DB) => {
- const query = await DB.select("*")
- .from("keys")
- .where({ owner_id: userId });
+ const query = await DB.select("*").from("keys").where({ ownerId: userId });
if (!query || query.error) {
return [];
diff --git a/node_common/data/methods/get-every-file.js b/node_common/data/methods/get-every-file.js
new file mode 100644
index 00000000..7f3203db
--- /dev/null
+++ b/node_common/data/methods/get-every-file.js
@@ -0,0 +1,47 @@
+import * as Serializers from "~/node_common/serializers";
+
+import { runQuery } from "~/node_common/data/utilities";
+
+export default async ({ sanitize = false, publicOnly = false } = {}) => {
+ return await runQuery({
+ label: "GET_EVERY_FILE",
+ queryFn: async (DB) => {
+ let files;
+ if (publicOnly) {
+ files = await DB.select(
+ "files.id",
+ "files.ownerId",
+ "files.cid",
+ "files.isPublic",
+ "files.data"
+ )
+ .from("files")
+ .leftJoin("slate_files", "slate_files.fileId", "files.id")
+ .leftJoin("slates", "slate_files.slateId", "slates.id")
+ .where("slates.isPublic", true)
+ .orWhere("files.isPublic", true)
+ .groupBy("files.id");
+ } else {
+ files = await DB.select("*").from("files");
+ }
+
+ if (!files || files.error) {
+ return [];
+ }
+
+ if (sanitize) {
+ files = files.map((file) => Serializers.sanitizeFile(file));
+ }
+
+ return JSON.parse(JSON.stringify(files));
+ },
+ errorFn: async (e) => {
+ console.log({
+ error: true,
+ decorator: "GET_EVERY_FILE",
+ });
+
+ return [];
+ },
+ });
+};
diff --git a/node_common/data/methods/get-every-slate.js b/node_common/data/methods/get-every-slate.js
index 256ff13d..983c4def 100644
--- a/node_common/data/methods/get-every-slate.js
+++ b/node_common/data/methods/get-every-slate.js
@@ -2,24 +2,68 @@ import * as Serializers from "~/node_common/serializers";
import { runQuery } from "~/node_common/data/utilities";
-export default async (sanitize = true) => {
+export default async ({ sanitize = false, includeFiles = false, publicOnly = false } = {}) => {
return await runQuery({
label: "GET_EVERY_SLATE",
queryFn: async (DB) => {
- const r = await DB.select("id", "slatename", "data").from("slates");
+ // const slateFiles = () =>
+ // DB.raw("json_agg(?? order by ?? asc) as ??", ["files", "slate_files.createdAt", "objects"]);
- if (!r || r.error) {
+ const slateFiles = () =>
+ DB.raw("coalesce(json_agg(?? order by ?? asc) filter (where ?? is not null), '[]') as ??", [
+ "files",
+ "slate_files.createdAt",
+ "files.id",
+ "objects",
+ ]);
+
+ let slates;
+ if (publicOnly) {
+ if (includeFiles) {
+ slates = await DB.select(
+ "slates.id",
+ "slates.slatename",
+ "slates.data",
+ "slates.ownerId",
+ "slates.isPublic",
+ slateFiles()
+ )
+ .from("slates")
+ .leftJoin("slate_files", "slate_files.slateId", "=", "slates.id")
+ .leftJoin("files", "slate_files.fileId", "=", "files.id")
+ .where("slates.isPublic", true)
+ .groupBy("slates.id");
+ } else {
+ slates = await DB.select("*").from("slates").where("isPublic", true);
+ }
+ } else {
+ if (includeFiles) {
+ slates = await DB.select(
+ "slates.id",
+ "slates.slatename",
+ "slates.data",
+ "slates.ownerId",
+ "slates.isPublic",
+ slateFiles()
+ )
+ .from("slates")
+ .leftJoin("slate_files", "slate_files.slateId", "=", "slates.id")
+ .leftJoin("files", "slate_files.fileId", "=", "files.id")
+ .groupBy("slates.id");
+ } else {
+ slates = await DB.select("*").from("slates");
+ }
+ }
+
+ if (!slates || slates.error) {
return [];
}
if (sanitize) {
- const sanitized = r
- .filter((each) => !each.data.public)
- .map((each) => Serializers.slate(each));
- return JSON.parse(JSON.stringify(sanitized));
+ slates = slates.map((slate) => Serializers.sanitizeSlate(slate));
}
- return JSON.parse(JSON.stringify(r));
+ return JSON.parse(JSON.stringify(slates));
},
errorFn: async (e) => {
console.log({
diff --git a/node_common/data/methods/get-every-user.js b/node_common/data/methods/get-every-user.js
index 7be9692a..afb6cd5c 100644
--- a/node_common/data/methods/get-every-user.js
+++ b/node_common/data/methods/get-every-user.js
@@ -2,22 +2,37 @@ import * as Serializers from "~/node_common/serializers";
import { runQuery } from "~/node_common/data/utilities";
-export default async (sanitize = true) => {
+export default async ({ sanitize = false, includeFiles = false } = {}) => {
return await runQuery({
label: "GET_EVERY_USER",
queryFn: async (DB) => {
- const r = await DB.select("id", "username", "data").from("users");
+ // const userFiles = () =>
+ // DB.raw("json_agg(?? order by ?? desc) as ??", ["files", "files.createdAt", "library"]);
- if (!r || r.error) {
+ const userFiles = () =>
+ DB.raw(
+ "coalesce(json_agg(?? order by ?? desc) filter (where ?? is not null), '[]') as ??",
+ ["files", "files.createdAt", "files.id", "library"]
+ );
+
+ let users;
+ if (includeFiles) {
+ users = await DB.select("users.id", "users.username", "users.data", userFiles())
+ .from("users")
+ .leftJoin("files", "files.ownerId", "users.id");
+ } else {
+ users = await DB.select("*").from("users");
+ }
+
+ if (!users || users.error) {
return [];
}
if (sanitize) {
- const sanitized = r.map((each) => Serializers.user(each));
- return JSON.parse(JSON.stringify(sanitized));
+ users = users.map((user) => Serializers.sanitizeUser(user));
}
- return JSON.parse(JSON.stringify(r));
+ return JSON.parse(JSON.stringify(users));
},
errorFn: async (e) => {
console.log({
diff --git a/node_common/data/methods/get-explore.js b/node_common/data/methods/get-explore.js
new file mode 100644
index 00000000..f98509a8
--- /dev/null
+++ b/node_common/data/methods/get-explore.js
@@ -0,0 +1,92 @@
+import { runQuery } from "~/node_common/data/utilities";
+
+export default async ({ earliestTimestamp, latestTimestamp }) => {
+ return await runQuery({
+ label: "GET_EXPLORE",
+ queryFn: async (DB) => {
+ const users = () => DB.raw("row_to_json(??) as ??", ["users", "owner"]);
+
+ const slates = () => DB.raw("row_to_json(??) as ??", ["slates", "slate"]);
+
+ const files = () => DB.raw("row_to_json(??) as ??", ["files", "file"]);
+
+ let query;
+ if (earliestTimestamp) {
+ //NOTE(martina): for pagination, fetching the "next 100" results
+ let date = new Date(earliestTimestamp);
+ let s = date.getSeconds();
+ if (s < 0) {
+ s = 60 + s;
+ }
+ date.setSeconds(s - 1);
+ query = await DB.select(
+ "activity.id",
+ "activity.type",
+ "activity.createdAt",
+ users(),
+ slates(),
+ files()
+ )
+ .from("activity")
+ .join("users", "users.id", "=", "activity.ownerId")
+ .leftJoin("files", "files.id", "=", "activity.fileId")
+ .leftJoin("slates", "slates.id", "=", "activity.slateId")
+ .where("activity.createdAt", "<", date.toISOString())
+ .where("activity.type", "CREATE_SLATE_OBJECT")
+ .orderBy("activity.createdAt", "desc")
+ .limit(100);
+ } else if (latestTimestamp) {
+ //NOTE(martina): for fetching new updates since the last time they loaded
+ let date = new Date(latestTimestamp);
+ date.setSeconds(date.getSeconds() + 1);
+ query = await DB.select(
+ "activity.id",
+ "activity.type",
+ "activity.createdAt",
+ users(),
+ slates(),
+ files()
+ )
+ .from("activity")
+ .join("users", "users.id", "=", "activity.ownerId")
+ .leftJoin("files", "files.id", "=", "activity.fileId")
+ .leftJoin("slates", "slates.id", "=", "activity.slateId")
+ .where("activity.createdAt", ">", date.toISOString())
+ .where("activity.type", "CREATE_SLATE_OBJECT")
+ .orderBy("activity.createdAt", "desc")
+ .limit(100);
+ } else {
+ //NOTE(martina): for the first fetch they make, when they have not loaded any explore events yet
+ query = await DB.select(
+ "activity.id",
+ "activity.type",
+ "activity.createdAt",
+ users(),
+ slates(),
+ files()
+ )
+ .from("activity")
+ .join("users", "users.id", "=", "activity.ownerId")
+ .leftJoin("files", "files.id", "=", "activity.fileId")
+ .leftJoin("slates", "slates.id", "=", "activity.slateId")
+ .where("activity.type", "CREATE_SLATE_OBJECT")
+ .orderBy("activity.createdAt", "desc")
+ .limit(100);
+ }
+
+ if (!query || query.error) {
+ return [];
+ }
+
+ return JSON.parse(JSON.stringify(query));
+ },
+ errorFn: async (e) => {
+ console.log({
+ error: true,
+ decorator: "GET_EXPLORE",
+ });
+
+ return [];
+ },
+ });
+};
diff --git a/node_common/data/methods/get-file-by-cid.js b/node_common/data/methods/get-file-by-cid.js
new file mode 100644
index 00000000..6f63853d
--- /dev/null
+++ b/node_common/data/methods/get-file-by-cid.js
@@ -0,0 +1,35 @@
+import * as Serializers from "~/node_common/serializers";
+
+import { runQuery } from "~/node_common/data/utilities";
+
+//NOTE(martina): if you include an ownerId, this will return a single entry since there are no duplicate cids within a user's files
+//if you don't include an ownerId, this will return an array of entries since multiple users can have the same file
+export default async ({ ownerId, cid, sanitize = false }) => {
+ return await runQuery({
+ label: "GET_FILE_BY_CID",
+ queryFn: async (DB) => {
+ let query;
+ if (ownerId) {
+ query = await DB.select("*").from("files").where({ ownerId, cid }).first();
+ } else {
+ query = await DB.select("*").from("files").where({ cid });
+ }
+
+ if (!query || query.error) {
+ return null;
+ }
+
+ if (sanitize) {
+ query = Serializers.sanitizeFile(query);
+ }
+
+ return JSON.parse(JSON.stringify(query));
+ },
+ errorFn: async (e) => {
+ return {
+ error: true,
+ decorator: "GET_FILE_BY_CID",
+ };
+ },
+ });
+};
diff --git a/node_common/data/methods/get-file-by-id.js b/node_common/data/methods/get-file-by-id.js
new file mode 100644
index 00000000..6cfac20e
--- /dev/null
+++ b/node_common/data/methods/get-file-by-id.js
@@ -0,0 +1,28 @@
+import * as Serializers from "~/node_common/serializers";
+
+import { runQuery } from "~/node_common/data/utilities";
+
+export default async ({ id, sanitize = false }) => {
+ return await runQuery({
+ label: "GET_FILE_BY_ID",
+ queryFn: async (DB) => {
+ const query = await DB.select("*").from("files").where({ id }).first();
+
+ if (!query || query.error) {
+ return null;
+ }
+
+ if (sanitize) {
+ query = Serializers.sanitizeFile(query);
+ }
+
+ return JSON.parse(JSON.stringify(query));
+ },
+ errorFn: async (e) => {
+ return {
+ error: true,
+ decorator: "GET_FILE_BY_ID",
+ };
+ },
+ });
+};
diff --git a/node_common/data/methods/get-files-by-cids.js b/node_common/data/methods/get-files-by-cids.js
new file mode 100644
index 00000000..25a1e000
--- /dev/null
+++ b/node_common/data/methods/get-files-by-cids.js
@@ -0,0 +1,37 @@
+import * as Serializers from "~/node_common/serializers";
+
+import { runQuery } from "~/node_common/data/utilities";
+
+export default async ({ ownerId, cids, sanitize = false }) => {
+ return await runQuery({
+ label: "GET_FILES_BY_CIDS",
+ queryFn: async (DB) => {
+ let query;
+ if (ownerId) {
+ query = await DB.select("*").from("files").where("ownerId", ownerId).whereIn("cid", cids);
+ } else {
+ query = await DB.select("*").from("files").whereIn("cid", cids);
+ }
+
+ if (!query || query.error) {
+ return null;
+ }
+
+ let serialized = [];
+ if (sanitize) {
+ for (let file of query) {
+ serialized.push(Serializers.sanitizeFile(file));
+ }
+ return JSON.parse(JSON.stringify(serialized));
+ }
+
+ return JSON.parse(JSON.stringify(query));
+ },
+ errorFn: async (e) => {
+ return {
+ error: true,
+ decorator: "GET_FILES_BY_CIDS",
+ };
+ },
+ });
+};
diff --git a/node_common/data/methods/get-files-by-ids.js b/node_common/data/methods/get-files-by-ids.js
new file mode 100644
index 00000000..9fac0cec
--- /dev/null
+++ b/node_common/data/methods/get-files-by-ids.js
@@ -0,0 +1,48 @@
+import * as Serializers from "~/node_common/serializers";
+
+import { runQuery } from "~/node_common/data/utilities";
+
+export default async ({ ids, sanitize = false, publicOnly = false }) => {
+ return await runQuery({
+ label: "GET_FILES_BY_IDS",
+ queryFn: async (DB) => {
+ let query;
+ if (publicOnly) {
+ query = await DB.select(
+ "files.id",
+ "files.ownerId",
+ "files.cid",
+ "files.isPublic",
+ "files.filename",
+ "files.data"
+ )
+ .from("files")
+ .leftJoin("slate_files", "slate_files.fileId", "=", "files.id")
+ .leftJoin("slates", "slates.id", "=", "slate_files.slateId")
+ .whereIn("files.id", ids)
+ .where("files.isPublic", true)
+ .orWhereIn("files.id", ids)
+ .andWhere("slates.isPublic", true)
+ .groupBy("files.id");
+ } else {
+ query = await DB.select("*").from("files").whereIn("id", ids);
+ }
+
+ if (!query || query.error) {
+ return null;
+ }
+
+ if (sanitize) {
+ query = query.map((file) => Serializers.sanitizeFile(file));
+ }
+
+ return JSON.parse(JSON.stringify(query));
+ },
+ errorFn: async (e) => {
+ return {
+ error: true,
+ decorator: "GET_FILES_BY_IDS",
+ };
+ },
+ });
+};
diff --git a/node_common/data/methods/get-files-by-user-id.js b/node_common/data/methods/get-files-by-user-id.js
new file mode 100644
index 00000000..03f2ece2
--- /dev/null
+++ b/node_common/data/methods/get-files-by-user-id.js
@@ -0,0 +1,54 @@
+import * as Serializers from "~/node_common/serializers";
+
+import { runQuery } from "~/node_common/data/utilities";
+
+export default async ({ id, sanitize = false, publicOnly = false }) => {
+ return await runQuery({
+ label: "GET_FILES_BY_USER_ID",
+ queryFn: async (DB) => {
+ let query;
+ if (publicOnly) {
+ query = await DB.select(
+ "files.id",
+ "files.ownerId",
+ "files.cid",
+ "files.isPublic",
+ "files.filename",
+ "files.data"
+ )
+ .from("files")
+ .leftJoin("slate_files", "slate_files.fileId", "=", "files.id")
+ .leftJoin("slates", "slate_files.slateId", "=", "slates.id")
+ .where({ "files.ownerId": id, "slates.isPublic": true })
+ .orWhere({ "files.ownerId": id, "files.isPublic": true })
+ .orderBy("files.createdAt", "desc")
+ .groupBy("files.id");
+ } else {
+ query = await DB.select("*")
+ .from("files")
+ .where("ownerId", id)
+ .orderBy("createdAt", "desc");
+ }
+
+ if (!query || query.error) {
+ return null;
+ }
+
+ let serialized = [];
+ if (sanitize) {
+ for (let file of query) {
+ serialized.push(Serializers.sanitizeFile(file));
+ }
+ return JSON.parse(JSON.stringify(serialized));
+ }
+
+ return JSON.parse(JSON.stringify(query));
+ },
+ errorFn: async (e) => {
+ return {
+ error: true,
+ decorator: "GET_FILES_BY_USER_ID",
+ };
+ },
+ });
+};
diff --git a/node_common/data/methods/get-followers-by-user-id.js b/node_common/data/methods/get-followers-by-user-id.js
new file mode 100644
index 00000000..90d5508a
--- /dev/null
+++ b/node_common/data/methods/get-followers-by-user-id.js
@@ -0,0 +1,34 @@
+import { runQuery } from "~/node_common/data/utilities";
+
+import * as Serializers from "~/node_common/serializers";
+
+export default async ({ userId }) => {
+ return await runQuery({
+ label: "GET_FOLLOWERS_BY_USER_ID",
+ queryFn: async (DB) => {
+ const query = await DB.select("users.id", "users.username", "users.data")
+ .from("users")
+ .join("subscriptions", "subscriptions.ownerId", "=", "users.id")
+ .where({ "subscriptions.userId": userId })
+ .orderBy("subscriptions.createdAt", "desc");
+ if (!query || query.error) {
+ return [];
+ }
+
+ let serialized = [];
+ for (let user of query) {
+ serialized.push(Serializers.sanitizeUser(user));
+ }
+
+ return JSON.parse(JSON.stringify(serialized));
+ },
+ errorFn: async (e) => {
+ console.log({
+ error: true,
+ decorator: "GET_FOLLOWERS_BY_USER_ID",
+ });
+
+ return [];
+ },
+ });
+};
diff --git a/node_common/data/methods/get-following-by-user-id.js b/node_common/data/methods/get-following-by-user-id.js
new file mode 100644
index 00000000..753b1adb
--- /dev/null
+++ b/node_common/data/methods/get-following-by-user-id.js
@@ -0,0 +1,35 @@
+import { runQuery } from "~/node_common/data/utilities";
+
+import * as Serializers from "~/node_common/serializers";
+
+export default async ({ ownerId }) => {
+ return await runQuery({
+ label: "GET_FOLLOWING_BY_USER_ID",
+ queryFn: async (DB) => {
+ const query = await DB.select("users.id", "users.username", "users.data")
+ .from("users")
+ .join("subscriptions", "subscriptions.userId", "=", "users.id")
+ .where({ "subscriptions.ownerId": ownerId })
+ .orderBy("subscriptions.createdAt", "desc");
+
+ if (!query || query.error) {
+ return [];
+ }
+
+ let serialized = [];
+ for (let user of query) {
+ serialized.push(Serializers.sanitizeUser(user));
+ }
+
+ return JSON.parse(JSON.stringify(serialized));
+ },
+ errorFn: async (e) => {
+ console.log({
+ error: true,
+ decorator: "GET_FOLLOWING_BY_USER_ID",
+ });
+
+ return [];
+ },
+ });
+};
diff --git a/node_common/data/methods/get-or-create-global-stats.js b/node_common/data/methods/get-or-create-global-stats.js
deleted file mode 100644
index 04098884..00000000
--- a/node_common/data/methods/get-or-create-global-stats.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async (date, generateDataFn) => {
- return await runQuery({
- label: "GET_OR_CREATE_GLOBAL_STATS",
- queryFn: async (DB) => {
- date.setHours(0, 0, 0, 0);
-
- let end = new Date();
- end.setHours(23, 59, 59, 999);
-
- const query = await DB.select("*")
- .from("global")
- .where("created_at", ">=", date)
- .where("created_at", "<", end)
- .first();
-
- if (query && query.id) {
- return query;
- }
-
- const insert = await DB.insert({
- created_at: date,
- data: await generateDataFn(),
- })
- .into("global")
- .returning("*");
-
- const index = insert ? insert.pop() : null;
-
- if (!index) {
- return null;
- }
-
- return JSON.parse(JSON.stringify(index));
- },
- errorFn: async (e) => {
- console.log(e);
- return {
- error: true,
- decorator: "GET_OR_CREATE_GLOBAL_STATS",
- };
- },
- });
-};
diff --git a/node_common/data/methods/get-pending-data-for-user-id.js b/node_common/data/methods/get-pending-data-for-user-id.js
deleted file mode 100644
index dfbccd2e..00000000
--- a/node_common/data/methods/get-pending-data-for-user-id.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async ({ userId }) => {
- return await runQuery({
- label: "GET_PENDING_DATA_BY_USER_ID",
- queryFn: async (DB) => {
- const query = await DB.select("*")
- .from("pending")
- .where({ owner_user_id: userId });
-
- if (!query || query.error) {
- return [];
- }
-
- return JSON.parse(JSON.stringify(query));
- },
- errorFn: async (e) => {
- console.log({
- error: true,
- decorator: "GET_PENDING_DATA_BY_USER_ID",
- });
-
- return [];
- },
- });
-};
diff --git a/node_common/data/methods/get-pending-trusted-relationships-by-user-id.js b/node_common/data/methods/get-pending-trusted-relationships-by-user-id.js
deleted file mode 100644
index 4db155d7..00000000
--- a/node_common/data/methods/get-pending-trusted-relationships-by-user-id.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async ({ userId }) => {
- return await runQuery({
- label: "GET_PENDING_TRUSTED_RELATIONSHIPS_BY_USER_ID",
- queryFn: async (DB) => {
- const query = await DB.select("*")
- .from("trusted")
- .where({ target_user_id: userId });
-
- if (!query || query.error) {
- return [];
- }
-
- return JSON.parse(JSON.stringify(query));
- },
- errorFn: async (e) => {
- console.log({
- error: true,
- decorator: "GET_PENDING_TRUSTED_RELATIONSHIPS_BY_USER_ID",
- });
-
- return [];
- },
- });
-};
diff --git a/node_common/data/methods/get-slate-by-id.js b/node_common/data/methods/get-slate-by-id.js
index 73c02db8..8885c897 100644
--- a/node_common/data/methods/get-slate-by-id.js
+++ b/node_common/data/methods/get-slate-by-id.js
@@ -1,20 +1,54 @@
+import * as Serializers from "~/node_common/serializers";
+
import { runQuery } from "~/node_common/data/utilities";
-export default async ({ id }) => {
+export default async ({ id, sanitize = false, includeFiles = false }) => {
return await runQuery({
label: "GET_SLATE_BY_ID",
queryFn: async (DB) => {
- const query = await DB.select("*").from("slates").where({ id }).first();
+ // const slateFiles = () =>
+ // DB.raw("json_agg(?? order by ?? asc) as ??", ["files", "slate_files.createdAt", "objects"]);
+ const slateFiles = () =>
+ DB.raw("coalesce(json_agg(?? order by ?? asc) filter (where ?? is not null), '[]') as ??", [
+ "files",
+ "slate_files.createdAt",
+ "files.id",
+ "objects",
+ ]);
+
+ let query;
+
+ if (includeFiles) {
+ query = await DB.select(
+ "slates.id",
+ "slates.slatename",
+ "slates.data",
+ "slates.ownerId",
+ "slates.isPublic",
+ slateFiles()
+ )
+ .from("slates")
+ .leftJoin("slate_files", "slate_files.slateId", "=", "slates.id")
+ .leftJoin("files", "slate_files.fileId", "=", "files.id")
+ .where({ "slates.id": id })
+ .groupBy("slates.id")
+ .first();
+ } else {
+ query = await DB.select("id", "slatename", "data", "ownerId", "isPublic")
+ .from("slates")
+ .where({ id })
+ .first();
+ }
if (!query || query.error) {
return null;
}
- if (query.id) {
- return JSON.parse(JSON.stringify(query));
+ if (sanitize) {
+ query = Serializers.sanitizeSlate(query);
}
- return null;
+ return JSON.parse(JSON.stringify(query));
},
errorFn: async (e) => {
return {
diff --git a/node_common/data/methods/get-slate-by-name.js b/node_common/data/methods/get-slate-by-name.js
index daf88c97..43309ee5 100644
--- a/node_common/data/methods/get-slate-by-name.js
+++ b/node_common/data/methods/get-slate-by-name.js
@@ -1,15 +1,14 @@
+import * as Serializers from "~/node_common/serializers";
+
import { runQuery } from "~/node_common/data/utilities";
-export default async ({ slatename, ownerId, username }) => {
+export default async ({ slatename, ownerId, username, sanitize = false, includeFiles = false }) => {
return await runQuery({
label: "GET_SLATE_BY_NAME",
queryFn: async (DB) => {
let id = ownerId;
if (username && !ownerId) {
- const user = await DB.select("*")
- .from("users")
- .where({ username })
- .first();
+ const user = await DB.select("id").from("users").where({ username }).first();
if (!user || user.error) {
return null;
@@ -18,24 +17,50 @@ export default async ({ slatename, ownerId, username }) => {
id = user.id;
}
- const query = await DB.select("*").from("slates").where({ slatename });
+ // const slateFiles = () =>
+ // DB.raw("json_agg(?? order by ?? asc) as ??", ["files", "slate_files.createdAt", "objects"]);
+
+ const slateFiles = () =>
+ DB.raw("coalesce(json_agg(?? order by ?? asc) filter (where ?? is not null), '[]') as ??", [
+ "files",
+ "slate_files.createdAt",
+ "files.id",
+ "objects",
+ ]);
+
+ let query;
+
+ if (includeFiles) {
+ query = await DB.select(
+ "slates.id",
+ "slates.slatename",
+ "slates.data",
+ "slates.ownerId",
+ "slates.isPublic",
+ slateFiles()
+ )
+ .from("slates")
+ .leftJoin("slate_files", "slate_files.slateId", "=", "slates.id")
+ .leftJoin("files", "slate_files.fileId", "=", "files.id")
+ .where({ "slates.slatename": slatename, "slates.ownerId": id })
+ .groupBy("slates.id")
+ .first();
+ } else {
+ query = await DB.select("id", "slatename", "data", "ownerId", "isPublic")
+ .from("slates")
+ .where({ slatename, ownerId: id })
+ .first();
+ }
if (!query || query.error) {
return null;
}
- let foundSlate;
- for (let slate of query) {
- if (slate.data.ownerId && slate.data.ownerId === id) {
- foundSlate = slate;
- }
+ if (sanitize) {
+ query = Serializers.sanitizeSlate(query);
}
- if (foundSlate && foundSlate.id) {
- return JSON.parse(JSON.stringify(foundSlate));
- }
-
- return null;
+ return JSON.parse(JSON.stringify(query));
},
errorFn: async (e) => {
return {
diff --git a/node_common/data/methods/get-slate-files-by-cids.js b/node_common/data/methods/get-slate-files-by-cids.js
new file mode 100644
index 00000000..c85dcff9
--- /dev/null
+++ b/node_common/data/methods/get-slate-files-by-cids.js
@@ -0,0 +1,38 @@
+import { runQuery } from "~/node_common/data/utilities";
+
+/**
+ * Gets the files in the slate with id SLATEID that have a cid in CIDS. Used to check for
+ * duplicate cid files in a slate before adding a file to a slate
+ */
+export default async ({ slateId, cids }) => {
+ return await runQuery({
+ label: "GET_SLATE_FILES_BY_CID",
+ queryFn: async (DB) => {
+ const query = await DB.select(
+ "files.id",
+ "files.ownerId",
+ "files.cid",
+ "files.isPublic",
+ "files.filename",
+ "files.data"
+ )
+ .from("files")
+ .join("slate_files", "slate_files.fileId", "=", "files.id")
+ .where("slate_files.slateId", slateId)
+ .whereIn("files.cid", cids)
+ .groupBy("files.id");
+
+ if (!query || query.error) {
+ return null;
+ }
+
+ return JSON.parse(JSON.stringify(query));
+ },
+ errorFn: async (e) => {
+ return {
+ error: true,
+ decorator: "GET_SLATE_FILES_BY_CID",
+ };
+ },
+ });
+};
diff --git a/node_common/data/methods/get-slate-objects-by-cid.js b/node_common/data/methods/get-slate-objects-by-cid.js
deleted file mode 100644
index 40d86dd2..00000000
--- a/node_common/data/methods/get-slate-objects-by-cid.js
+++ /dev/null
@@ -1,77 +0,0 @@
-import { runQuery } from "~/node_common/data/utilities";
-
-// NOTE(jim): Passing URL and CID because right now
-// the CID only lives in the url property of the object.
-export default async ({ cid, url, ownerId }) => {
- return await runQuery({
- label: "GET_SLATE_OBJECT_BY_CID",
- queryFn: async (DB) => {
- let hasObjectURL;
- if (ownerId) {
- hasObjectURL = (textileURL) =>
- DB.raw(`?? @> ?::jsonb`, [
- "data",
- JSON.stringify({ objects: [{ url: textileURL, ownerId }] }),
- ]);
- } else {
- hasObjectURL = (textileURL) =>
- DB.raw(`?? @> ?::jsonb`, ["data", JSON.stringify({ objects: [{ url: textileURL }] })]);
- }
-
- /*
- const hasObjectCID = (id) =>
- DB.raw(`?? @> ?::jsonb`, ["data", JSON.stringify({ objects: [{ cid: id }] })]);
-
- const query = await DB.select("*")
- .from("slates")
- .where(hasObjectCID(cid));
- */
-
- const query = await DB.select("*")
- .from("slates")
- .where(hasObjectURL(url));
-
- if (!query || query.error) {
- return [];
- }
-
- return query;
-
- // let solution = [];
- // query.forEach((each) => {
- // // TODO(martina): Change this when you fix props.
- // const object = each.data.objects.find((object) => object.url === url);
-
- // if (!object) {
- // return;
- // }
-
- // if (!each.data.public) {
- // return;
- // }
-
- // object.slate = {
- // id: each.id,
- // created_at: each.created_at,
- // updated_at: each.updated_at,
- // slatename: each.slatename,
- // data: {
- // ownerId: each.data.ownerId,
- // },
- // };
-
- // solution.push(object);
- // });
-
- // return solution;
- },
- errorFn: async (e) => {
- console.log({
- error: true,
- decorator: "GET_SLATE_OBJECT_BY_CID",
- });
-
- return [];
- },
- });
-};
diff --git a/node_common/data/methods/get-slates-by-ids.js b/node_common/data/methods/get-slates-by-ids.js
index b94860f7..b8b4f961 100644
--- a/node_common/data/methods/get-slates-by-ids.js
+++ b/node_common/data/methods/get-slates-by-ids.js
@@ -1,14 +1,54 @@
+import * as Serializers from "~/node_common/serializers";
+
import { runQuery } from "~/node_common/data/utilities";
-export default async ({ ids }) => {
+export default async ({ ids, sanitize = false, includeFiles = false }) => {
return await runQuery({
label: "GET_SLATES_BY_IDS",
queryFn: async (DB) => {
- const query = await DB.select("*").from("slates").whereIn("id", ids);
+ // const slateFiles = () =>
+ // DB.raw("json_agg(?? order by ?? asc) as ??", ["files", "slate_files.createdAt", "objects"]);
+
+ const slateFiles = () =>
+ DB.raw("coalesce(json_agg(?? order by ?? asc) filter (where ?? is not null), '[]') as ??", [
+ "files",
+ "slate_files.createdAt",
+ "files.id",
+ "objects",
+ ]);
+
+ if (includeFiles) {
+ query = await DB.select(
+ "slates.id",
+ "slates.slatename",
+ "slates.data",
+ "slates.ownerId",
+ "slates.isPublic",
+ slateFiles()
+ )
+ .from("slates")
+ .leftJoin("slate_files", "slate_files.slateId", "=", "slates.id")
+ .leftJoin("files", "slate_files.fileId", "=", "files.id")
+ .whereIn("slates.id", ids)
+ .groupBy("slates.id");
+ } else {
+ query = await DB.select("id", "slatename", "data", "ownerId", "isPublic")
+ .from("slates")
+ .whereIn("id", ids);
+ }
+
if (!query || query.error) {
return [];
}
+ let serialized = [];
+ if (sanitize) {
+ for (let slate of query) {
+ serialized.push(Serializers.sanitizeSlate(slate));
+ }
+ return JSON.parse(JSON.stringify(serialized));
+ }
+
return JSON.parse(JSON.stringify(query));
},
errorFn: async (e) => {
diff --git a/node_common/data/methods/get-slates-by-user-id.js b/node_common/data/methods/get-slates-by-user-id.js
index 6ee8703c..f13035e1 100644
--- a/node_common/data/methods/get-slates-by-user-id.js
+++ b/node_common/data/methods/get-slates-by-user-id.js
@@ -1,32 +1,88 @@
+import * as Serializers from "~/node_common/serializers";
+
import { runQuery } from "~/node_common/data/utilities";
-export default async ({ userId, publicOnly = false }) => {
+export default async ({ ownerId, sanitize = false, includeFiles = false, publicOnly = false }) => {
return await runQuery({
label: "GET_SLATES_BY_USER_ID",
queryFn: async (DB) => {
- const hasUser = (id) =>
- DB.raw(`?? @> ?::jsonb`, ["data", JSON.stringify({ ownerId: id })]);
- const isPublic = () =>
- DB.raw(`?? @> ?::jsonb`, ["data", JSON.stringify({ public: true })]);
+ // const slateFiles = () =>
+ // DB.raw("json_agg(?? order by ?? asc) as ??", ["files", "slate_files.createdAt", "objects"]);
+
+ // const slateFiles = () =>
+ // DB.raw("coalesce(json_agg(?? order by ?? asc), '[]'::json) as ??", [
+ // "files",
+ // "slate_files.createdAt",
+ // "objects",
+ // ]);
+ const slateFiles = () =>
+ DB.raw("coalesce(json_agg(?? order by ?? asc) filter (where ?? is not null), '[]') as ??", [
+ "files",
+ "slate_files.createdAt",
+ "files.id",
+ "objects",
+ ]);
let query;
- if (publicOnly) {
- query = await DB.select("*")
- .from("slates")
- .where(hasUser(userId))
- .where(isPublic())
- .orderBy("updated_at", "desc");
+
+ if (includeFiles) {
+ if (publicOnly) {
+ query = await DB.select(
+ "slates.id",
+ "slates.slatename",
+ "slates.data",
+ "slates.ownerId",
+ "slates.isPublic",
+ slateFiles()
+ )
+ .from("slates")
+ .leftJoin("slate_files", "slate_files.slateId", "=", "slates.id")
+ .leftJoin("files", "slate_files.fileId", "=", "files.id")
+ .where({ "slates.ownerId": ownerId, "slates.isPublic": true })
+ .groupBy("slates.id")
+ .orderBy("slates.updatedAt", "desc");
+ } else {
+ query = await DB.select(
+ "slates.id",
+ "slates.slatename",
+ "slates.data",
+ "slates.ownerId",
+ "slates.isPublic",
+ slateFiles()
+ )
+ .from("slates")
+ .leftJoin("slate_files", "slate_files.slateId", "=", "slates.id")
+ .leftJoin("files", "slate_files.fileId", "=", "files.id")
+ .where({ "slates.ownerId": ownerId })
+ .groupBy("slates.id")
+ .orderBy("slates.updatedAt", "desc");
+ }
} else {
- query = await DB.select("*")
- .from("slates")
- .where(hasUser(userId))
- .orderBy("updated_at", "desc");
+ if (publicOnly) {
+ query = await DB.select("id", "slatename", "data", "ownerId", "isPublic")
+ .from("slates")
+ .where({ "slates.ownerId": ownerId, "slates.isPublic": true })
+ .orderBy("updatedAt", "desc");
+ } else {
+ query = await DB.select("id", "slatename", "data", "ownerId", "isPublic")
+ .from("slates")
+ .where({ "slates.ownerId": ownerId })
+ .orderBy("updatedAt", "desc");
+ }
}
if (!query || query.error) {
return [];
}
+ let serialized = [];
+ if (sanitize) {
+ for (let slate of query) {
+ serialized.push(Serializers.sanitizeSlate(slate));
+ }
+ return JSON.parse(JSON.stringify(serialized));
+ }
+
return JSON.parse(JSON.stringify(query));
},
errorFn: async (e) => {
diff --git a/node_common/data/methods/get-subscribers-by-slate-id.js b/node_common/data/methods/get-subscribers-by-slate-id.js
new file mode 100644
index 00000000..1b784a40
--- /dev/null
+++ b/node_common/data/methods/get-subscribers-by-slate-id.js
@@ -0,0 +1,35 @@
+import { runQuery } from "~/node_common/data/utilities";
+
+import * as Serializers from "~/node_common/serializers";
+
+export default async ({ slateId }) => {
+ return await runQuery({
+ label: "GET_SUBSCRIBERS_BY_SLATE_ID",
+ queryFn: async (DB) => {
+ const query = await DB.select("users.id", "users.username", "users.data")
+ .from("users")
+ .join("subscriptions", "subscriptions.ownerId", "=", "users.id")
+ .where({ "subscriptions.slateId": slateId })
+ .orderBy("subscriptions.createdAt", "desc");
+
+ if (!query || query.error) {
+ return [];
+ }
+
+ let serialized = [];
+ for (let user of query) {
+ serialized.push(Serializers.sanitizeUser(user));
+ }
+
+ return JSON.parse(JSON.stringify(serialized));
+ },
+ errorFn: async (e) => {
+ console.log({
+ error: true,
+ decorator: "GET_SUBSCRIBERS_BY_SLATE_ID",
+ });
+
+ return [];
+ },
+ });
+};
diff --git a/node_common/data/methods/get-subscribers-by-user-id.js b/node_common/data/methods/get-subscribers-by-user-id.js
deleted file mode 100644
index b2a5050e..00000000
--- a/node_common/data/methods/get-subscribers-by-user-id.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async ({ userId }) => {
- return await runQuery({
- label: "GET_SUBSCRIBERS_BY_USER_ID",
- queryFn: async (DB) => {
- const query = await DB.select("*")
- .from("subscriptions")
- .where({ target_user_id: userId });
-
- if (!query || query.error) {
- return [];
- }
-
- return JSON.parse(JSON.stringify(query));
- },
- errorFn: async (e) => {
- console.log({
- error: true,
- decorator: "GET_SUBSCRIBERS_BY_USER_ID",
- });
-
- return [];
- },
- });
-};
diff --git a/node_common/data/methods/get-subscription-by-id.js b/node_common/data/methods/get-subscription-by-id.js
deleted file mode 100644
index c5cc04ff..00000000
--- a/node_common/data/methods/get-subscription-by-id.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async ({ subscriberUserId, slateId, userId }) => {
- const whereQuery = { owner_user_id: subscriberUserId };
-
- if (slateId) {
- whereQuery.target_slate_id = slateId;
- }
-
- if (userId) {
- whereQuery.target_user_id = userId;
- }
-
- return await runQuery({
- label: "GET_SUBSCRIPTION_BY_ID",
- queryFn: async (DB) => {
- const query = await DB.select("*")
- .from("subscriptions")
- .where(whereQuery)
- .first();
-
- if (!query || query.error) {
- return null;
- }
-
- if (query.id) {
- return JSON.parse(JSON.stringify(query));
- }
-
- return null;
- },
- errorFn: async (e) => {
- return {
- error: true,
- decorator: "GET_SUBSCRIPTION_BY_ID",
- };
- },
- });
-};
diff --git a/node_common/data/methods/get-trusted-relationship-by-id.js b/node_common/data/methods/get-subscription.js
similarity index 51%
rename from node_common/data/methods/get-trusted-relationship-by-id.js
rename to node_common/data/methods/get-subscription.js
index 36be67d3..0eb44f75 100644
--- a/node_common/data/methods/get-trusted-relationship-by-id.js
+++ b/node_common/data/methods/get-subscription.js
@@ -1,10 +1,18 @@
import { runQuery } from "~/node_common/data/utilities";
-export default async ({ id }) => {
+export default async ({ ownerId, slateId, userId }) => {
+ let whereQuery;
+
+ if (slateId) {
+ whereQuery = { ownerId, slateId };
+ } else if (userId) {
+ whereQuery = { ownerId, userId };
+ }
+
return await runQuery({
- label: "GET_TRUSTED_RELATIONSHIP_BY_ID",
+ label: "GET_SUBSCRIPTION",
queryFn: async (DB) => {
- const query = await DB.select("*").from("trusted").where({ id }).first();
+ const query = await DB.select("*").from("subscriptions").where(whereQuery).first();
if (!query || query.error) {
return null;
@@ -19,7 +27,7 @@ export default async ({ id }) => {
errorFn: async (e) => {
return {
error: true,
- decorator: "GET_TRUSTED_RELATIONSHIP_BY_ID",
+ decorator: "GET_SUBSCRIPTION",
};
},
});
diff --git a/node_common/data/methods/get-subscriptions-by-user-id.js b/node_common/data/methods/get-subscriptions-by-user-id.js
index 8b7492a4..0b686f0c 100644
--- a/node_common/data/methods/get-subscriptions-by-user-id.js
+++ b/node_common/data/methods/get-subscriptions-by-user-id.js
@@ -1,18 +1,48 @@
import { runQuery } from "~/node_common/data/utilities";
-export default async ({ userId }) => {
+import * as Serializers from "~/node_common/serializers";
+
+export default async ({ ownerId }) => {
return await runQuery({
label: "GET_SUBSCRIPTIONS_BY_USER_ID",
queryFn: async (DB) => {
- const query = await DB.select("*")
- .from("subscriptions")
- .where({ owner_user_id: userId });
+ // const slateFiles = () =>
+ // DB.raw("json_agg(?? order by ?? asc) as ??", ["files", "slate_files.createdAt", "objects"]);
+
+ const slateFiles = () =>
+ DB.raw("coalesce(json_agg(?? order by ?? asc) filter (where ?? is not null), '[]') as ??", [
+ "files",
+ "slate_files.createdAt",
+ "files.id",
+ "objects",
+ ]);
+
+ const query = await DB.select(
+ "slates.id",
+ "slates.slatename",
+ "slates.data",
+ "slates.ownerId",
+ "slates.isPublic",
+ slateFiles()
+ )
+ .from("slates")
+ .join("subscriptions", "subscriptions.slateId", "=", "slates.id")
+ .join("slate_files", "slate_files.slateId", "=", "slates.id")
+ .join("files", "slate_files.fileId", "=", "files.id")
+ .where({ "subscriptions.ownerId": ownerId })
+ // .orderBy("subscriptions.createdAt", "desc");
+ .groupBy("slates.id");
if (!query || query.error) {
return [];
}
- return JSON.parse(JSON.stringify(query));
+ let serialized = [];
+ for (let slate of query) {
+ serialized.push(Serializers.sanitizeSlate(slate));
+ }
+
+ return JSON.parse(JSON.stringify(serialized));
},
errorFn: async (e) => {
console.log({
diff --git a/node_common/data/methods/get-subscriptions-to-slate-id.js b/node_common/data/methods/get-subscriptions-to-slate-id.js
deleted file mode 100644
index fa8903c8..00000000
--- a/node_common/data/methods/get-subscriptions-to-slate-id.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async ({ slateId }) => {
- return await runQuery({
- label: "GET_SUBSCRIPTIONS_TO_SLATE_ID",
- queryFn: async (DB) => {
- const query = await DB.select("*")
- .from("subscriptions")
- .where({ target_slate_id: slateId });
-
- if (!query || query.error) {
- return [];
- }
-
- return JSON.parse(JSON.stringify(query));
- },
- errorFn: async (e) => {
- console.log({
- error: true,
- decorator: "GET_SUBSCRIPTIONS_TO_SLATE_ID",
- });
-
- return [];
- },
- });
-};
diff --git a/node_common/data/methods/get-subscriptions-to-user-id.js b/node_common/data/methods/get-subscriptions-to-user-id.js
deleted file mode 100644
index dc9b8d1e..00000000
--- a/node_common/data/methods/get-subscriptions-to-user-id.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async ({ userId }) => {
- return await runQuery({
- label: "GET_SUBSCRIPTIONS_TO_USER_ID",
- queryFn: async (DB) => {
- const query = await DB.select("*")
- .from("subscriptions")
- .where({ target_user_id: userId });
-
- if (!query || query.error) {
- return [];
- }
-
- return JSON.parse(JSON.stringify(query));
- },
- errorFn: async (e) => {
- console.log({
- error: true,
- decorator: "GET_SUBSCRIPTIONS_TO_USER_ID",
- });
-
- return [];
- },
- });
-};
diff --git a/node_common/data/methods/get-trusted-relationship-by-ids.js b/node_common/data/methods/get-trusted-relationship-by-ids.js
deleted file mode 100644
index af85ee00..00000000
--- a/node_common/data/methods/get-trusted-relationship-by-ids.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async ({ ownerUserId, targetUserId }) => {
- return await runQuery({
- label: "GET_TRUSTED_RELATIONSHIP_BY_IDS",
- queryFn: async (DB) => {
- const query = await DB.select("*")
- .from("trusted")
- .where({ owner_user_id: ownerUserId, target_user_id: targetUserId })
- .first();
-
- if (!query || query.error) {
- return null;
- }
-
- if (query.id) {
- return JSON.parse(JSON.stringify(query));
- }
-
- return null;
- },
- errorFn: async (e) => {
- return {
- error: true,
- decorator: "GET_TRUSTED_RELATIONSHIP_BY_IDS",
- };
- },
- });
-};
diff --git a/node_common/data/methods/get-trusted-relationships-by-user-id.js b/node_common/data/methods/get-trusted-relationships-by-user-id.js
deleted file mode 100644
index e371532f..00000000
--- a/node_common/data/methods/get-trusted-relationships-by-user-id.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async ({ userId }) => {
- return await runQuery({
- label: "GET_TRUSTED_RELATIONSHIPS_BY_USER_ID",
- queryFn: async (DB) => {
- const query = await DB.select("*")
- .from("trusted")
- .where({ owner_user_id: userId });
-
- if (!query || query.error) {
- return [];
- }
-
- return JSON.parse(JSON.stringify(query));
- },
- errorFn: async (e) => {
- console.log({
- error: true,
- decorator: "GET_TRUSTED_RELATIONSHIPS_BY_USER_ID",
- });
-
- return [];
- },
- });
-};
diff --git a/node_common/data/methods/get-user-by-id.js b/node_common/data/methods/get-user-by-id.js
index 6fb3afd2..cbb24240 100644
--- a/node_common/data/methods/get-user-by-id.js
+++ b/node_common/data/methods/get-user-by-id.js
@@ -1,20 +1,91 @@
+import * as Serializers from "~/node_common/serializers";
+
import { runQuery } from "~/node_common/data/utilities";
-export default async ({ id }) => {
+/**
+ * Use sanitize = true if this data will be returned to some user other than the selected user.
+ * If just using the user data on the back end, there is no need to sanitize
+ * Use publicOnly = true to specify that only public files should be included when includeFiles is set to true
+ */
+export default async ({ id, sanitize = false, includeFiles = false, publicOnly = false }) => {
return await runQuery({
label: "GET_USER_BY_ID",
queryFn: async (DB) => {
- const query = await DB.select("*").from("users").where({ id }).first();
+ // const userFiles = () =>
+ // DB.raw("json_agg(?? order by ?? desc) as ??", ["files", "files.createdAt", "library"]);
+
+ const userFiles = () =>
+ DB.raw(
+ "coalesce(json_agg(?? order by ?? desc) filter (where ?? is not null), '[]') as ??",
+ ["files", "files.createdAt", "files.id", "library"]
+ );
+
+ let query;
+ if (includeFiles) {
+ if (publicOnly) {
+ //TODO(martina): fix this so can be done in one query. Right now, it's duplicating files for each slate_files entry. Need to do distinct on file.id for the json agg
+ // query = await DB.select(
+ // "users.id",
+ // "users.username",
+ // "users.data",
+ // "users.email",
+ // userFiles()
+ // )
+ // .from("users")
+ // .join("files", "files.ownerId", "users.id")
+ // .join("slate_files", "files.id", "=", "slate_files.fileId")
+ // .join("slates", "slates.id", "=", "slate_files.slateId")
+ // .where({ "users.id": id, "files.isPublic": true })
+ // .orWhere({ "users.id": id, "slates.isPublic": true })
+ // .groupBy("users.id")
+ // .first();
+
+ query = await DB.select("*").from("users").where({ id }).first();
+
+ let library = await DB.select(
+ "files.id",
+ "files.ownerId",
+ "files.cid",
+ "files.isPublic",
+ "files.filename",
+ "files.data"
+ )
+ .from("files")
+ .leftJoin("slate_files", "slate_files.fileId", "=", "files.id")
+ .leftJoin("slates", "slate_files.slateId", "=", "slates.id")
+ .where({ "files.ownerId": id, "slates.isPublic": true })
+ .orWhere({ "files.ownerId": id, "files.isPublic": true })
+ .orderBy("files.createdAt", "desc")
+ .groupBy("files.id");
+
+ query.library = library;
+ } else {
+ query = await DB.select(
+ "users.id",
+ "users.username",
+ "users.data",
+ "users.email",
+ userFiles()
+ )
+ .from("users")
+ .where({ "users.id": id })
+ .leftJoin("files", "files.ownerId", "users.id")
+ .groupBy("users.id")
+ .first();
+ }
+ } else {
+ query = await DB.select("*").from("users").where({ id }).first();
+ }
+
+ if (sanitize) {
+ query = Serializers.sanitizeUser(query);
+ }
if (!query || query.error) {
return null;
}
- if (query.id) {
- return JSON.parse(JSON.stringify(query));
- }
-
- return null;
+ return JSON.parse(JSON.stringify(query));
},
errorFn: async (e) => {
return {
diff --git a/node_common/data/methods/get-user-by-username.js b/node_common/data/methods/get-user-by-username.js
index 667bec5b..abfe9cac 100644
--- a/node_common/data/methods/get-user-by-username.js
+++ b/node_common/data/methods/get-user-by-username.js
@@ -1,23 +1,114 @@
+import * as Serializers from "~/node_common/serializers";
+
import { runQuery } from "~/node_common/data/utilities";
-export default async ({ username }) => {
+export default async ({ username, sanitize = false, includeFiles = false, publicOnly = false }) => {
return await runQuery({
label: "GET_USER_BY_USERNAME",
queryFn: async (DB) => {
- const query = await DB.select("*")
- .from("users")
- .where({ username })
- .first();
+ // const userFiles = () =>
+ // DB.raw("json_agg(?? order by ?? desc) as ??", ["files", "files.createdAt", "library"]);
+
+ const userFiles = () =>
+ DB.raw(
+ "coalesce(json_agg(?? order by ?? desc) filter (where ?? is not null), '[]') as ??",
+ ["files", "files.createdAt", "files.id", "library"]
+ );
+
+ let query;
+ if (includeFiles) {
+ if (publicOnly) {
+ // query = await DB.select(
+ // "users.id",
+ // "users.username",
+ // "users.data",
+ // "users.email",
+ // userFiles()
+ // )
+ // .from("users")
+ // .join("files", "files.ownerId", "users.id")
+ // .join("slate_files", "files.id", "=", "slate_files.fileId")
+ // .join("slates", "slates.id", "=", "slate_files.slateId")
+ // .where({ "users.username": username, "files.isPublic": true })
+ // .orWhere({ "users.username": username, "slates.isPublic": true })
+ // .groupBy("users.id");
+ // .first();
+
+ // let subquery = () =>
+ // DB.select(
+ // "files.id",
+ // "files.ownerId",
+ // "files.cid",
+ // "files.isPublic",
+ // "files.filename",
+ // "files.data"
+ // )
+ // .from("files")
+ // .join("slate_files", "files.id", "=", "slate_files.fileId")
+ // .join("slates", "slates.id", "=", "slate_files.slateId")
+ // .where({ "files.isPublic": true })
+ // .orWhere({ "slates.isPublic": true })
+ // .as("files");
+
+ // query = await DB.select(
+ // "users.id",
+ // "users.username",
+ // "users.data",
+ // "users.email",
+ // userFiles()
+ // )
+ // .from("users")
+ // .join(subquery(), "publicFiles.ownerId", "=", "users.id")
+ // .where({ "users.username": username })
+ // .groupBy("users.id")
+ // .first();
+ query = await DB.select("*").from("users").where({ username }).first();
+
+ const id = query.id;
+
+ let library = await DB.select(
+ "files.id",
+ "files.ownerId",
+ "files.cid",
+ "files.isPublic",
+ "files.filename",
+ "files.data"
+ )
+ .from("files")
+ .leftJoin("slate_files", "slate_files.fileId", "=", "files.id")
+ .leftJoin("slates", "slate_files.slateId", "=", "slates.id")
+ .where({ "files.ownerId": id, "slates.isPublic": true })
+ .orWhere({ "files.ownerId": id, "files.isPublic": true })
+ .orderBy("files.createdAt", "desc")
+ .groupBy("files.id");
+
+ query.library = library;
+ } else {
+ query = await DB.select(
+ "users.id",
+ "users.username",
+ "users.data",
+ "users.email",
+ userFiles()
+ )
+ .from("users")
+ .where({ "users.username": username })
+ .leftJoin("files", "files.ownerId", "users.id")
+ .first();
+ }
+ } else {
+ query = await DB.select("*").from("users").where({ username }).first();
+ }
if (!query || query.error) {
return null;
}
- if (query.id) {
- return JSON.parse(JSON.stringify(query));
+ if (sanitize) {
+ query = Serializers.sanitizeUser(query);
}
- return null;
+ return JSON.parse(JSON.stringify(query));
},
errorFn: async (e) => {
return {
diff --git a/node_common/data/methods/query-slates.js b/node_common/data/methods/query-slates.js
deleted file mode 100644
index f4c77437..00000000
--- a/node_common/data/methods/query-slates.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import * as Serializers from "~/node_common/serializers";
-
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async ({ query }) => {
- return await runQuery({
- label: "QUERY_SLATES",
- queryFn: async (DB) => {
- const r = await DB.select("id", "slatename", "data")
- .from("slates")
- .where("slatename", "like", `%${query}%`)
- .limit(24);
-
- if (!r || r.error) {
- return [];
- }
-
- const sanitized = r
- .filter((each) => each.data.public)
- .map((each) => Serializers.slate(each));
- return JSON.parse(JSON.stringify(sanitized));
- },
- errorFn: async (e) => {
- console.log({
- error: true,
- decorator: "QUERY_SLATES",
- });
-
- return [];
- },
- });
-};
diff --git a/node_common/data/methods/query-users.js b/node_common/data/methods/query-users.js
deleted file mode 100644
index 8ff5a0c5..00000000
--- a/node_common/data/methods/query-users.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import * as Serializers from "~/node_common/serializers";
-
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async ({ query }) => {
- return await runQuery({
- label: "QUERY_USERS",
- queryFn: async (DB) => {
- const r = await DB.select("id", "username", "data")
- .from("users")
- .where("username", "like", `%${query}%`)
- .limit(24);
-
- if (!r || r.error) {
- return [];
- }
-
- const sanitized = r.map((each) => Serializers.user(each));
- return JSON.parse(JSON.stringify(sanitized));
- },
- errorFn: async (e) => {
- console.log({
- error: true,
- decorator: "QUERY_USERS",
- });
-
- return [];
- },
- });
-};
diff --git a/node_common/data/methods/update-file-by-id.js b/node_common/data/methods/update-file-by-id.js
new file mode 100644
index 00000000..0c2387d6
--- /dev/null
+++ b/node_common/data/methods/update-file-by-id.js
@@ -0,0 +1,42 @@
+import * as Serializers from "~/node_common/serializers";
+
+import { runQuery } from "~/node_common/data/utilities";
+
+//NOTE(martina): if updating privacy, use the separate update-file-privacy function which will remove it from activity and slates as well
+
+//NOTE(martina): you can pass in an update object whose data component is incomplete (e.g. data: { name: "New name" }) without accidentally
+//wiping the rest of data b/c this updater method overlays it over the current value for data
+
+export default async ({ id, data }) => {
+ const updateObject = { id };
+
+ if (data) {
+ updateObject.data = data;
+ }
+
+ return await runQuery({
+ label: "UPDATE_FILE_BY_ID",
+ queryFn: async (DB) => {
+ let currentFile = await DB.from("files").where("id", id).first();
+
+ if (!currentFile || currentFile.error) {
+ return {
+ error: true,
+ decorator: "UPDATE_FILE_BY_ID_FILE_NOT_FOUND",
+ };
+ }
+
+ let updatedFile = Serializers.getUpdatedFile(currentFile, updateObject);
+
+ const response = await DB.from("files").where("id", id).update(updatedFile).returning("*");
+ const index = response ? response.pop() : null;
+ return JSON.parse(JSON.stringify(index));
+ },
+ errorFn: async (e) => {
+ return {
+ error: true,
+ decorator: "UPDATE_FILE_BY_ID",
+ };
+ },
+ });
+};
diff --git a/node_common/data/methods/update-file-privacy.js b/node_common/data/methods/update-file-privacy.js
new file mode 100644
index 00000000..8637e75f
--- /dev/null
+++ b/node_common/data/methods/update-file-privacy.js
@@ -0,0 +1,59 @@
+import { runQuery } from "~/node_common/data/utilities";
+
+export default async ({ id, ownerId, isPublic }) => {
+ return await runQuery({
+ label: "UPDATE_FILE_PRIVACY",
+ queryFn: async (DB) => {
+ if (isPublic === false) {
+ //NOTE(martina): if making a file private, remove any activity items involving it
+ const activity = await DB("activity").where("fileId", id).del();
+ console.log(activity);
+
+ //NOTE(martina): and nullify the fileId in any reposted slates to indicate it is no longer available
+ // const repostedSlateFiles = await DB.from("slate_files")
+ // .join("slates", "slates.id", "=", "slate_files.slateId")
+ // .whereNot("slates.ownerId", "=", ownerId)
+ // .where("slate_files.fileId", id)
+ // .update({ "slate_files.fileId": null })
+ // .returning("*");
+
+ const repostedSlateFiles = await DB.from("slate_files")
+ .whereIn("id", function () {
+ this.select("slate_files.id")
+ .from("slate_files")
+ .join("slates", "slates.id", "=", "slate_files.slateId")
+ .where({ "slate_files.fileId": id })
+ .whereNot("slates.ownerId", "=", ownerId);
+ })
+ .del();
+ // .update({ fileId: null })
+
+ //NOTE(martina): and remove it from any of the user's public slates
+ const publicSlatesContainingFile = await DB.from("slate_files")
+ .whereIn("id", function () {
+ this.select("slate_files.id")
+ .from("slate_files")
+ .join("slates", "slates.id", "=", "slate_files.slateId")
+ .where({
+ "slates.isPublic": true,
+ "slates.ownerId": ownerId,
+ "slate_files.fileId": id,
+ });
+ })
+ .del()
+ .returning("*");
+ }
+
+ const response = await DB.from("files").where("id", id).update({ isPublic }).returning("*");
+
+ const index = response ? response.pop() : null;
+ return JSON.parse(JSON.stringify(index));
+ },
+ errorFn: async (e) => {
+ return {
+ error: true,
+ decorator: "UPDATE_FILE_PRIVACY",
+ };
+ },
+ });
+};
diff --git a/node_common/data/methods/update-slate-by-id.js b/node_common/data/methods/update-slate-by-id.js
index 92b59d15..17af20c8 100644
--- a/node_common/data/methods/update-slate-by-id.js
+++ b/node_common/data/methods/update-slate-by-id.js
@@ -1,7 +1,22 @@
+import * as Serializers from "~/node_common/serializers";
+
import { runQuery } from "~/node_common/data/utilities";
-export default async ({ id, slatename, updated_at, data }) => {
- const updateObject = { data, updated_at };
+//NOTE(martina): if updating privacy, use the separate update-slate-privacy function which will remove it from activity as well
+
+//NOTE(martina): you can pass in an update object whose data component is incomplete (e.g. data: { name: "New name" }) without accidentally
+//wiping the rest of data b/c this updater method overlays it over the current value for data
+
+export default async ({ id, slatename, updatedAt, data }) => {
+ const updateObject = { id };
+
+ if (updatedAt) {
+ updateObject.updatedAt = updatedAt;
+ }
+
+ if (data) {
+ updateObject.data = data;
+ }
if (slatename) {
updateObject.slatename = slatename;
@@ -10,13 +25,21 @@ export default async ({ id, slatename, updated_at, data }) => {
return await runQuery({
label: "UPDATE_SLATE_BY_ID",
queryFn: async (DB) => {
- const response = await DB.from("slates")
- .where("id", id)
- .update(updateObject)
- .returning("*");
+ let currentSlate = await DB.from("slates").where("id", id).first();
+
+ if (!currentSlate || currentSlate.error) {
+ return {
+ error: true,
+ decorator: "UPDATE_SLATE_BY_ID_SLATE_NOT_FOUND",
+ };
+ }
+
+ let updatedSlate = Serializers.getUpdatedSlate(currentSlate, updateObject);
+
+ const response = await DB.from("slates").where("id", id).update(updatedSlate).returning("*");
const index = response ? response.pop() : null;
- return index;
+ return JSON.parse(JSON.stringify(index));
},
errorFn: async (e) => {
return {
diff --git a/node_common/data/methods/update-slate-privacy.js b/node_common/data/methods/update-slate-privacy.js
new file mode 100644
index 00000000..15ae999c
--- /dev/null
+++ b/node_common/data/methods/update-slate-privacy.js
@@ -0,0 +1,25 @@
+import { runQuery } from "~/node_common/data/utilities";
+
+export default async ({ id, isPublic }) => {
+ return await runQuery({
+ label: "UPDATE_SLATE_PRIVACY",
+ queryFn: async (DB) => {
+ if (!isPublic) {
+ const subscriptions = await DB("subscriptions").where({ slateId: id }).del();
+
+ const activity = await DB("activity").where("slateId", id).del();
+ }
+
+ const response = await DB.from("slates").where("id", id).update({ isPublic }).returning("*");
+
+ const index = response ? response.pop() : null;
+ return JSON.parse(JSON.stringify(index));
+ },
+ errorFn: async (e) => {
+ return {
+ error: true,
+ decorator: "UPDATE_SLATE_PRIVACY",
+ };
+ },
+ });
+};
diff --git a/node_common/data/methods/update-trusted-relationship-by-id.js b/node_common/data/methods/update-trusted-relationship-by-id.js
deleted file mode 100644
index 84dfa636..00000000
--- a/node_common/data/methods/update-trusted-relationship-by-id.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import { runQuery } from "~/node_common/data/utilities";
-
-export default async ({ id, data }) => {
- return await runQuery({
- label: "UPDATE_TRUSTED_RELATIONSHIP_BY_ID",
- queryFn: async (DB) => {
- const response = await DB.from("trusted")
- .where("id", id)
- .update({ data })
- .returning("*");
-
- const index = response ? response.pop() : null;
- return JSON.parse(JSON.stringify(index));
- },
- errorFn: async (e) => {
- return {
- error: true,
- decorator: "UPDATE_TRUSTED_RELATIONSHIP_BY_ID",
- };
- },
- });
-};
diff --git a/node_common/data/methods/update-user-by-id.js b/node_common/data/methods/update-user-by-id.js
index dc435b43..975cc71f 100644
--- a/node_common/data/methods/update-user-by-id.js
+++ b/node_common/data/methods/update-user-by-id.js
@@ -1,7 +1,10 @@
+import * as Serializers from "~/node_common/serializers";
+
import { runQuery } from "~/node_common/data/utilities";
-export default async ({ id, data, username, salt, password }) => {
- const updateObject = {};
+export default async ({ id, data, lastActive, username, salt, password }) => {
+ console.log(id);
+ const updateObject = { id, lastActive: lastActive || new Date() };
if (data) {
updateObject.data = data;
@@ -22,13 +25,21 @@ export default async ({ id, data, username, salt, password }) => {
return await runQuery({
label: "UPDATE_USER_BY_ID",
queryFn: async (DB) => {
- const response = await DB.from("users")
- .where("id", id)
- .update(updateObject)
- .returning("*");
+ let currentUser = await DB.from("users").where("id", id).first();
- const index = response ? response.pop() : null;
- return index;
+ if (!currentUser || currentUser.error) {
+ return {
+ error: true,
+ decorator: "UPDATE_USER_BY_ID_USER_NOT_FOUND",
+ };
+ }
+
+ let updatedUser = Serializers.getUpdatedUser(currentUser, updateObject);
+
+ const query = await DB.from("users").where("id", id).update(updatedUser).returning("*");
+
+ const index = query ? query.pop() : null;
+ return JSON.parse(JSON.stringify(index));
},
errorFn: async (e) => {
return {
diff --git a/node_common/managers/analytics.js b/node_common/managers/analytics.js
deleted file mode 100644
index 23a5e53d..00000000
--- a/node_common/managers/analytics.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import * as Utilities from "~/node_common/utilities";
-import * as Data from "~/node_common/data";
-import * as Powergate from "~/node_common/powergate";
-import * as Constants from "~/node_common/constants";
-
-export const get = async () => {
- // Current endpoints available for consumption
- // Endpoints: blocks, blockParents, blockRewards, blockMessages, receipts, messages
- const endpoint = "blocks";
- // const response = await fetch(Constants.ANALYTICS_URL + endpoint);
- // const analytics = response.json();
-
- // TODO(jim): re-enable when we use the data.
- return { disabled: true };
-};
diff --git a/node_common/managers/library.js b/node_common/managers/library.js
deleted file mode 100644
index 3fba0b81..00000000
--- a/node_common/managers/library.js
+++ /dev/null
@@ -1,169 +0,0 @@
-import { v4 as uuid } from "uuid";
-import { getFileExtension } from "../../common/strings";
-
-// NOTE(jim):
-// There is some Navigation specific data here for folders.
-export const createBucket = ({ id, name }) => {
- return {
- id,
- decorator: "FOLDER",
- icon: "FOLDER",
- name: name,
- pageTitle: `Exploring ${name}`,
- date: new Date(),
- size: null,
- children: [],
- };
-};
-
-// NOTE(jim):
-// Every root level user gets a bucket.
-export const init = ({ bucketName, readableName }) => [
- createBucket({ id: bucketName, name: readableName }),
-];
-
-export const createLocalDataIncomplete = ({ type, size, name }, id = null) => {
- return {
- id: !id ? `data-${uuid()}` : id,
- name: name,
- decorator: "FILE",
- icon: type,
- size: size,
- file: name,
- type: type,
- date: new Date(),
- networks: [],
- job: null,
- cid: null,
- storage: 0,
- retrieval: 0,
- };
-};
-
-export const updateDataIPFS = (d, { ipfs }) => {
- // TODO(jim): DELETE_THIS_GUARD_CODE
- if (!d.networks) {
- d.networks = [];
- delete d.network;
- }
-
- if (!d.networks.includes("IPFS")) {
- d.networks.push("IPFS");
- }
-
- return { ...d, cid: ipfs.replace("/ipfs/", ""), ipfs };
-};
-
-export const updateDataById = ({ user, id, data }) => {
- const { library } = user.data;
-
- for (let i = 0; i < library.length; i++) {
- for (let j = 0; j < library[i].children.length; j++) {
- if (library[i].children[j].id === id) {
- library[i].children[j] = data;
- return { ...user.data, library };
- }
- }
- }
-
- return { ...user.data, library };
-};
-
-export const getDataByCID = (user, cid) => {
- const { library } = user.data;
-
- // TODO(jim): Totally purges the ID.
- for (let i = 0; i < library.length; i++) {
- for (let j = 0; j < library[i].children.length; j++) {
- if (library[i].children[j].cid === cid) {
- return library[i].children[j];
- }
- }
- }
-
- return null;
-};
-
-export const addData = ({ user, files }) => {
- const { library } = user.data;
-
- // TODO(jim): Since we don't support bucket organization... yet.
- // Add just pushes to the first set. But we can change this easily later.
- let noRepeats = [];
- for (let file of files) {
- file.cid = file.cid || file.ipfs.replace("/ipfs/", "");
- delete file.ipfs;
- delete file.icon;
- noRepeats.push(file);
- }
-
- let newCids = [];
- for (let i = 0; i < library.length; i++) {
- let cids = library[i].children.map((file) => file.cid) || [];
- noRepeats = noRepeats.filter((item) => {
- let isNotRepeat = !cids.includes(item.cid) && !newCids.includes(item.cid);
- newCids.push(item.cid);
- return isNotRepeat;
- });
- }
-
- for (let i = 0; i < library.length; i++) {
- library[i].children = [...noRepeats, ...library[i].children];
- break;
- }
-
- return {
- updatedUserDataFields: { ...user.data, library },
- added: noRepeats.length,
- skipped: files.length - noRepeats.length,
- };
-};
-
-export const editItem = ({ user, update }) => {
- const { library } = user.data;
-
- // NOTE(daniel): handle multiple data updates to user library
- if (Array.isArray(update)) {
- update.forEach((item) => {
- for (let i = 0; i < library[0].children.length; i++) {
- if (library[0].children[i].id === item.data.id) {
- library[0].children[i] = {
- ...library[0].children[i],
- ...item.data,
- };
- }
- }
- });
-
- return user.data;
- }
-
- for (let i = 0; i < library[0].children.length; i++) {
- if (library[0].children[i].id === update.data.id) {
- library[0].children[i] = {
- ...library[0].children[i],
- ...update.data,
- // coverImage: update.data?.coverImage,
- // name: update.data?.name,
- };
- break;
- }
- }
- return user.data;
-};
-
-export const removeTagFromItems = ({ user, tag }) => {
- const { library } = user.data;
- for (let i = 0; i < library[0].children.length; i++) {
- let item = library[0].children[i];
-
- if (!item.tags) continue;
-
- let tagIndex = item.tags.indexOf(tag);
- if (tagIndex > -1) {
- item.tags.splice(tagIndex, 1);
- }
- }
-
- return user.data;
-};
diff --git a/node_common/managers/search.js b/node_common/managers/search.js
index 07db6aa3..4dae253d 100644
--- a/node_common/managers/search.js
+++ b/node_common/managers/search.js
@@ -6,6 +6,7 @@ import * as Serializers from "~/node_common/serializers";
import * as Strings from "~/common/strings";
import * as Websocket from "~/node_common/nodejs-websocket";
import * as NodeLogging from "~/node_common/node-logging";
+import * as Window from "~/common/window";
const websocketSend = async (type, data) => {
if (Strings.isEmpty(Environment.PUBSUB_SECRET)) {
@@ -14,7 +15,6 @@ const websocketSend = async (type, data) => {
const ws = Websocket.get();
if (!ws) {
- console.log("no websocket. creating now...");
ws = Websocket.create();
await Window.delay(2000);
}
@@ -40,22 +40,59 @@ export const updateUser = async (user, action) => {
NodeLogging.log(`Search is updating user ...`);
- const data = {
- data: { type: action, data: { ...Serializers.user(user), type: "USER" } },
+ let data;
+ if (Array.isArray(user)) {
+ data = user.map((item) => {
+ return { ...Serializers.sanitizeUser(item), type: "USER" };
+ });
+ } else {
+ data = { ...Serializers.sanitizeUser(user), type: "USER" };
+ }
+
+ websocketSend("UPDATE", {
id: "LENS",
- };
- websocketSend("UPDATE", data);
+ data: { action, data },
+ });
};
export const updateSlate = async (slate, action) => {
- console.log("UPDATE SEARCH for slate / files in slate");
+ console.log("UPDATE SEARCH for slate");
if (!slate || !action) return;
NodeLogging.log(`Search is updating slate ...`);
- const data = {
+ let data;
+ if (Array.isArray(slate)) {
+ data = slate.map((item) => {
+ return { ...Serializers.sanitizeSlate(item), type: "SLATE" };
+ });
+ } else {
+ data = { ...Serializers.sanitizeSlate(slate), type: "SLATE" };
+ }
+
+ websocketSend("UPDATE", {
id: "LENS",
- data: { type: action, data: { ...Serializers.slate(slate), type: "SLATE" } },
- };
- websocketSend("UPDATE", data);
+ data: { action, data },
+ });
+};
+
+export const updateFile = async (file, action) => {
+ console.log("UPDATE SEARCH for file");
+ if (!file || !action) return;
+
+ NodeLogging.log(`Search is updating file ...`);
+
+ let data;
+ if (Array.isArray(file)) {
+ data = file.map((item) => {
+ return { ...Serializers.sanitizeFile(item), type: "FILE" };
+ });
+ } else {
+ data = { ...Serializers.sanitizeFile(file), type: "FILE" };
+ }
+
+ websocketSend("UPDATE", {
+ id: "LENS",
+ data: { action, data },
+ });
};
diff --git a/node_common/managers/slate.js b/node_common/managers/slate.js
index 72e5973a..5cecf498 100644
--- a/node_common/managers/slate.js
+++ b/node_common/managers/slate.js
@@ -7,16 +7,16 @@ export const getRandomSlateElementURL = async ({ id, fallback = "" }) => {
return fallback;
}
- const query = await Data.getSlateById({ id });
+ const query = await Data.getSlateById({ id, includeFiles: true, sanitize: true });
if (!query || query.error) {
return fallback;
}
- if (!query.data.objects.length) {
+ if (!query.objects.length) {
return fallback;
}
- const index = Numbers.getRandomInt(0, query.data.objects.length - 1);
- return query.data.objects[index].url;
+ const index = Numbers.getRandomInt(0, query.objects.length - 1);
+ return Strings.getURLfromCID(query.objects[index].cid);
};
diff --git a/node_common/managers/viewer.js b/node_common/managers/viewer.js
index a47d1985..e3a544e8 100644
--- a/node_common/managers/viewer.js
+++ b/node_common/managers/viewer.js
@@ -18,7 +18,6 @@ const websocketSend = async (type, data) => {
let ws = Websocket.get();
if (!ws) {
- console.log("no websocket. creating now...");
ws = Websocket.create();
await Window.delay(2000);
}
@@ -38,154 +37,70 @@ const websocketSend = async (type, data) => {
);
};
-export const hydratePartialViewer = async (user) => {
- const data = {
- id: user.id,
- username: user.username,
- data: {
- name: user.data.name ? user.data.name : "",
- photo: user.data.photo ? user.data.photo : "",
- body: user.data.body ? user.data.body : "",
- },
- type: "PARTIAL_VIEWER",
- library: user.data.library,
- onboarding: user.data.onboarding || {},
+export const hydratePartial = async (
+ id,
+ { viewer, slates, keys, library, subscriptions, following, followers }
+) => {
+ if (!id) return;
- // TODO(jim): Move this elsewhere.
- allow_filecoin_directory_listing: user.data.allow_filecoin_directory_listing
- ? user.data.allow_filecoin_directory_listing
- : null,
- allow_automatic_data_storage: user.data.allow_automatic_data_storage
- ? user.data.allow_automatic_data_storage
- : null,
- allow_encrypted_data_storage: user.data.allow_encrypted_data_storage
- ? user.data.allow_encrypted_data_storage
- : null,
- };
+ let update = { id };
- websocketSend("UPDATE", data);
-};
-
-export const hydratePartialStatus = async (status, userId) => {
- console.log("HYDRATE partial status");
- const data = {
- id: userId,
- status,
- };
- websocketSend("UPDATE", data);
-};
-
-export const hydratePartialSubscriptions = async (updated, userId) => {
- console.log("HYDRATE partial subscriptions");
- const data = {
- id: userId,
- };
-
- const user = await Data.getUserById({ id: userId });
- if (!user) {
- return null;
+ if (viewer) {
+ let user;
+ if (library) {
+ user = await Data.getUserById({
+ id,
+ includeFiles: true,
+ });
+ } else {
+ user = await Data.getUserById({
+ id,
+ });
+ }
+ update = {
+ ...update,
+ username: user.username,
+ email: user.email,
+ data: user.data,
+ library: user.library,
+ };
+ } else if (library) {
+ library = await Data.getFilesByUserId({ id, sanitize: true, publicOnly: false });
+ update.library = library;
}
- if (user.error) {
- return null;
- }
-
- let mostRecent;
- if (updated.subscriptions) {
- const subscriptions = await Data.getSubscriptionsByUserId({ userId });
- let r1 = await Serializers.doSubscriptions({
- users: [],
- slates: [],
- subscriptions,
- serializedUsersMap: { [user.id]: Serializers.user(user) },
- serializedSlatesMap: {},
+ if (slates) {
+ const slates = await Data.getSlatesByUserId({
+ ownerId: id,
+ sanitize: true,
+ includeFiles: true,
});
- data.subscriptions = r1.serializedSubscriptions;
- mostRecent = r1;
+ update.slates = slates;
}
- if (updated.subscribers) {
- const subscribers = await Data.getSubscribersByUserId({ userId });
- let r2 = await Serializers.doSubscribers({
- users: [],
- slates: [],
- subscribers,
- serializedUsersMap: mostRecent
- ? mostRecent.serializedUsersMap
- : { [user.id]: Serializers.user(user) },
- serializedSlatesMap: mostRecent ? mostRecent.serializedSlatesMap : {},
- });
- data.subscribers = r2.serializedSubscribers;
- mostRecent = r2;
+ if (keys) {
+ const keys = await Data.getAPIKeysByUserId({ userId: id });
+ update.keys = keys;
}
- // if (updated.trusted) {
- // const trusted = await Data.getTrustedRelationshipsByUserId({ userId });
- // let r3 = await Serializers.doTrusted({
- // users: [],
- // trusted,
- // serializedUsersMap: mostRecent
- // ? mostRecent.serializedUsersMap
- // : { [user.id]: Serializers.user(user) },
- // serializedSlatesMap: mostRecent ? mostRecent.serializedSlatesMap : {},
- // });
- // data.trusted = r3.serializedTrusted;
- // mostRecent = r3;
- // }
+ if (subscriptions) {
+ const subscriptions = await Data.getSubscriptionsByUserId({ ownerId: id });
+ update.subscriptions = subscriptions;
+ }
- // if (updated.pendingTrusted) {
- // const pendingTrusted = await Data.getPendingTrustedRelationshipsByUserId({
- // userId,
- // });
- // let r4 = await Serializers.doPendingTrusted({
- // users: [userId],
- // pendingTrusted,
- // serializedUsersMap: mostRecent
- // ? mostRecent.serializedUsersMap
- // : { [user.id]: Serializers.user(user) },
- // serializedSlatesMap: mostRecent ? mostRecent.serializedSlatesMap : {},
- // });
- // data.pendingTrusted = r4.serializedPendingTrusted;
- // }
+ if (following) {
+ const following = await Data.getFollowingByUserId({ ownerId: id });
+ update.following = following;
+ }
- websocketSend("UPDATE", data);
+ if (followers) {
+ const followers = await Data.getFollowersByUserId({ userId: id });
+ update.followers = followers;
+ }
+
+ websocketSend("UPDATE", update);
};
-export const hydratePartialKeys = async (keys, userId) => {
- console.log("HYDRATE partial keys");
- const data = {
- id: userId,
- keys,
- };
-
- websocketSend("UPDATE", data);
-};
-
-export const hydratePartialLibrary = async (library, userId) => {
- console.log("HYDRATE partial library");
- const data = {
- id: userId,
- library,
- };
-
- websocketSend("UPDATE", data);
-};
-
-export const hydratePartialSlates = async (slates, userId) => {
- console.log("HYDRATE partial slates");
- const data = {
- id: userId,
- slates,
- };
-
- websocketSend("UPDATE", data);
-};
-
-// export const hydratePartialActivity = async (activity, userId) => {
-// this one will need to be more complex like what is in hydrate subscriptions
-// websocketSend("UPDATE", data);
-// };
-
export const hydrate = async (id) => {
let data = getById({ id });
websocketSend("UPDATE", data);
@@ -209,10 +124,18 @@ export const shouldRedirect = async ({ id }) => {
// TODO(jim): Work on better serialization when adoption starts occuring.
export const getById = async ({ id }) => {
- const user = await Data.getUserById({
+ let user = await Data.getUserById({
id,
+ includeFiles: true,
});
+ // try {
+ // JSON.stringify(user);
+ // } catch (e) {
+ // console.log(user);
+ // console.log("errored on json.stringify user (1st time)");
+ // }
+
if (!user) {
return null;
}
@@ -221,104 +144,69 @@ export const getById = async ({ id }) => {
return null;
}
- // TODO(jim): You can serialize this last because you will have all the information
- // from subscriptions, trusted, and pendingTrusted most likely.
- const slates = await Data.getSlatesByUserId({ userId: id });
+ // user.library = await Data.getFilesByUserId({ id, sanitize: true });
+
+ const slates = await Data.getSlatesByUserId({
+ ownerId: id,
+ sanitize: true,
+ includeFiles: true,
+ });
const keys = await Data.getAPIKeysByUserId({ userId: id });
- const subscriptions = await Data.getSubscriptionsByUserId({ userId: id });
- const subscribers = await Data.getSubscribersByUserId({ userId: id });
-
- let serializedUsersMap = { [user.id]: Serializers.user(user) };
- let serializedSlatesMap = {};
-
- // NOTE(jim): The most expensive call first.
- const r1 = await Serializers.doSubscriptions({
- users: [],
- slates: [],
- subscriptions,
- serializedUsersMap,
- serializedSlatesMap,
- });
-
- const r2 = await Serializers.doSubscribers({
- users: [],
- slates: [],
- subscribers,
- serializedUsersMap: r1.serializedUsersMap,
- serializedSlatesMap: r1.serializedSlatesMap,
- });
-
- // // NOTE(jim): If any trusted users are subscription users, this ends up being cheaper.
- // const trusted = await Data.getTrustedRelationshipsByUserId({ userId: id });
- // const r3 = await Serializers.doTrusted({
- // users: [],
- // trusted,
- // serializedUsersMap: r2.serializedUsersMap,
- // serializedSlatesMap: r2.serializedSlatesMap,
- // });
-
- // // NOTE(jim): This should be the cheapest call.
- // const pendingTrusted = await Data.getPendingTrustedRelationshipsByUserId({
- // userId: id,
- // });
- // const r4 = await Serializers.doPendingTrusted({
- // users: [id],
- // pendingTrusted,
- // serializedUsersMap: r3.serializedUsersMap,
- // serializedSlatesMap: r3.serializedSlatesMap,
- // });
+ const subscriptions = await Data.getSubscriptionsByUserId({ ownerId: id });
+ const following = await Data.getFollowingByUserId({ ownerId: id });
+ const followers = await Data.getFollowersByUserId({ userId: id });
+ let cids = {};
let bytes = 0;
let imageBytes = 0;
let videoBytes = 0;
let audioBytes = 0;
let epubBytes = 0;
let pdfBytes = 0;
- user.data.library[0].children.forEach((each) => {
- if (each.type && each.type.startsWith("image/")) {
- imageBytes += each.size;
- } else if (each.type && each.type.startsWith("video/")) {
- videoBytes += each.size;
- } else if (each.type && each.type.startsWith("audio/")) {
- audioBytes += each.size;
- } else if (each.type && each.type.startsWith("application/epub")) {
- epubBytes += each.size;
- } else if (each.type && each.type.startsWith("application/pdf")) {
- pdfBytes += each.size;
+ for (let each of user.library) {
+ if (cids[each.cid]) {
+ continue;
}
- if (each.coverImage) {
- imageBytes += each.coverImage.size;
+ if (each.data.type && each.data.type.startsWith("image/")) {
+ imageBytes += each.data.size;
+ } else if (each.data.type && each.data.type.startsWith("video/")) {
+ videoBytes += each.data.size;
+ } else if (each.data.type && each.data.type.startsWith("audio/")) {
+ audioBytes += each.data.size;
+ } else if (each.data.type && each.data.type.startsWith("application/epub")) {
+ epubBytes += each.data.size;
+ } else if (each.data.type && each.data.type.startsWith("application/pdf")) {
+ pdfBytes += each.data.size;
}
- bytes += each.size;
- });
+ let coverImage = each.data.coverImage;
+ if (coverImage && !cids[coverImage.cid]) {
+ imageBytes += coverImage.data.size;
+ cids[coverImage.cid] = true;
+ }
+ bytes += each.data.size;
+ cids[each.cid] = true;
+ }
- const tags = Utilities.getUserTags({ library: user.data.library[0].children, slates });
+const tags = Utilities.getUserTags({ library: user.library, slates });
- const { bucketRoot } = await Utilities.getBucketAPIFromUserToken({
- user,
- });
+const { bucketRoot } = await Utilities.getBucketAPIFromUserToken({
+ user,
+});
- return {
- ...Serializers.user(user),
- type: "VIEWER",
- library: user.data.library,
- onboarding: user.data.onboarding || {},
- status: user.data.status || {},
- tags,
- userBucketCID: bucketRoot?.path,
-
- // TODO(jim): Move this elsewhere.
- allow_filecoin_directory_listing: user.data.allow_filecoin_directory_listing
- ? user.data.allow_filecoin_directory_listing
- : null,
- allow_automatic_data_storage: user.data.allow_automatic_data_storage
- ? user.data.allow_automatic_data_storage
- : null,
- allow_encrypted_data_storage: user.data.allow_encrypted_data_storage
- ? user.data.allow_encrypted_data_storage
- : null,
-
- // NOTE(jim): Remaining data.
+ let viewer = {
+ id: user.id,
+ username: user.username,
+ email: user.email,
+ data: user.data,
+ library: user.library,
+ // onboarding: user.data.onboarding || {},
+ // status: user.data.status || {},
+ // settings: {
+ // allow_automatic_data_storage: user.data.allow_automatic_data_storage || null,
+ // allow_encrypted_data_storage: user.data.allow_encrypted_data_storage || null,
+ // allow_filecoin_directory_listing: user.data.allow_filecoin_directory_listing || null,
+ // settings_deals_auto_approve: user.data.settings_deals_auto_approve || null,
+ // },
stats: {
bytes,
maximumBytes: Constants.TEXTILE_ACCOUNT_BYTE_LIMIT,
@@ -328,13 +216,23 @@ export const getById = async ({ id }) => {
epubBytes,
pdfBytes,
},
+ tags,
+ userBucketCID: bucketRoot?.path,
keys,
slates,
- subscriptions: r1.serializedSubscriptions,
- subscribers: r2.serializedSubscribers,
- // trusted: r3.serializedTrusted,
- // pendingTrusted: r4.serializedPendingTrusted,
+ subscriptions,
+ following,
+ followers,
};
+
+ // try {
+ // JSON.stringify(viewer);
+ // } catch (e) {
+ // console.log(viewer);
+ // console.log("errored on json.stringify viewer (2nd time)");
+ // }
+
+ return viewer;
};
export const getDealHistory = async ({ id }) => {
@@ -389,7 +287,7 @@ export const getDealHistory = async ({ id }) => {
time: o.time,
createdAt: Strings.toDateSinceEpoch(o.time),
pending: o.pending,
- user: Serializers.user(user),
+ user: Serializers.sanitizeUser(user),
});
}
} catch (e) {
@@ -403,7 +301,7 @@ export const getDealHistory = async ({ id }) => {
});
}
- return { type: "VIEWER_FILECOIN_DEALS", deals };
+ return { deals };
};
export const getTextileById = async ({ id }) => {
@@ -492,7 +390,6 @@ export const getTextileById = async ({ id }) => {
const settings = await b.buckets.defaultArchiveConfig(b.bucketKey);
return {
- type: "VIEWER_FILECOIN",
settings: {
...settings,
addr: addresses[0].address,
diff --git a/node_common/monitor.js b/node_common/monitor.js
index 558921d4..ba95fafb 100644
--- a/node_common/monitor.js
+++ b/node_common/monitor.js
@@ -3,14 +3,14 @@ import * as Social from "~/node_common/social";
export const deal = ({ userId, data }) => {
try {
- Data.createOrUpdateStats(new Date(), { deals: 1 });
+ // Data.createOrUpdateStats(new Date(), { deals: 1 });
// NOTE(jim):
// , CREATED DEAL
- Data.createActivity({
- userId,
- data: { type: "USER_DEAL", actorUserId: data.actorUserId, context: data.context },
- });
+ // Data.createActivity({
+ // userId,
+ // data: { type: "USER_DEAL", actorUserId: data.actorUserId, context: data.context },
+ // });
const userProfileURL = `https://slate.host/${data.context.username}`;
const userURL = `<${userProfileURL}|${data.context.username}>`;
@@ -22,19 +22,14 @@ export const deal = ({ userId, data }) => {
}
};
-export const createUser = ({ userId, data }) => {
+export const createUser = ({ user }) => {
try {
- Data.createOrUpdateStats(new Date(), { users: 1 });
+ // Data.createOrUpdateStats(new Date(), { users: 1 });
// NOTE(jim):
// , CREATED ACCOUNT
- Data.createActivity({
- userId,
- data: { type: "CREATE_USER", actorUserId: data.actorUserId, context: data.context },
- });
-
- const userProfileURL = `https://slate.host/${data.context.username}`;
- const userURL = `<${userProfileURL}|${data.context.username}>`;
+ const userProfileURL = `https://slate.host/${user.username}`;
+ const userURL = `<${userProfileURL}|${user.username}>`;
const message = `*${userURL}* joined the movement.`;
Social.sendSlackMessage(message);
@@ -43,55 +38,54 @@ export const createUser = ({ userId, data }) => {
}
};
-const createSlateActivityForEachSubscriber = async ({ userId, data }) => {
- const subscriptions = await Data.getSubscriptionsToUserId({ userId });
+// const createSlateActivityForEachSubscriber = async ({ userId, data }) => {
+// const subscriptions = await Data.getSubscriptionsToUserId({ userId });
- if (subscriptions.length) {
- for (let i = 0; i < subscriptions.length; i++) {
- const s = subscriptions[i];
+// if (subscriptions.length) {
+// for (let i = 0; i < subscriptions.length; i++) {
+// const s = subscriptions[i];
- // NOTE(jim):
- // CREATED
- Data.createActivity({
- userId: s.owner_user_id,
- data: {
- type: "SUBSCRIBED_CREATE_SLATE",
- actorUserId: data.actorUserId,
- context: data.context,
- },
- });
- }
- }
+// // NOTE(jim):
+// // CREATED
+// Data.createActivity({
+// userId: s.owner_user_id,
+// data: {
+// type: "SUBSCRIBED_CREATE_SLATE",
+// actorUserId: data.actorUserId,
+// context: data.context,
+// },
+// });
+// }
+// }
- //NOTE(martina): creates the activity event used for explore/discover
- Data.createActivity({
- userId: "SLATE",
- data: {
- type: "SUBSCRIBED_CREATE_SLATE",
- actorUserId: data.actorUserId,
- context: data.context,
- },
- });
-};
+// //NOTE(martina): creates the activity event used for explore/discover
+// Data.createActivity({
+// userId: "SLATE",
+// data: {
+// type: "SUBSCRIBED_CREATE_SLATE",
+// actorUserId: data.actorUserId,
+// context: data.context,
+// },
+// });
+// };
+
+export const createSlate = ({ user, slate }) => {
+ // Data.createOrUpdateStats(new Date(), { slates: 1 });
+
+ if (!slate.isPublic) return;
-export const createSlate = ({ userId, data }) => {
try {
- Data.createOrUpdateStats(new Date(), { slates: 1 });
-
// NOTE(jim):
// CREATED
Data.createActivity({
- userId,
- data: { type: "CREATE_SLATE", actorUserId: data.actorUserId, context: data.context },
+ ownerId: user.id,
+ slateId: slate.id,
+ type: "CREATE_SLATE",
});
- // NOTE(JIM):
- // WITNESSES CREATING
- createSlateActivityForEachSubscriber({ userId, data });
-
- const userProfileURL = `https://slate.host/${data.context.user.username}`;
- const userURL = `<${userProfileURL}|${data.context.user.username}>`;
- const message = `*${userURL}* created a slate: https://slate.host/${data.context.user.username}/${data.context.slate.slatename}`;
+ const userProfileURL = `https://slate.host/${user.username}`;
+ const userURL = `<${userProfileURL}|${user.username}>`;
+ const message = `*${userURL}* created a slate: https://slate.host/${user.username}/${slate.slatename}`;
Social.sendSlackMessage(message);
} catch (e) {
@@ -99,84 +93,117 @@ export const createSlate = ({ userId, data }) => {
}
};
-const createSlateObjectActivityForEachSubscriber = async ({ slateId, userId, data }) => {
- let subscriptions = await Data.getSubscriptionsToUserId({ userId });
+// const createSlateObjectActivityForEachSubscriber = async ({ slateId, userId, data }) => {
+// let subscriptions = await Data.getSubscriptionsToUserId({ userId });
- if (subscriptions.length) {
- for (let i = 0; i < subscriptions.length; i++) {
- const s = subscriptions[i];
+// if (subscriptions.length) {
+// for (let i = 0; i < subscriptions.length; i++) {
+// const s = subscriptions[i];
- // NOTE(jim):
- // WITNESS ADDED OBJECT TO
- Data.createActivity({
- userId: s.owner_user_id,
- data: {
- type: "SUBSCRIBED_ADD_TO_SLATE",
- actorUserId: data.actorUserId,
- context: data.context,
- },
- });
- }
+// // NOTE(jim):
+// // WITNESS ADDED OBJECT TO
+// Data.createActivity({
+// userId: s.owner_user_id,
+// data: {
+// type: "SUBSCRIBED_ADD_TO_SLATE",
+// actorUserId: data.actorUserId,
+// context: data.context,
+// },
+// });
+// }
+// }
+
+// subscriptions = await Data.getSubscriptionsToSlateId({ slateId });
+
+// if (subscriptions.length) {
+// for (let i = 0; i < subscriptions.length; i++) {
+// const s = subscriptions[i];
+
+// // NOTE(jim):
+// // WITNESS ADDED OBJECT TO
+// Data.createActivity({
+// userId: s.owner_user_id,
+// data: {
+// type: "SUBSCRIBED_ADD_TO_SLATE",
+// actorUserId: data.actorUserId,
+// context: data.context,
+// },
+// });
+// }
+// }
+
+// //NOTE(martina): creates the activity event used for explore/discover
+// Data.createActivity({
+// userId: "SLATE",
+// data: {
+// type: "SUBSCRIBED_ADD_TO_SLATE",
+// actorUserId: data.actorUserId,
+// context: data.context,
+// },
+// });
+// };
+
+// export const createSlateObject = ({ slateId, userId, data }) => {
+// Data.createOrUpdateStats(new Date(), { objects: 1 });
+
+// // TODO(jim): We may do some private tracking here.
+// if (data.context.private) {
+// return;
+// }
+
+// try {
+// // NOTE(jim):
+// // ADDED TO
+// Data.createActivity({
+// slateId,
+// data: {
+// type: "CREATE_SLATE_OBJECT",
+// actorUserId: data.actorUserId,
+// context: data.context,
+// },
+// });
+
+// // NOTE(jim):
+// // WITNESS ADDED OBJECT TO
+// createSlateObjectActivityForEachSubscriber({ slateId, userId, data });
+
+// const userProfileURL = `https://slate.host/${data.context.user.username}`;
+// const userURL = `<${userProfileURL}|${data.context.user.username}>`;
+// const objectURL = ``;
+// const message = `*${userURL}* added ${objectURL} to https://slate.host/${data.context.user.username}/${data.context.slate.slatename}`;
+
+// Social.sendSlackMessage(message);
+// } catch (e) {
+// console.log(e);
+// }
+// };
+
+export const createSlateObjects = ({ slate, user, files }) => {
+ // Data.createOrUpdateStats(new Date(), { objects: files.length });
+ console.log("inside create slate objects");
+ if (!slate.isPublic) return;
+
+ let activityItems = [];
+ for (let file of files) {
+ activityItems.push({
+ ownerId: user.id,
+ slateId: slate.id,
+ fileId: file.id,
+ type: "CREATE_SLATE_OBJECT",
+ });
}
-
- subscriptions = await Data.getSubscriptionsToSlateId({ slateId });
-
- if (subscriptions.length) {
- for (let i = 0; i < subscriptions.length; i++) {
- const s = subscriptions[i];
-
- // NOTE(jim):
- // WITNESS ADDED OBJECT TO
- Data.createActivity({
- userId: s.owner_user_id,
- data: {
- type: "SUBSCRIBED_ADD_TO_SLATE",
- actorUserId: data.actorUserId,
- context: data.context,
- },
- });
- }
- }
-
- //NOTE(martina): creates the activity event used for explore/discover
- Data.createActivity({
- userId: "SLATE",
- data: {
- type: "SUBSCRIBED_ADD_TO_SLATE",
- actorUserId: data.actorUserId,
- context: data.context,
- },
- });
-};
-
-export const createSlateObject = ({ slateId, userId, data }) => {
- Data.createOrUpdateStats(new Date(), { objects: 1 });
-
- // TODO(jim): We may do some private tracking here.
- if (data.context.private) {
- return;
- }
-
+ console.log(activityItems);
try {
- // NOTE(jim):
- // ADDED TO
- Data.createActivity({
- slateId,
- data: {
- type: "CREATE_SLATE_OBJECT",
- actorUserId: data.actorUserId,
- context: data.context,
- },
- });
+ Data.createActivity(activityItems);
- // NOTE(jim):
- // WITNESS ADDED OBJECT TO
- createSlateObjectActivityForEachSubscriber({ slateId, userId, data });
-
- const userProfileURL = `https://slate.host/${data.context.user.username}`;
- const userURL = `<${userProfileURL}|${data.context.user.username}>`;
- const objectURL = ``;
- const message = `*${userURL}* added ${objectURL} to https://slate.host/${data.context.user.username}/${data.context.slate.slatename}`;
+ const userProfileURL = `https://slate.host/${user.username}`;
+ const userURL = `<${userProfileURL}|${user.username}>`;
+ const objectURL = ``;
+ const extra =
+ files.length > 1
+ ? `and ${files.length - 1} other file${files.length - 1 > 1 ? "s " : " "}`
+ : "";
+ const message = `*${userURL}* added ${objectURL} ${extra}to https://slate.host/${user.username}/${slate.slatename}`;
Social.sendSlackMessage(message);
} catch (e) {
@@ -184,62 +211,62 @@ export const createSlateObject = ({ slateId, userId, data }) => {
}
};
-const createSubscribeUserActivityForEachSubscriber = async ({ userId, data }) => {
- const subscriptions = await Data.getSubscriptionsToUserId({ userId });
+// const createSubscribeUserActivityForEachSubscriber = async ({ userId, data }) => {
+// const subscriptions = await Data.getSubscriptionsToUserId({ userId });
- if (subscriptions.length) {
- for (let i = 0; i < subscriptions.length; i++) {
- const s = subscriptions[i];
+// if (subscriptions.length) {
+// for (let i = 0; i < subscriptions.length; i++) {
+// const s = subscriptions[i];
- // NOTE(jim):
- // , SUBSCRIBED TO
- Data.createActivity({
- userId: s.owner_user_id,
- data: {
- type: "USER_SUBSCRIBED_TO_SUBSCRIBED_USER",
- actorUserId: data.actorUserId,
- context: data.context,
- },
- });
- }
- }
-};
+// // NOTE(jim):
+// // , SUBSCRIBED TO
+// Data.createActivity({
+// userId: s.owner_user_id,
+// data: {
+// type: "USER_SUBSCRIBED_TO_SUBSCRIBED_USER",
+// actorUserId: data.actorUserId,
+// context: data.context,
+// },
+// });
+// }
+// }
+// };
-export const subscribeUser = ({ userId, data }) => {
- Data.createOrUpdateStats(new Date(), { subscribeUsers: 1 });
+export const subscribeUser = ({ user, targetUser }) => {
+ // Data.createOrUpdateStats(new Date(), { subscribeUsers: 1 });
try {
// NOTE(jim):
// , YOU SUBSCRIBED TO
- Data.createActivity({
- userId,
- data: {
- type: "SUBSCRIBE_USER",
- actorUserId: data.actorUserId,
- context: data.context,
- },
- });
+ // Data.createActivity({
+ // userId,
+ // data: {
+ // type: "SUBSCRIBE_USER",
+ // actorUserId: data.actorUserId,
+ // context: data.context,
+ // },
+ // });
// NOTE(jim):
// . SUBSCRIBED TO
- Data.createActivity({
- userId: data.context.targetUserId,
- data: {
- type: "RECEIVED_SUBSCRIBER",
- actorUserId: data.actorUserId,
- context: data.context,
- },
- });
+ // Data.createActivity({
+ // userId: data.context.targetUserId,
+ // data: {
+ // type: "RECEIVED_SUBSCRIBER",
+ // actorUserId: data.actorUserId,
+ // context: data.context,
+ // },
+ // });
// NOTE(jim):
// WITNESSES SUBSCRIBE TO
// createSubscribeUserActivityForEachSubscriber({ userId, data });
- const userProfileURL = `https://slate.host/${data.context.username}`;
- const userURL = `<${userProfileURL}|${data.context.username}>`;
+ const userProfileURL = `https://slate.host/${user.username}`;
+ const userURL = `<${userProfileURL}|${user.username}>`;
- const targetUserProfileURL = `https://slate.host/${data.context.targetUsername}`;
- const targetUserURL = `<${targetUserProfileURL}|${data.context.targetUsername}>`;
+ const targetUserProfileURL = `https://slate.host/${targetUser.username}`;
+ const targetUserURL = `<${targetUserProfileURL}|${targetUser.username}>`;
const message = `*${userURL}* subscribed to ${targetUserURL}`;
Social.sendSlackMessage(message);
@@ -248,37 +275,37 @@ export const subscribeUser = ({ userId, data }) => {
}
};
-export const subscribeSlate = ({ slateId, data }) => {
- Data.createOrUpdateStats(new Date(), { subscribeSlates: 1 });
+export const subscribeSlate = ({ user, targetSlate }) => {
+ // Data.createOrUpdateStats(new Date(), { subscribeSlates: 1 });
try {
// NOTE(jim):
// , HAS SUBSCRIBED
- Data.createActivity({
- slateId,
- data: {
- type: "USER_SUBSCRIBED_SLATE",
- actorUserId: data.actorUserId,
- context: data.context,
- },
- });
+ // Data.createActivity({
+ // slateId,
+ // data: {
+ // type: "USER_SUBSCRIBED_SLATE",
+ // actorUserId: data.actorUserId,
+ // context: data.context,
+ // },
+ // });
// NOTE(jim):
// , YOU HAVE SUBSCRIBED TO
- Data.createActivity({
- userId: data.actorUserId,
- data: {
- type: "SUBSCRIBE_SLATE",
- actorUserId: data.actorUserId,
- context: data.context,
- },
- });
+ // Data.createActivity({
+ // userId: data.actorUserId,
+ // data: {
+ // type: "SUBSCRIBE_SLATE",
+ // actorUserId: data.actorUserId,
+ // context: data.context,
+ // },
+ // });
- const userProfileURL = `https://slate.host/${data.context.username}`;
- const userURL = `<${userProfileURL}|${data.context.username}>`;
+ const userProfileURL = `https://slate.host/${user.username}`;
+ const userURL = `<${userProfileURL}|${user.username}>`;
- const targetSlatePageURL = `https://slate.host/$/${data.context.slateId}`;
- const targetSlateURL = `<${targetSlatePageURL}|${data.context.slateId}>`;
+ const targetSlatePageURL = `https://slate.host/$/${targetSlate.id}`;
+ const targetSlateURL = `<${targetSlatePageURL}|${targetSlate.slateId}>`;
const message = `*${userURL}* subscribed to slate:${targetSlateURL}`;
Social.sendSlackMessage(message);
@@ -287,58 +314,58 @@ export const subscribeSlate = ({ slateId, data }) => {
}
};
-export const requestPeer = ({ userId, data }) => {
- // NOTE(jim): Don't track stats on this.
+// export const requestPeer = ({ userId, data }) => {
+// // NOTE(jim): Don't track stats on this.
- try {
- // NOTE(jim):
- // , WANTS TO BE YOUR PEER.
- Data.createActivity({
- userId,
- data: {
- type: "REQUEST_PEER",
- actorUserId: data.actorUserId,
- context: data.context,
- },
- });
+// try {
+// // NOTE(jim):
+// // , WANTS TO BE YOUR PEER.
+// Data.createActivity({
+// userId,
+// data: {
+// type: "REQUEST_PEER",
+// actorUserId: data.actorUserId,
+// context: data.context,
+// },
+// });
- const userProfileURL = `https://slate.host/${data.context.username}`;
- const userURL = `<${userProfileURL}|${data.context.username}>`;
+// const userProfileURL = `https://slate.host/${data.context.username}`;
+// const userURL = `<${userProfileURL}|${data.context.username}>`;
- const targetUserProfileURL = `https://slate.host/${data.context.targetUsername}`;
- const targetUserURL = `<${targetUserProfileURL}|${data.context.targetUsername}>`;
+// const targetUserProfileURL = `https://slate.host/${data.context.targetUsername}`;
+// const targetUserURL = `<${targetUserProfileURL}|${data.context.targetUsername}>`;
- const message = `*${userURL}* made a request to trust ${targetUserURL}`;
- Social.sendSlackMessage(message);
- } catch (e) {
- console.log(e);
- }
-};
+// const message = `*${userURL}* made a request to trust ${targetUserURL}`;
+// Social.sendSlackMessage(message);
+// } catch (e) {
+// console.log(e);
+// }
+// };
-export const verifyPeer = ({ userId, data }) => {
- // NOTE(jim): Don't track stats on this.
+// export const verifyPeer = ({ userId, data }) => {
+// // NOTE(jim): Don't track stats on this.
- try {
- // NOTE(jim):
- // , ACCEPTED YOUR REQUEST.
- Data.createActivity({
- userId,
- data: {
- type: "VERIFY_PEER",
- actorUserId: data.actorUserId,
- context: data.context,
- },
- });
+// try {
+// // NOTE(jim):
+// // , ACCEPTED YOUR REQUEST.
+// Data.createActivity({
+// userId,
+// data: {
+// type: "VERIFY_PEER",
+// actorUserId: data.actorUserId,
+// context: data.context,
+// },
+// });
- const userProfileURL = `https://slate.host/${data.context.username}`;
- const userURL = `<${userProfileURL}|${data.context.username}>`;
+// const userProfileURL = `https://slate.host/${data.context.username}`;
+// const userURL = `<${userProfileURL}|${data.context.username}>`;
- const targetUserProfileURL = `https://slate.host/${data.context.targetUsername}`;
- const targetUserURL = `<${targetUserProfileURL}|${data.context.targetUsername}>`;
+// const targetUserProfileURL = `https://slate.host/${data.context.targetUsername}`;
+// const targetUserURL = `<${targetUserProfileURL}|${data.context.targetUsername}>`;
- const message = `*${userURL}* has accepted a peer-to-peer relationship with ${targetUserURL}`;
- Social.sendSlackMessage(message);
- } catch (e) {
- console.log(e);
- }
-};
+// const message = `*${userURL}* has accepted a peer-to-peer relationship with ${targetUserURL}`;
+// Social.sendSlackMessage(message);
+// } catch (e) {
+// console.log(e);
+// }
+// };
diff --git a/node_common/serializers.js b/node_common/serializers.js
index 40260c00..2e58ef04 100644
--- a/node_common/serializers.js
+++ b/node_common/serializers.js
@@ -1,371 +1,152 @@
-import DB from "~/node_common/database";
-import * as Data from "~/node_common/data";
+//NOTE(martina): when you add any new variable to the user, file, or slate objects, add it in these structures
+//add it to sanitize___ if it should be sent to the front end
+//add it to clean____ if it should be saved to the database
-export const user = (entity) => {
+//NOTE(martina): these functions are to remove sensitive information before sending the data to the front end
+//only variables listed here will be sent to the front end
+
+export const sanitizeUser = (entity) => {
return {
- type: "USER",
id: entity.id,
username: entity.username,
- slates: entity.slates ? entity.slates : [],
- library: entity.library ? entity.library : [],
+ slates: entity.slates, //NOTE(martina): this is not in the database. It is added after
+ library: entity.library, //NOTE(martina): this is not in the database. It is added after
data: {
- name: entity.data.name ? entity.data.name : "",
- photo: entity.data.photo ? entity.data.photo : "",
- body: entity.data.body ? entity.data.body : "",
+ name: entity.data?.name,
+ photo: entity.data?.photo,
+ body: entity.data?.body,
},
};
};
-export const slate = (entity) => {
+export const sanitizeSlate = (entity) => {
return {
- type: "SLATE",
id: entity.id,
slatename: entity.slatename,
+ ownerId: entity.ownerId,
+ isPublic: entity.isPublic,
+ objects: entity.objects,
+ user: entity.user, //NOTE(martina): this is not in the database. It is added after
data: {
- ownerId: entity.data.ownerId,
- name: entity.data.name ? entity.data.name : "",
- body: entity.data.body ? entity.data.body : "",
- objects: entity.data.objects,
- layouts: entity.data.layouts,
- public: entity.data.public,
+ name: entity.data?.name,
+ body: entity.data?.body,
+ preview: entity.data?.preview,
+ layouts: entity.data?.layouts,
+ tags: entity.data?.tags,
},
};
};
-export const doSlates = async ({ serializedUsers, slates }) => {
- const userToSlatesMap = {};
-
- const sanitized = slates.map((d) => {
- let o = null;
-
- if (userToSlatesMap[d.data.ownerId]) {
- userToSlatesMap[d.data.ownerId].push(d);
- }
-
- if (!userToSlatesMap[d.data.ownerId]) {
- userToSlatesMap[d.data.ownerId] = [d];
- }
-
- if (d.data.ownerId) {
- o = serializedUsers.find((e) => d.data.ownerId === e.id);
- }
-
- return { ...d, owner: o };
- });
-
+export const sanitizeFile = (entity) => {
return {
- serializedSlates: JSON.parse(JSON.stringify(sanitized)),
- userToSlatesMap,
+ id: entity.id,
+ cid: entity.cid,
+ ownerId: entity.ownerId,
+ isPublic: entity.isPublic,
+ filename: entity.filename,
+ data: {
+ type: entity.data?.type,
+ name: entity.data?.name,
+ size: entity.data?.size,
+ body: entity.data?.body,
+ source: entity.data?.source,
+ author: entity.data?.author,
+ blurhash: entity.data?.blurhash,
+ coverImage: entity.data?.coverImage,
+ downloads: entity.data?.downloads, //NOTE(martina): newly added
+ tags: entity.data?.tags, //NOTE(martina): newly added
+ unity: entity.data?.unity, //NOTE(martina): newly added
+ link: entity.data?.link, //NOTE(martina): newly added
+ },
};
};
-// export const doTrusted = async ({ users, trusted, serializedUsersMap, serializedSlatesMap }) => {
-// trusted.forEach((each) => {
-// if (each.target_user_id && !serializedUsersMap[each.target_user_id]) {
-// users.push(each.target_user_id);
-// }
-// });
-
-// let userEntities = [];
-// try {
-// if (users.length) {
-// userEntities = await DB.select("id", "username", "data")
-// .from("users")
-// .whereIn("id", users);
-// }
-// } catch (e) {
-// return {
-// serializedTrusted: trusted,
-// serializedUsersMap,
-// serializedSlatesMap,
-// };
-// }
-
-// const sanitized = trusted.map((data) => {
-// let u = null;
-// let o = null;
-
-// if (data.target_user_id) {
-// if (serializedUsersMap[data.target_user_id]) {
-// u = serializedUsersMap[data.target_user_id];
-// } else {
-// u = userEntities.find((e) => data.target_user_id === e.id);
-// u = user(u);
-// serializedUsersMap[data.target_user_id] = u;
-// }
-// }
-
-// if (data.owner_user_id) {
-// if (serializedUsersMap[data.owner_user_id]) {
-// o = serializedUsersMap[data.owner_user_id];
-// } else {
-// o = userEntities.find((e) => data.owner_user_id === e.id);
-// o = user(o);
-// serializedUsersMap[data.owner_user_id] = o;
-// }
-// }
-
-// return { ...data, user: u, owner: o };
-// });
-
-// return {
-// serializedTrusted: JSON.parse(JSON.stringify(sanitized)),
-// serializedUsersMap,
-// serializedSlatesMap,
-// };
-// };
-
-// export const doPendingTrusted = async ({
-// users,
-// pendingTrusted,
-// serializedUsersMap,
-// serializedSlatesMap,
-// }) => {
-// pendingTrusted.forEach((each) => {
-// if (each.owner_user_id && !serializedUsersMap[each.owner_user_id]) {
-// users.push(each.owner_user_id);
-// }
-// });
-
-// let userEntities = [];
-
-// try {
-// if (users.length) {
-// userEntities = await DB.select("id", "username", "data")
-// .from("users")
-// .whereIn("id", users);
-// }
-// } catch (e) {
-// return {
-// serializedPendingTrusted: pendingTrusted,
-// serializedUsersMap,
-// serializedSlatesMap,
-// };
-// }
-
-// const sanitized = pendingTrusted.map((data) => {
-// let u = null;
-// let o = null;
-
-// if (data.target_user_id) {
-// if (serializedUsersMap[data.target_user_id]) {
-// u = serializedUsersMap[data.target_user_id];
-// } else {
-// u = userEntities.find((e) => data.target_user_id === e.id);
-// u = user(u);
-// serializedUsersMap[data.target_user_id] = u;
-// }
-// }
-
-// if (data.owner_user_id) {
-// if (serializedUsersMap[data.owner_user_id]) {
-// o = serializedUsersMap[data.owner_user_id];
-// } else {
-// o = userEntities.find((e) => data.owner_user_id === e.id);
-// o = user(o);
-// serializedUsersMap[data.owner_user_id] = o;
-// }
-// }
-
-// return { ...data, user: u, owner: o };
-// });
-
-// return {
-// serializedPendingTrusted: JSON.parse(JSON.stringify(sanitized)),
-// serializedUsersMap,
-// serializedSlatesMap,
-// };
-// };
-
-export const doSubscriptions = async ({
- users,
- slates,
- subscriptions,
- serializedUsersMap,
- serializedSlatesMap,
-}) => {
- subscriptions.forEach((each) => {
- if (each.target_user_id && !serializedUsersMap[each.target_user_id]) {
- users.push(each.target_user_id);
- }
-
- if (each.target_slate_id && !serializedSlatesMap[each.target_slate_id]) {
- slates.push(each.target_slate_id);
- }
- });
-
- let userEntities = [];
- try {
- if (users.length) {
- userEntities = await DB.select("id", "username", "data").from("users").whereIn("id", users);
- }
- } catch (e) {
- return {
- serializedSubscriptions: subscriptions,
- serializedUsersMap,
- serializedSlatesMap,
- };
- }
-
- let slateEntities = [];
- try {
- if (slates.length) {
- slateEntities = await DB.select("id", "slatename", "data")
- .from("slates")
- .whereIn("id", slates);
- }
- } catch (e) {
- return {
- serializedSubscriptions: subscriptions,
- serializedUsersMap,
- serializedSlatesMap,
- };
- }
-
- const sanitized = subscriptions.map((data) => {
- let u = null;
- let o = null;
- let s = null;
-
- if (data.target_user_id) {
- if (serializedUsersMap[data.target_user_id]) {
- u = serializedUsersMap[data.target_user_id];
- } else {
- u = userEntities.find((e) => data.target_user_id === e.id);
- u = user(u);
- serializedUsersMap[data.target_user_id] = u;
- }
- }
-
- if (data.owner_user_id) {
- if (serializedUsersMap[data.owner_user_id]) {
- o = serializedUsersMap[data.owner_user_id];
- } else {
- o = userEntities.find((e) => data.owner_user_id === e.id);
- o = user(o);
- serializedUsersMap[data.owner_user_id] = o;
- }
- }
-
- if (data.target_slate_id) {
- if (serializedSlatesMap[data.target_slate_id]) {
- s = serializedSlatesMap[data.target_slate_id];
- } else {
- s = slateEntities.find((e) => data.target_slate_id === e.id);
- s = slate(s);
- serializedSlatesMap[data.target_slate_id] = s;
- }
- }
-
- return { ...data, user: u, owner: o, slate: s };
- });
+//NOTE(martina): these functions are to remove extraneous information before updating the database entry.
+//Only variables included here will be added to the database
+export const cleanUser = (entity) => {
return {
- serializedSubscriptions: JSON.parse(JSON.stringify(sanitized)),
- serializedUsersMap,
- serializedSlatesMap,
+ id: entity.id,
+ username: entity.username,
+ createdAt: entity.createdAt,
+ lastActive: entity.lastActive,
+ salt: entity.salt,
+ password: entity.password,
+ email: entity.email,
+ data: entity.data,
+ // data: {
+ // name: entity.data?.name,
+ // photo: entity.data?.photo,
+ // body: entity.data?.body,
+ // tokens: entity.data?.tokens,
+ // settings: entity.data?.settings,
+ // onboarding: entity.data?.onboarding,
+ // status: entity.data?.status,
+ // library: entity.data?.library, //MIGRATION: take this out after
+ // },
};
};
-export const doSubscribers = async ({
- users,
- slates,
- subscribers,
- serializedUsersMap,
- serializedSlatesMap,
-}) => {
- subscribers.forEach((each) => {
- if (each.owner_user_id && !serializedUsersMap[each.owner_user_id]) {
- users.push(each.owner_user_id);
- }
- });
-
- let userEntities = [];
- try {
- if (users.length) {
- userEntities = await DB.select("id", "username", "data").from("users").whereIn("id", users);
- }
- } catch (e) {
- return {
- serializedSubscribers: subscribers,
- serializedUsersMap,
- serializedSlatesMap,
- };
- }
-
- const sanitized = subscribers.map((data) => {
- let u = null;
- let o = null;
- let s = null;
-
- if (data.owner_user_id) {
- if (serializedUsersMap[data.owner_user_id]) {
- o = serializedUsersMap[data.owner_user_id];
- } else {
- o = userEntities.find((e) => data.owner_user_id === e.id);
- o = user(o);
- serializedUsersMap[data.owner_user_id] = o;
- }
- }
-
- if (data.target_user_id) {
- if (serializedUsersMap[data.target_user_id]) {
- u = serializedUsersMap[data.target_user_id];
- } else {
- u = userEntities.find((e) => data.target_user_id === e.id);
- u = user(u);
- serializedUsersMap[data.target_user_id] = u;
- }
- }
-
- return { ...data, user: u, owner: o, slate: s };
- });
-
+export const cleanSlate = (entity) => {
return {
- serializedSubscribers: JSON.parse(JSON.stringify(sanitized)),
- serializedUsersMap,
- serializedSlatesMap,
+ id: entity.id,
+ createdAt: entity.createdAt,
+ updatedAt: entity.updatedAt,
+ slatename: entity.slatename,
+ isPublic: entity.isPublic,
+ ownerId: entity.ownerId,
+ data: entity.data,
+ // data: {
+ // name: entity.data?.name,
+ // body: entity.data?.body,
+ // preview: entity.data?.preview,
+ // layouts: entity.data?.layouts,
+ // tags: entity.data?.tags,
+ // objects: entity.data?.objects, //MIGRATION: take this out after
+ // },
};
};
-export const doActivity = async (fetchedActivity) => {
- let activity = fetchedActivity;
- let slateIds = [];
- if (activity && activity.length) {
- activity = activity.filter((item) => {
- if (item.data.type === "SUBSCRIBED_CREATE_SLATE") {
- slateIds.push(item.data.context.slate.id);
- }
- return (
- item.data.type === "SUBSCRIBED_CREATE_SLATE" || item.data.type === "SUBSCRIBED_ADD_TO_SLATE"
- );
- });
- }
-
- let slates = [];
- if (slateIds && slateIds.length) {
- slates = await Data.getSlatesByIds({ ids: slateIds });
- }
-
- let slateTable = {};
- for (let slate of slates || []) {
- slateTable[slate.id] = slate;
- }
-
- for (let item of activity) {
- if (item.data.type === "SUBSCRIBED_CREATE_SLATE") {
- let slate = slateTable[item.data.context.slate.id];
- if (slate?.data?.objects?.length) {
- item.data.context.slate = slate;
- }
- }
- }
- //NOTE(martina): remove empty slates
- activity = activity.filter((item) => {
- if (item.data.type === "SUBSCRIBED_ADD_TO_SLATE") return true;
- let slate = item.data.context.slate;
- return slate?.data?.objects?.length;
- });
-
- return activity;
+export const cleanFile = (entity) => {
+ return {
+ id: entity.id,
+ cid: entity.cid,
+ createdAt: entity.createdAt,
+ ownerId: entity.ownerId,
+ isPublic: entity.isPublic,
+ filename: entity.filename,
+ data: entity.data,
+ // data: {
+ // type: entity.data?.type,
+ // name: entity.data?.name,
+ // size: entity.data?.size,
+ // body: entity.data?.body,
+ // source: entity.data?.source,
+ // author: entity.data?.author,
+ // blurhash: entity.data?.blurhash,
+ // coverImage: entity.data?.coverImage,
+ // downloads: entity.data?.downloads,
+ // tags: entity.data?.tags,
+ // unity: entity.data?.unity,
+ // link: entity.data?.link,
+ // },
+ };
+};
+
+//NOTE(martina): these functions are used to get the updated object that is obtained by merging the old and new objects
+// and using the above cleaning functions to strip out things that should not be in the database or should not be mutated
+
+export const getUpdatedSlate = (oldSlate, updates) => {
+ let updatedSlate = cleanSlate(updates);
+ return { ...oldSlate, ...updatedSlate, data: { ...oldSlate.data, ...updatedSlate.data } };
+};
+
+export const getUpdatedFile = (oldFile, updates) => {
+ let updatedFile = cleanFile(updates);
+ return { ...oldFile, ...updatedFile, data: { ...oldFile.data, ...updatedFile.data } };
+};
+
+export const getUpdatedUser = (oldUser, updates) => {
+ let updatedUser = cleanUser(updates);
+ return { ...oldUser, ...updatedUser, data: { ...oldUser.data, ...updatedUser.data } };
};
diff --git a/node_common/utilities.js b/node_common/utilities.js
index ffa82432..c8e2ff26 100644
--- a/node_common/utilities.js
+++ b/node_common/utilities.js
@@ -156,6 +156,7 @@ export const addExistingCIDToData = async ({ buckets, key, path, cid }) => {
// NOTE(jim): Requires @textile/hub
export const getBucketAPIFromUserToken = async ({ user, bucketName, encrypted = false }) => {
const token = user.data.tokens.api;
+ console.log(token);
const name = Strings.isEmpty(bucketName) ? BUCKET_NAME : bucketName;
const identity = await PrivateKey.fromString(token);
let buckets = await Buckets.withKeyInfo(TEXTILE_KEY_INFO);
diff --git a/package.json b/package.json
index 0485dd45..bc26c389 100644
--- a/package.json
+++ b/package.json
@@ -27,7 +27,8 @@
"scripts": "NODE_TLS_REJECT_UNAUTHORIZED=0 node --max-old-space-size=8192 ./scripts",
"www-setup-database": "NODE_TLS_REJECT_UNAUTHORIZED=0 node ./scripts setup-database",
"www-seed-database": "NODE_TLS_REJECT_UNAUTHORIZED=0 node ./scripts seed-database",
- "www-adjust-database": "NODE_TLS_REJECT_UNAUTHORIZED=0 node ./scripts adjust"
+ "www-adjust-database": "NODE_TLS_REJECT_UNAUTHORIZED=0 node ./scripts adjust",
+ "www-migrate-files": "NODE_TLS_REJECT_UNAUTHORIZED=0 node ./scripts files-migration"
},
"repository": "filecoin-project/slate",
"dependencies": {
diff --git a/pages/_/index.js b/pages/_/index.js
index c05726f7..045e5257 100644
--- a/pages/_/index.js
+++ b/pages/_/index.js
@@ -6,9 +6,8 @@ export const getServerSideProps = async ({ query }) => {
return {
props: {
viewer: query.viewer,
- analytics: query.analytics,
- mobile: query.mobile,
- mac: query.mac,
+ isMobile: query.isMobile,
+ isMac: query.isMac,
resources: query.resources,
},
};
@@ -19,9 +18,8 @@ export default class ApplicationPage extends React.Component {
return (
);
diff --git a/pages/_/integration-page.js b/pages/_/integration-page.js
deleted file mode 100644
index 070c0004..00000000
--- a/pages/_/integration-page.js
+++ /dev/null
@@ -1,195 +0,0 @@
-import * as React from "react";
-import * as Constants from "~/common/constants";
-import * as System from "~/components/system";
-import * as Actions from "~/common/actions";
-import * as Events from "~/common/custom-events";
-
-import { css } from "@emotion/react";
-
-const STYLES_ITEM = css`
- font-size: 12px;
- font-weight: 600;
- font-famliy: monaco;
- white-space: pre-wrap;
- overflow-wrap: break-word;
-`;
-
-const STYLES_ROW = css`
- display: flex;
- align-items: flex-start;
- justify-content: space-between;
-`;
-
-const STYLES_COLUMN = css`
- width: 33.33%;
- flex-shrink: 0;
- padding: 24px;
- box-sizing: border-box;
-`;
-
-export const getServerSideProps = async (context) => {
- return {
- props: { ...context.query },
- };
-};
-
-export default class IntegrationPage extends React.Component {
- state = {
- results: [],
- viewer: this.props.viewer,
- };
-
- async componentDidMount() {
- const response = await Actions.getNetworkDirectory();
- console.log(response);
- }
-
- _handleChange = async (e) => {
- const query = e.target.value;
- const results = await Actions.search({
- query,
- filter: {
- slates: true,
- },
- });
-
- this.setState({ results: results.data.results });
- };
-
- _handleUpdate = async (e) => {
- const response = await Actions.hydrateAuthenticatedUser();
-
- if (Events.hasError(response)) {
- return null;
- }
-
- const updates = {
- viewer: response.data,
- };
-
- this.setState(updates);
- };
-
- _handleDelete = async (entity) => {
- const response = await Actions.deleteTrustRelationship({ id: entity.id });
- console.log(response);
-
- await this._handleUpdate();
- };
-
- _handleTrust = async (user) => {
- const response = await Actions.createTrustRelationship({
- userId: user.target_user_id ? user.target_user_id : user.id,
- });
- console.log(response);
-
- await this._handleUpdate();
- };
-
- _handleAccept = async (user) => {
- const response = await Actions.updateTrustRelationship({
- userId: user.owner_user_id,
- });
- console.log(response);
-
- await this._handleUpdate();
- };
-
- _handleSubscribe = async (entity) => {
- let response;
- if (entity.type === "USER" || entity.target_user_id) {
- response = await Actions.createSubscription({
- userId: entity.target_user_id ? entity.target_user_id : entity.id,
- });
- console.log(response);
- }
-
- if (entity.type === "SLATE" || entity.target_slate_id) {
- response = await Actions.createSubscription({
- slateId: entity.target_slate_id ? entity.target_slate_id : entity.id,
- });
- console.log(response);
- }
-
- await this._handleUpdate();
- };
-
- render() {
- return (
-
-
- {/* {this.state.viewer.pendingTrusted.map((each) => {
- return (
-
- {JSON.stringify(each, null, 1)}{" "}
-
- {!each.data.verified ? (
- this._handleAccept(each)}>Accept
- ) : null}
-
- {each.data.verified ? (
- this._handleDelete(each)}>Delete
- ) : null}
-
-
- );
- })} */}
-
- {/* {this.state.viewer.trusted.map((each) => {
- return (
-
- {JSON.stringify(each, null, 1)}{" "}
-
- {!each.data.verified ? (
- this._handleTrust(each)}>
- Cancel Pending Request Or Delete Friend
-
- ) : null}
-
- {each.data.verified ? (
- this._handleDelete(each)}>Delete
- ) : null}
-
-
- );
- })} */}
-
-
-
Update {this.state.viewer.username}
-
-
-
- {this.state.results.map((each) => {
- if (!each) {
- return;
- }
-
- return (
-
- {JSON.stringify(each, null, 1)}{" "}
-
- {each.type === "USER" ? (
- this._handleTrust(each)}>Trust
- ) : null}
- this._handleSubscribe(each)}>Subscribe
-
-
- );
- })}
-
-
- {this.state.viewer.subscriptions.map((each) => {
- return (
-
- {JSON.stringify(each, null, 1)}{" "}
-
- this._handleSubscribe(each)}>Unsubscribe
-
-
- );
- })}
-
-
- );
- }
-}
diff --git a/pages/_/profile.js b/pages/_/profile.js
index fd5c4766..12f5bf6d 100644
--- a/pages/_/profile.js
+++ b/pages/_/profile.js
@@ -24,7 +24,6 @@ export const getServerSideProps = async (context) => {
const STYLES_ROOT = css`
display: block;
grid-template-rows: auto 1fr auto;
- text-align: center;
font-size: 1rem;
min-height: 100vh;
background-color: ${Constants.system.foreground};
@@ -40,7 +39,7 @@ export default class ProfilePage extends React.Component {
window.onpopstate = this._handleBackForward;
if (!Strings.isEmpty(this.props.cid)) {
- let files = this.props.creator.library[0]?.children || [];
+ let files = this.props.creator.library || [];
let index = files.findIndex((object) => object.cid === this.props.cid);
if (index !== -1) {
Events.dispatchCustomEvent({
@@ -58,26 +57,26 @@ export default class ProfilePage extends React.Component {
};
render() {
- const title = this.props.creator ? `${this.props.creator.username}` : "404";
+ const title = this.props.creator
+ ? this.props.creator.data.name
+ ? `${this.props.creator.data.name} on Slate`
+ : `@${this.props.creator.username} on Slate`
+ : "404";
const url = `https://slate.host/${title}`;
const description = this.props.creator.data.body;
const image = this.props.creator.data.photo;
- const buttons = (
- this.setState({ visible: true })}>Follow
- );
-
if (Strings.isEmpty(image)) {
image = DEFAULT_IMAGE;
}
+
return (
{
};
};
-export const FileTypeDefaultPreview = () => {
- if (props.type && props.type.startsWith("video/")) {
- return DEFAULT_VIDEO;
- }
- if (props.type && props.type.startsWith("audio/")) {
- return DEFAULT_AUDIO;
- }
- if (props.type && props.type.startsWith("application/epub")) {
- return DEFAULT_BOOK;
- }
- if (props.type && props.type.startsWith("application/pdf")) {
- return DEFAULT_DOCUMENT;
+export const FileTypeDefaultPreview = (props) => {
+ if (props.type) {
+ if (Validations.isVideoType(type)) {
+ return DEFAULT_VIDEO;
+ } else if (Validations.isAudioType(type)) {
+ return DEFAULT_AUDIO;
+ } else if (Validations.isPdfType(type)) {
+ return DEFAULT_DOCUMENT;
+ } else if (Validations.isEpubType(type)) {
+ return DEFAULT_BOOK;
+ }
}
return DEFAULT_DATA;
};
@@ -184,7 +182,7 @@ export default class SlatePage extends React.Component {
}
if (!Strings.isEmpty(this.props.cid)) {
- let files = this.props.slate.data.objects || [];
+ let files = this.props.slate.objects || [];
let index = files.findIndex((object) => object.cid === this.props.cid);
if (index !== -1) {
Events.dispatchCustomEvent({
@@ -203,10 +201,9 @@ export default class SlatePage extends React.Component {
};
_handleSave = async (layouts) => {
- await Actions.updateSlate({
+ await Actions.updateSlateLayout({
id: this.props.slate.id,
- layoutOnly: true,
- data: { layouts },
+ layouts,
});
};
@@ -225,38 +222,37 @@ export default class SlatePage extends React.Component {
let url = `https://slate.host/${this.props.creator.username}/${this.props.slate.slatename}`;
let headerURL = `https://slate.host/${this.props.creator.username}`;
- let { objects, layouts, body, preview } = this.props.slate.data;
- let isPublic = this.props.slate.data.public;
+ let { objects, isPublic } = this.props.slate;
+ let { layouts, body, preview } = this.props.slate.data;
let image;
if (Strings.isEmpty(this.props.cid)) {
image = preview;
if (Strings.isEmpty(image)) {
for (let i = 0; i < objects.length; i++) {
if (
- objects[i].type &&
- Validations.isPreviewableImage(objects[i].type) &&
- objects[i].size &&
- objects[i].size < SIZE_LIMIT
+ objects[i].data.type &&
+ Validations.isPreviewableImage(objects[i].data.type) &&
+ objects[i].data.size &&
+ objects[i].data.size < SIZE_LIMIT
) {
- image = objects[i].url;
+ image = Strings.getURLfromCID(objects[i].cid);
break;
}
}
}
} else {
+ const cid = Strings.getCIDFromIPFS(each.cid);
let object = objects.find((each) => {
- const url = each.url;
- const cid = Strings.getCIDFromIPFS(url);
return cid === this.props.cid;
});
if (object) {
- title = !Strings.isEmpty(object.title) ? object.title : this.props.cid;
- body = !Strings.isEmpty(object.body) ? Strings.elide(object.body) : `An object on ${url}`;
- image = object.type.includes("image/") ? (
- object.url
+ title = object.data.name || object.filename;
+ body = !Strings.isEmpty(object.data.body) ? Strings.elide(object.data.body) : "";
+ image = object.data.type.includes("image/") ? (
+ Strings.getURLfromCID(object.cid)
) : (
-
+
);
url = `${url}/cid:${this.props.cid}`;
}
@@ -296,7 +292,7 @@ export default class SlatePage extends React.Component {
- {this.props.slate.data.objects.length}{" "}
+ {this.props.slate.objects.length}{" "}
Files
@@ -324,14 +320,15 @@ export default class SlatePage extends React.Component {
- {this.props.mobile ? (
+ {this.props.isMobile ? (
Horizontal
- {["far-left", "left", "center", "right", "far-right"].map((dir) => (
+ {["far-left", "left", "center", "right", "far-right"].map((dir, i) => (
{
this._handleClick(e, "horizontal", dir);
@@ -256,8 +257,9 @@ import { GlobalTooltip, TooltipWrapper, TooltipAnchor } from "slate-react-system
height: "300px",
}}
>
- {["above", "up", "center", "down", "below"].map((dir) => (
+ {["above", "up", "center", "down", "below"].map((dir, i) => (
{
this._handleClick(e, "vertical", dir);
diff --git a/pages/api/activity/get-activity.js b/pages/api/activity/get-activity.js
new file mode 100644
index 00000000..260f79c1
--- /dev/null
+++ b/pages/api/activity/get-activity.js
@@ -0,0 +1,64 @@
+import * as Utilities from "~/node_common/utilities";
+import * as Data from "~/node_common/data";
+import * as Serializers from "~/node_common/serializers";
+import * as Strings from "~/common/strings";
+
+/**
+ * This endpoint is used to get the activity feed items that involve the users in FOLLOWING or slates in SUBSCRIPTIONS, paginated 100 at a time.
+ *
+ * Including the timestamp for the earliest activity item shown as EARLIESTTIMESTAMP will give you the next "page" of results (the next 100 results dated prior to that timestamp).
+ * Including the timestamp for the latest activity item shown as LATESTTIMESTAMP will give you any activity updates that have happened since that time.
+ * If both timestamps are omitted, this function will get the first "page" of 100 results
+ * FOLLOWING is the ids of the users that the querying user is following
+ * SUBSCRIPTIONS is the ids of the slates that the querying user is following
+ */
+
+export default async (req, res) => {
+ const id = Utilities.getIdFromCookie(req);
+
+ if (!id) {
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
+ }
+
+ let following = req.body.data?.following;
+ let subscriptions = req.body.data?.subscriptions;
+ if (!following || !subscriptions) {
+ const fetchedSubscriptions = await Data.getSubscriptionsByUserId({ ownerId: id });
+
+ if (fetchedSubscriptions && !fetchedSubscriptions.error) {
+ subscriptions = fetchedSubscriptions.map((sub) => sub.id);
+ }
+
+ const fetchedFollowing = await Data.getFollowingByUserId({ ownerId: id });
+
+ console.log(fetchedFollowing);
+
+ if (fetchedFollowing && !fetchedFollowing.error) {
+ following = fetchedFollowing.map((sub) => sub.id);
+ }
+ }
+
+ if (!following.length && !subscriptions.length) {
+ return res.status(200).send({ decorator: "SERVER_GET_ACTIVITY", activity: [] });
+ }
+
+ let earliestTimestamp;
+ let latestTimestamp;
+ if (req.body.data) {
+ earliestTimestamp = req.body.data.earliestTimestamp;
+ latestTimestamp = req.body.data.latestTimestamp;
+ }
+
+ let response = await Data.getActivity({
+ earliestTimestamp,
+ latestTimestamp,
+ following,
+ subscriptions,
+ });
+
+ if (!response || response.error) {
+ return res.status(400).send({ decorator: "SERVER_GET_ACTIVITY_NOT_FOUND", error: true });
+ }
+
+ return res.status(200).send({ decorator: "SERVER_GET_ACTIVITY", activity: response });
+};
diff --git a/pages/api/activity/get-explore.js b/pages/api/activity/get-explore.js
new file mode 100644
index 00000000..791935ec
--- /dev/null
+++ b/pages/api/activity/get-explore.js
@@ -0,0 +1,33 @@
+import * as Utilities from "~/node_common/utilities";
+import * as Data from "~/node_common/data";
+import * as Serializers from "~/node_common/serializers";
+import * as Strings from "~/common/strings";
+
+/**
+ * This endpoint is used to get explore feed items, paginated 100 at a time.
+ *
+ * Including the timestamp for the earliest activity item shown as EARLIESTTIMESTAMP will give you the next "page" of results (the next 100 results dated prior to that timestamp).
+ * Including the timestamp for the latest activity item shown as LATESTTIMESTAMP will give you any activity updates that have happened since that time.
+ * If both timestamps are omitted, this function will get the first "page" of 100 results
+ */
+
+export default async (req, res) => {
+ let earliestTimestamp;
+ let latestTimestamp;
+
+ if (req.body.data) {
+ earliestTimestamp = req.body.data.earliestTimestamp;
+ latestTimestamp = req.body.data.latestTimestamp;
+ }
+
+ let response = await Data.getExplore({
+ earliestTimestamp,
+ latestTimestamp,
+ });
+
+ if (!response || response.error) {
+ return res.status(400).send({ decorator: "SERVER_GET_EXPLORE_NOT_FOUND", error: true });
+ }
+
+ return res.status(200).send({ decorator: "SERVER_GET_EXPLORE", explore: response });
+};
diff --git a/pages/api/activity/get.js b/pages/api/activity/get.js
deleted file mode 100644
index 958dffc5..00000000
--- a/pages/api/activity/get.js
+++ /dev/null
@@ -1,47 +0,0 @@
-import * as Utilities from "~/node_common/utilities";
-import * as Data from "~/node_common/data";
-import * as Serializers from "~/node_common/serializers";
-import * as Strings from "~/common/strings";
-
-export default async (req, res) => {
- const id = Utilities.getIdFromCookie(req);
- if (!id) {
- return res.status(500).send({ decorator: "SERVER_GET_ACTIVITY", error: true });
- }
-
- const user = await Data.getUserById({
- id,
- });
-
- if (!user) {
- return res.status(404).send({
- decorator: "SERVER_GET_ACTIVITY_USER_NOT_FOUND",
- error: true,
- });
- }
-
- if (user.error) {
- return res.status(500).send({
- decorator: "SERVER_GET_ACTIVITY_USER_NOT_FOUND",
- error: true,
- });
- }
-
- let response = await Data.getActivityForUserId({
- userId: req.body.data.explore ? "SLATE" : user.id,
- earliestTimestamp: req.body.data.earliestTimestamp,
- latestTimestamp: req.body.data.latestTimestamp,
- });
-
- if (!response) {
- return res.status(404).send({ decorator: "SERVER_GET_ACTIVITY_NOT_FOUND", error: true });
- }
-
- if (response.error) {
- return res.status(500).send({ decorator: "SERVER_GET_ACTIVITY_NOT_FOUND", error: true });
- }
-
- let activity = await Serializers.doActivity(response);
-
- return res.status(200).send({ decorator: "SERVER_GET_SLATE", activity });
-};
diff --git a/pages/api/addresses/send.js b/pages/api/addresses/send.js
index f9b66d82..a107738d 100644
--- a/pages/api/addresses/send.js
+++ b/pages/api/addresses/send.js
@@ -5,41 +5,26 @@ import * as Powergate from "~/node_common/powergate";
export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
if (!id) {
- return res
- .status(500)
- .send({ decorator: "SERVER_SEND_FILECOIN_NO_ID", error: true });
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
}
const user = await Data.getUserById({
id,
});
-
if (!user) {
- return res
- .status(404)
- .send({ decorator: "SERVER_SEND_FILECOIN_USER_NOT_FOUND", error: true });
+ return res.status(404).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
}
-
if (user.error) {
- return res
- .status(500)
- .send({ decorator: "SERVER_SEND_FILECOIN_USER_NOT_FOUND", error: true });
+ return res.status(500).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
}
const PG = Powergate.get(user);
- let data;
try {
- data = await PG.ffs.sendFil(
- req.body.data.source,
- req.body.data.target,
- req.body.data.amount
- );
+ await PG.ffs.sendFil(req.body.data.source, req.body.data.target, req.body.data.amount);
} catch (e) {
console.log(e);
- return res
- .status(500)
- .send({ decorator: "SERVER_SEND_FILECOIN_ACTION_FAILURE", error: true });
+ return res.status(500).send({ decorator: "SERVER_SEND_FILECOIN_ACTION_FAILURE", error: true });
}
return res.status(200).send({ decorator: "SERVER_SEND_FILECOIN" });
diff --git a/pages/api/clean-up/slates.js b/pages/api/clean-up/slates.js
index 13075ade..8932f5ec 100644
--- a/pages/api/clean-up/slates.js
+++ b/pages/api/clean-up/slates.js
@@ -4,7 +4,7 @@ import * as Strings from "~/common/strings";
import * as Constants from "~/common/constants";
export default async (req, res) => {
- const slates = await Data.getEverySlate(false);
+ const slates = await Data.getEverySlate();
for (let slate of slates) {
//NOTE(martina): uncomment to test
let newObjs = [];
@@ -65,11 +65,11 @@ export default async (req, res) => {
return false;
}
if (obj.cid) {
- obj.url = Strings.getCIDGatewayURL(obj.cid);
+ obj.url = Strings.getURLfromCID(obj.cid);
} else {
if (!obj.url.includes(Constants.gateways.ipfs)) {
obj.cid = Strings.urlToCid(obj.url);
- obj.url = Strings.getCIDGatewayURL(obj.cid);
+ obj.url = Strings.getURLfromCID(obj.cid);
}
obj.url = obj.url.replace("https://undefined", "https://");
}
diff --git a/pages/api/clean-up/users.js b/pages/api/clean-up/users.js
index 470d9fe5..a4082705 100644
--- a/pages/api/clean-up/users.js
+++ b/pages/api/clean-up/users.js
@@ -3,7 +3,7 @@ import * as Strings from "~/common/strings";
import * as Constants from "~/common/constants";
export default async (req, res) => {
- const users = await Data.getEveryUser(false);
+ const users = await Data.getEveryUser();
for (let user of users) {
if (user.data?.library[0]?.children?.length) {
let library = user.data.library[0].children;
diff --git a/pages/api/data/add.js b/pages/api/data/add.js
deleted file mode 100644
index 31efe04f..00000000
--- a/pages/api/data/add.js
+++ /dev/null
@@ -1,81 +0,0 @@
-import * as Utilities from "~/node_common/utilities";
-import * as Data from "~/node_common/data";
-import * as LibraryManager from "~/node_common/managers/library";
-import * as ViewerManager from "~/node_common/managers/viewer";
-
-export default async (req, res) => {
- const id = Utilities.getIdFromCookie(req);
-
- const user = await Data.getUserById({
- id,
- });
-
- if (!user || user.error) {
- return res.status(403).send({ decorator: "SERVER_ADD_TO_SLATE_USER_NOT_FOUND", error: true });
- }
-
- let { buckets, bucketKey, bucketRoot, bucketName } = await Utilities.getBucketAPIFromUserToken({
- user,
- });
-
- if (!buckets) {
- return res.status(500).send({
- decorator: "SERVER_GET_BUCKET_DATA",
- error: true,
- });
- }
-
- if (!req.body.data.items) {
- return res.status(500).send({
- decorator: "SERVER_NO_CID",
- error: true,
- });
- }
-
- let userCIDs = user.data.library[0].children.map((file) => file.cid);
- let newFiles = [];
- for (let item of req.body.data.items) {
- let cid = item.cid;
- if (userCIDs.includes(cid)) {
- continue;
- }
- let response = await Utilities.addExistingCIDToData({
- buckets,
- key: bucketKey,
- path: bucketRoot.path,
- cid,
- });
-
- if (response && !response.error) {
- let owner = await Data.getUserById({ id: item.ownerId });
- if (owner && !owner.error) {
- for (let file of owner.data.library[0].children) {
- if (file.cid === cid) {
- file.date = new Date();
- newFiles.push(file);
- break;
- }
- }
- }
- }
- }
-
- const { updatedUserDataFields, added, skipped } = LibraryManager.addData({
- user,
- files: newFiles,
- });
-
- await Data.updateUserById({
- id: user.id,
- data: updatedUserDataFields,
- });
-
- if (updatedUserDataFields && updatedUserDataFields.library) {
- ViewerManager.hydratePartialLibrary(updatedUserDataFields.library, id);
- }
-
- return res.status(200).send({
- decorator: "SERVER_ADD_EXISTING_CID_TO_DATA",
- data: { added, skipped: skipped + req.body.data.items.length - newFiles.length },
- });
-};
diff --git a/pages/api/data/archive.js b/pages/api/data/archive.js
index 21934256..4d2dcecd 100644
--- a/pages/api/data/archive.js
+++ b/pages/api/data/archive.js
@@ -12,7 +12,7 @@ const STAGING_DEAL_BUCKET = "stage-deal";
export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
if (!id) {
- return res.status(403).send({ decorator: "SERVER_REMOVE_DATA_NOT_ALLOWED", error: true });
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
}
const user = await Data.getUserById({
@@ -21,14 +21,14 @@ export default async (req, res) => {
if (!user) {
return res.status(404).send({
- decorator: "SERVER_BUCKET_ARCHIVE_DEAL_USER_NOT_FOUND",
+ decorator: "SERVER_USER_NOT_FOUND",
error: true,
});
}
if (user.error) {
return res.status(500).send({
- decorator: "SERVER_BUCKET_ARCHIVE_DEAL_USER_NOT_FOUND",
+ decorator: "SERVER_USER_NOT_FOUND",
error: true,
});
}
@@ -45,14 +45,12 @@ export default async (req, res) => {
if (!buckets) {
return res.status(500).send({
- decorator: "SERVER_BUCKET_INIT_FAILURE",
+ decorator: "SERVER_NO_BUCKET_DATA",
error: true,
});
}
- // NOTE(jim):
- //
- // Getting the appropriate bucket key
+ // NOTE(jim): Getting the appropriate bucket key
let items = null;
let bucketSizeBytes = 0;
@@ -62,7 +60,7 @@ export default async (req, res) => {
bucketSizeBytes = path.item.size;
} catch (e) {
Social.sendTextileSlackMessage({
- file: "/node_common/managers/viewer.js",
+ file: "/pages/api/data/archive.js",
user,
message: e.message,
code: e.code,
@@ -72,7 +70,7 @@ export default async (req, res) => {
if (!items) {
return res.status(500).send({
- decorator: "STORAGE_DEAL_MAKING_NO_BUCKET",
+ decorator: "SERVER_NO_BUCKET_DATA",
error: true,
});
}
@@ -80,7 +78,7 @@ export default async (req, res) => {
console.log(`[ deal ] will make a deal for ${items.items.length} items`);
if (items.items.length < 2) {
return res.status(500).send({
- decorator: "STORAGE_DEAL_MAKING_NO_FILES",
+ decorator: "SERVER_ARCHIVE_NO_FILES",
error: true,
});
}
@@ -88,7 +86,7 @@ export default async (req, res) => {
console.log(`[ deal ] deal size: ${Strings.bytesToSize(bucketSizeBytes)}`);
if (bucketSizeBytes < MIN_ARCHIVE_SIZE_BYTES) {
return res.status(500).send({
- decorator: "STORAGE_BUCKET_TOO_SMALL",
+ decorator: "SERVER_ARCHIVE_BUCKET_TOO_SMALL",
message: `Your deal size of ${Strings.bytesToSize(
bucketSizeBytes
)} is too small. You must provide at least 100MB.`,
@@ -96,9 +94,8 @@ export default async (req, res) => {
});
}
- // NOTE(jim):
- //
- // Make sure that you haven't hit the MAX_BUCKET_COUNT
+ // NOTE(jim): Make sure that you haven't hit the MAX_BUCKET_COUNT
+
let userBuckets = [];
try {
userBuckets = await buckets.list();
@@ -112,7 +109,7 @@ export default async (req, res) => {
});
return res.status(500).send({
- decorator: "BUCKET_SPAWN_VERIFICATION_FAILED_FOR_BUCKET_COUNT",
+ decorator: "SERVER_ARCHIVE_BUCKET_COUNT_VERIFICATION_FAILED",
error: true,
});
}
@@ -122,16 +119,14 @@ export default async (req, res) => {
);
if (userBuckets.length >= MAX_BUCKET_COUNT) {
return res.status(500).send({
- decorator: "TOO_MANY_BUCKETS",
+ decorator: "SERVER_ARCHIVE_MAX_NUMBER_BUCKETS",
error: true,
});
}
- // NOTE(jim):
- //
- // Either encrypt the bucket or don't encrypt the bucket.
+ // NOTE(jim): Either encrypt the bucket or don't encrypt the bucket.
let encryptThisDeal = false;
- if (bucketName !== STAGING_DEAL_BUCKET && user.data.allow_encrypted_data_storage) {
+ if (bucketName !== STAGING_DEAL_BUCKET && user.data.settings?.allow_encrypted_data_storage) {
encryptThisDeal = true;
}
@@ -141,7 +136,7 @@ export default async (req, res) => {
let key = bucketRoot.key;
let encryptedBucketName = null;
- if (user.data.allow_encrypted_data_storage || req.body.data.forceEncryption) {
+ if (user.data.settings.allow_encrypted_data_storage || req.body.data.forceEncryption) {
encryptedBucketName = req.body.data.forceEncryption
? `encrypted-deal-${uuid()}`
: `encrypted-data-${uuid()}`;
@@ -150,7 +145,6 @@ export default async (req, res) => {
try {
const newBucket = await buckets.create(encryptedBucketName, true, items.cid);
-
key = newBucket.root.key;
} catch (e) {
Social.sendTextileSlackMessage({
@@ -162,7 +156,7 @@ export default async (req, res) => {
});
return res.status(500).send({
- decorator: "FORCED_ENCRYPTION_FAILED_FOR_DATA",
+ decorator: "SERVER_ARCHIVE_ENCRYPTION_FAILED",
error: true,
});
}
@@ -174,7 +168,6 @@ export default async (req, res) => {
try {
const newBucket = await buckets.create(newDealBucketName, false, items.cid);
-
key = newBucket.root.key;
} catch (e) {
Social.sendTextileSlackMessage({
@@ -186,7 +179,7 @@ export default async (req, res) => {
});
return res.status(500).send({
- decorator: "BUCKET_CLONING_FAILED",
+ decorator: "SERVER_ARCHIVE_BUCKET_CLONING_FAILED",
error: true,
});
}
@@ -195,9 +188,7 @@ export default async (req, res) => {
console.log(`[ normal ] ${key}`);
}
- // NOTE(jim):
- //
- // Finally make the deal
+ // NOTE(jim): Finally make the deal
let response = {};
let error = {};
@@ -237,14 +228,14 @@ export default async (req, res) => {
});
return res.status(500).send({
- decorator: "STORAGE_DEAL_MAKING_NOT_SANITARY",
+ decorator: "SERVER_ARCHIVE_DEAL_FAILED",
error: true,
message: e.message,
});
}
return res.status(200).send({
- decorator: "SERVER_DEAL_MAKING_PURE",
+ decorator: "SERVER_ARCHIVE",
data: { response, error },
});
};
diff --git a/pages/api/data/bucket-remove.js b/pages/api/data/bucket-remove.js
index 69af207f..c8284866 100644
--- a/pages/api/data/bucket-remove.js
+++ b/pages/api/data/bucket-remove.js
@@ -4,18 +4,13 @@ import * as Strings from "~/common/strings";
import * as Social from "~/node_common/social";
export default async (req, res) => {
- if (Strings.isEmpty(req.body.data.cid)) {
- return res
- .status(500)
- .send({ decorator: "SERVER_BUCKET_REMOVE_DATA_NO_CID", error: true });
- }
-
const id = Utilities.getIdFromCookie(req);
if (!id) {
- return res.status(403).send({
- decorator: "SERVER_BUCKET_REMOVE_DATA_NOT_ALLOWED",
- error: true,
- });
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
+ }
+
+ if (Strings.isEmpty(req.body.data.cid)) {
+ return res.status(500).send({ decorator: "SERVER_BUCKET_REMOVE_NO_CID", error: true });
}
const user = await Data.getUserById({
@@ -29,7 +24,7 @@ export default async (req, res) => {
if (!buckets) {
return res.status(500).send({
- decorator: "SERVER_BUCKET_BUCKET_INIT_FAILURE",
+ decorator: "SERVER_NO_BUCKET_DATA",
error: true,
});
}
@@ -49,9 +44,7 @@ export default async (req, res) => {
}
if (!r) {
- return res
- .status(500)
- .send({ decorator: "SERVER_BUCKET_REMOVE_DATA_NO_TEXTILE", error: true });
+ return res.status(500).send({ decorator: "SERVER_NO_BUCKET_DATA", error: true });
}
const targetBucket = r.find((d) => d.name === req.body.data.bucketName);
@@ -59,7 +52,7 @@ export default async (req, res) => {
if (!targetBucket) {
return res
.status(404)
- .send({ decorator: "SERVER_BUCKET_NOT_FOUND", error: true });
+ .send({ decorator: "SERVER_BUCKET_REMOVE_BUCKET_NOT_FOUND", error: true });
}
let items = null;
@@ -77,9 +70,7 @@ export default async (req, res) => {
}
if (!items) {
- return res
- .status(500)
- .send({ decorator: "SERVER_BUCKET_REMOVE_DATA_NO_TEXTILE", error: true });
+ return res.status(500).send({ decorator: "SERVER_BUCKET_REMOVE_NO_BUCKET_ITEMS", error: true });
}
let entity;
@@ -91,9 +82,7 @@ export default async (req, res) => {
}
if (!entity) {
- return res
- .status(500)
- .send({ decorator: "SERVER_BUCKET_REMOVE_DATA_NO_CID", error: true });
+ return res.status(500).send({ decorator: "SERVER_BUCKET_REMOVE_NO_MATCHING_CID", error: true });
}
let bucketRemoval;
@@ -108,13 +97,11 @@ export default async (req, res) => {
functionName: `buckets.removePath`,
});
- return res
- .status(500)
- .send({ decorator: "SERVER_BUCKET_REMOVE_DATA_NO_LINK", error: true });
+ return res.status(500).send({ decorator: "SERVER_BUCKET_REMOVE_FAILED", error: true });
}
return res.status(200).send({
- decorator: "SERVER_BUCKET_REMOVE_DATA",
+ decorator: "SERVER_BUCKET_REMOVE",
success: true,
bucketItems: items.items,
});
diff --git a/pages/api/data/cid-status.js b/pages/api/data/cid-status.js
deleted file mode 100644
index 45fdbe22..00000000
--- a/pages/api/data/cid-status.js
+++ /dev/null
@@ -1,145 +0,0 @@
-import * as Data from "~/node_common/data";
-import * as Utilities from "~/node_common/utilities";
-import * as Powergate from "~/node_common/powergate";
-import * as LibraryManager from "~/node_common/managers/library";
-
-const check = async (PG, jobId) =>
- new Promise((resolve) => {
- const jobsCancel = PG.ffs.watchJobs((j) => {
- resolve(j);
- }, jobId);
- });
-
-export default async (req, res) => {
- if (!req.body.data) {
- return res.status(500).send({ decorator: "SERVER_NO_CIDS_TO_CHECK", error: true });
- }
-
- if (!req.body.data.length) {
- return res.status(500).send({ decorator: "SERVER_NO_CIDS_TO_CHECK", error: true });
- }
-
- const id = Utilities.getIdFromCookie(req);
- const user = await Data.getUserById({
- id,
- });
-
- const PG = Powergate.get(user);
-
- const success = [];
- const failed = [];
- const reset = [];
-
- for (let i = 0; i < req.body.data.length; i++) {
- const x = req.body.data[i];
-
- if (!x.job) {
- failed.push(x);
- continue;
- }
-
- if (!x.ipfs) {
- failed.push(x);
- continue;
- }
-
- let job;
- try {
- job = await check(PG, x.job);
- } catch (e) {
- console.log(e);
- }
-
- if (job.status === 3) {
- console.log({ message: "ERROR", job });
- x.error = job.errCause;
- failed.push(x);
- continue;
- }
-
- if (job.status === 5) {
- console.log({ message: "SUCCESS", job });
- x.error = null;
- success.push(x);
- continue;
- }
-
- if (x.error) {
- x.error = null;
- reset.push(x);
- }
-
- console.log({ message: "NOOP", job });
- }
-
- let targetUser = { ...user };
-
- if (failed.length) {
- for (let i = 0; i < failed.length; i++) {
- let data = LibraryManager.getDataByCID(targetUser, failed[i].cid);
- if (!data) {
- continue;
- }
-
- data.networks = data.networks.filter((each) => each !== "FILECOIN");
- data.job = null;
- data.storage = 0;
- data.error = failed[i].error;
-
- targetUser.data = LibraryManager.updateDataById({
- user: targetUser,
- id: data.id,
- data,
- });
- }
- }
-
- if (success.length) {
- for (let i = 0; i < success.length; i++) {
- let data = LibraryManager.getDataByCID(targetUser, success[i].cid);
- if (!data) {
- continue;
- }
-
- data.storage = 1;
- data.error = null;
-
- targetUser.data = LibraryManager.updateDataById({
- user: targetUser,
- id: data.id,
- data,
- });
- }
- }
-
- if (reset.length) {
- for (let i = 0; i < reset.length; i++) {
- let data = LibraryManager.getDataByCID(targetUser, reset[i].cid);
- if (!data) {
- continue;
- }
-
- data.error = null;
-
- targetUser.data = LibraryManager.updateDataById({
- user: targetUser,
- id: data.id,
- data,
- });
- }
- }
-
- let response;
- if (success.length || failed.length || reset.length) {
- response = await Data.updateUserById({
- id: targetUser.id,
- data: targetUser.data,
- });
- }
-
- return res.status(200).send({
- decorator: "SERVER_CID_CHECK",
- update: success.length || failed.length || reset.length,
- updateResponse: response,
- });
-};
diff --git a/pages/api/data/create-pending.js b/pages/api/data/create-pending.js
deleted file mode 100644
index 07bddd96..00000000
--- a/pages/api/data/create-pending.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import * as Utilities from "~/node_common/utilities";
-import * as Data from "~/node_common/data";
-
-export default async (req, res) => {
- const id = Utilities.getIdFromCookie(req);
-
- if (!id) {
- return res.status(500).send({ decorator: "CREATE_PENDING_ERROR", error: true });
- }
-
- const response = await Data.createPendingData(req.body.data.data);
-
- if (!response) {
- return res.status(404).send({ decorator: "CREATE_PENDING_ERROR", error: true });
- }
-
- if (response.error) {
- return res.status(500).send({ decorator: response.decorator, error: response.error });
- }
-
- return res.status(200).send({
- decorator: "CREATE_PENDING_DATA",
- data: response,
- });
-};
diff --git a/pages/api/data/create.js b/pages/api/data/create.js
new file mode 100644
index 00000000..17014926
--- /dev/null
+++ b/pages/api/data/create.js
@@ -0,0 +1,65 @@
+import * as Utilities from "~/node_common/utilities";
+import * as Data from "~/node_common/data";
+import * as ViewerManager from "~/node_common/managers/viewer";
+
+export default async (req, res) => {
+ const id = Utilities.getIdFromCookie(req);
+ if (!id) {
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
+ }
+
+ const user = await Data.getUserById({
+ id,
+ });
+
+ if (!user) {
+ return res.status(404).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
+ }
+
+ if (user.error) {
+ return res.status(500).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
+ }
+
+ let files;
+ if (req.body.data.file) {
+ files = [req.body.data.file];
+ }
+ if (req.body.data.files) {
+ files = req.body.data.files;
+ } else {
+ return res.status(400).send({ decorator: "CREATE_FILE_NO_FILE_PROVIDED", error: true });
+ }
+
+ const duplicateFiles = await Data.getFilesByCids({
+ ownerId: user.id,
+ cids: files.map((file) => file.cid),
+ });
+ const duplicateCids = duplicateFiles.map((file) => file.cid);
+
+ let newFiles = files.filter((file) => !duplicateCids.includes(file.cid));
+
+ if (!newFiles.length) {
+ return res.status(400).send({ decorator: "CREATE_FILE_DUPLICATE", error: true });
+ }
+
+ newFiles = newFiles.map((file) => {
+ return { ...file, ownerId: user.id };
+ });
+
+ const response = await Data.createFile(newFiles);
+
+ if (!response) {
+ return res.status(404).send({ decorator: "CREATE_FILE_FAILED", error: true });
+ }
+
+ if (response.error) {
+ return res.status(500).send({ decorator: response.decorator, error: response.error });
+ }
+
+ ViewerManager.hydratePartial(id, { library: true });
+
+ return res.status(200).send({
+ decorator: "CREATE_FILE",
+ data: response,
+ });
+};
diff --git a/pages/api/data/delete.js b/pages/api/data/delete.js
new file mode 100644
index 00000000..dcacc095
--- /dev/null
+++ b/pages/api/data/delete.js
@@ -0,0 +1,178 @@
+import * as Data from "~/node_common/data";
+import * as Utilities from "~/node_common/utilities";
+import * as Strings from "~/common/strings";
+import * as Social from "~/node_common/social";
+import * as ViewerManager from "~/node_common/managers/viewer";
+import * as SearchManager from "~/node_common/managers/search";
+
+const DEFAULT_BUCKET_NAME = "data";
+
+export default async (req, res) => {
+ const id = Utilities.getIdFromCookie(req);
+ if (!id) {
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
+ }
+
+ let ids;
+ if (req.body.data.ids) {
+ ids = req.body.data.ids;
+ } else if (req.body.data.id) {
+ ids = [req.body.data.id];
+ }
+
+ if (!ids?.length) {
+ return res.status(400).send({ decorator: "SERVER_REMOVE_DATA_NO_IDS", error: true });
+ }
+
+ const user = await Data.getUserById({
+ id,
+ });
+
+ if (!user) {
+ return res.status(404).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
+ }
+
+ if (user.error) {
+ return res.status(500).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
+ }
+
+ const { buckets, bucketKey } = await Utilities.getBucketAPIFromUserToken({
+ user,
+ });
+
+ if (!buckets) {
+ return res.status(500).send({
+ decorator: "SERVER_NO_BUCKET_DATA",
+ error: true,
+ });
+ }
+
+ // TODO(jim): Put this call into a file for all Textile related calls.
+ let r = null;
+ try {
+ r = await buckets.list();
+ } catch (e) {
+ Social.sendTextileSlackMessage({
+ file: "/pages/api/data/delete.js",
+ user,
+ message: e.message,
+ code: e.code,
+ functionName: `buckets.list`,
+ });
+ }
+
+ if (!r) {
+ return res.status(500).send({ decorator: "SERVER_NO_BUCKET_DATA", error: true });
+ }
+
+ // TODO(jim): Put this call into a file for all Textile related calls.
+ let items = [];
+ try {
+ for (let i = 0; i < r.length; i++) {
+ if (r[i].name === DEFAULT_BUCKET_NAME) {
+ const next = await buckets.listPath(r[i].key, "/");
+ const set = next.item.items;
+ items = [...set, ...items];
+ }
+ }
+ } catch (e) {
+ Social.sendTextileSlackMessage({
+ file: "/pages/api/data/delete.js",
+ user,
+ message: e.message,
+ code: e.code,
+ functionName: `buckets.listIpfsPath`,
+ });
+ }
+
+ if (!items || !items.length) {
+ return res.status(500).send({ decorator: "SERVER_NO_BUCKET_DATA", error: true });
+ }
+
+ //NOTE(martina): get the cids of the corresponding coverImages that are to be deleted
+ let files = await Data.getFilesByIds({ ids });
+ let cids = files.map((file) => file.cid);
+ let coverImageCids = [];
+ for (let file of files) {
+ if (file.data.coverImage) {
+ coverImageCids.push(file.data.coverImage.cid);
+ }
+ }
+
+ //NOTE(martina): cover images that also exist in the library should not be deleted
+ let filesMatchingCoverImages = await Data.getFilesByCids({
+ ownerId: user.id,
+ cids: coverImageCids,
+ });
+ let excludedCoverImageCids = filesMatchingCoverImages.map((file) => file.cid);
+
+ for (let cid of coverImageCids) {
+ if (!excludedCoverImageCids.includes(cid)) {
+ cids.push(cid);
+ }
+ }
+
+ let entities = [];
+ for (let i = 0; i < items.length; i++) {
+ if (cids.includes(items[i].cid)) {
+ entities.push(items[i]);
+ continue;
+ }
+
+ // NOTE(jim): Maybe the CID is missing, but our names/ids are guaranteed to be unique.
+ if (ids.includes(items[i].name) || ids.includes(items[i].name.replace("data-", ""))) {
+ //NOTE(martina): older file ids were prefixed with "data-", so this is to account for that
+ entities.push(items[i]);
+ continue;
+ }
+
+ // NOTE(jim): Perform path check against cid as a last resort.
+ for (let j = 0; j < cids.length; j++) {
+ if (items[i].path.includes(cids[j])) {
+ entities.push(items[i]);
+ continue;
+ }
+ }
+
+ // NOTE(jim): Perform path check against name as a last resort.
+ for (let j = 0; j < ids.length; j++) {
+ if (items[i].path.includes(ids[j]) || items[i].path.includes(`data-${ids[j]}`)) {
+ //NOTE(martina): older file ids were prefixed with "data-", so this is to account for that
+ entities.push(items[i]);
+ continue;
+ }
+ }
+ }
+
+ if (entities.length) {
+ for (let entity of entities) {
+ try {
+ // NOTE(jim): We use name (aka. what we call id) instead of path because the second argument is for
+ // a subpath, not the full path.
+ await buckets.removePath(bucketKey, entity.name);
+ } catch (e) {
+ Social.sendTextileSlackMessage({
+ file: "/pages/api/data/delete.js",
+ user: user,
+ message: e.message,
+ code: e.code,
+ functionName: `buckets.removePath`,
+ });
+
+ continue;
+ }
+ }
+ }
+
+ await Data.deleteFilesByIds({ ownerId: id, ids });
+
+ SearchManager.updateFile(files, "REMOVE");
+
+ ViewerManager.hydratePartial(id, { slates: true, library: true });
+
+ return res.status(200).send({
+ decorator: "SERVER_REMOVE_DATA",
+ success: true,
+ bucketItems: items,
+ });
+};
diff --git a/pages/api/data/get.js b/pages/api/data/get-bucket.js
similarity index 68%
rename from pages/api/data/get.js
rename to pages/api/data/get-bucket.js
index af16ab11..f3535f4d 100644
--- a/pages/api/data/get.js
+++ b/pages/api/data/get-bucket.js
@@ -3,17 +3,10 @@ import * as Data from "~/node_common/data";
import * as Utilities from "~/node_common/utilities";
import * as Social from "~/node_common/social";
-const TEXTILE_KEY_INFO = {
- key: Environment.TEXTILE_HUB_KEY,
- secret: Environment.TEXTILE_HUB_SECRET,
-};
-
export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
if (!id) {
- return res
- .status(500)
- .send({ decorator: "SERVER_GET_BUCKET_DATA", error: true });
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
}
const user = await Data.getUserById({
@@ -25,9 +18,7 @@ export default async (req, res) => {
});
if (!buckets) {
- return res
- .status(500)
- .send({ decorator: "SERVER_GET_BUCKET_INIT", error: true });
+ return res.status(500).send({ decorator: "SERVER_NO_BUCKET_DATA", error: true });
}
// TODO(jim): Put this call into a file for all Textile related calls.
@@ -36,7 +27,7 @@ export default async (req, res) => {
r = await buckets.list();
} catch (e) {
Social.sendTextileSlackMessage({
- file: "/pages/api/data/get.js",
+ file: "/pages/api/data/get-bucket.js",
user,
message: e.message,
code: e.code,
@@ -45,9 +36,7 @@ export default async (req, res) => {
}
if (!r) {
- return res
- .status(500)
- .send({ decorator: "SERVER_GET_BUCKET_NO_TEXTILE", error: true });
+ return res.status(500).send({ decorator: "SERVER_NO_BUCKET_DATA", error: true });
}
// TODO(jim): Put this call into a file for all Textile related calls.
@@ -65,9 +54,7 @@ export default async (req, res) => {
}
if (!items) {
- return res
- .status(500)
- .send({ decorator: "SERVER_GET_BUCKET_NO_TEXTILE", error: true });
+ return res.status(500).send({ decorator: "SERVER_NO_BUCKET_DATA", error: true });
}
return res.status(200).send({
diff --git a/pages/api/data/process-pending.js b/pages/api/data/process-pending.js
deleted file mode 100644
index 7188e72c..00000000
--- a/pages/api/data/process-pending.js
+++ /dev/null
@@ -1,67 +0,0 @@
-import * as Utilities from "~/node_common/utilities";
-import * as Data from "~/node_common/data";
-import * as LibraryManager from "~/node_common/managers/library";
-import * as ViewerManager from "~/node_common/managers/viewer";
-
-export default async (req, res) => {
- const id = Utilities.getIdFromCookie(req);
-
- if (!id) {
- return res.status(500).send({ decorator: "PROCESS_PENDING_ERROR", error: true });
- }
-
- const user = await Data.getUserById({
- id,
- });
-
- if (!user) {
- return res.status(404).send({
- decorator: "PROCESS_PENDING_USER_NOT_FOUND",
- error: true,
- });
- }
-
- if (user.error) {
- return res.status(500).send({
- decorator: "PROCESS_PENDING_USER_NOT_FOUND",
- error: true,
- });
- }
-
- const pending = await Data.deletePendingDataByUserId({ owner_user_id: id });
-
- if (!pending) {
- return res.status(404).send({ decorator: "PROCESS_PENDING_ERROR", error: true });
- }
-
- if (pending.error) {
- return res.status(500).send({ decorator: response.decorator, error: response.error });
- }
-
- let cids = [];
- let noRepeats = [];
- for (let entry of pending) {
- if (cids.includes(entry.data.cid)) continue;
- cids.push(entry.data.cid);
- noRepeats.push(entry.data);
- }
-
- const { updatedUserDataFields, added, skipped } = LibraryManager.addData({
- user,
- files: noRepeats,
- });
-
- await Data.updateUserById({
- id,
- data: updatedUserDataFields,
- });
-
- if (added && updatedUserDataFields && updatedUserDataFields.library) {
- ViewerManager.hydratePartialLibrary(updatedUserDataFields.library, id);
- }
-
- return res.status(200).send({
- decorator: "PROCESS_PENDING_DATA",
- data: { added, skipped: skipped + pending.length - noRepeats.length },
- });
-};
diff --git a/pages/api/data/remove.js b/pages/api/data/remove.js
deleted file mode 100644
index 7799677a..00000000
--- a/pages/api/data/remove.js
+++ /dev/null
@@ -1,215 +0,0 @@
-import * as Data from "~/node_common/data";
-import * as Utilities from "~/node_common/utilities";
-import * as Strings from "~/common/strings";
-import * as Social from "~/node_common/social";
-import * as ViewerManager from "~/node_common/managers/viewer";
-import * as SearchManager from "~/node_common/managers/search";
-
-const DEFAULT_BUCKET_NAME = "data";
-
-export default async (req, res) => {
- if (!req.body.data || !req.body.data.cids || !req.body.data.cids.length) {
- return res.status(500).send({ decorator: "SERVER_REMOVE_DATA_NO_CID", error: true });
- }
-
- const id = Utilities.getIdFromCookie(req);
- if (!id) {
- return res.status(403).send({ decorator: "SERVER_REMOVE_DATA_NOT_ALLOWED", error: true });
- }
-
- const user = await Data.getUserById({
- id,
- });
-
- const { buckets, bucketKey } = await Utilities.getBucketAPIFromUserToken({
- user,
- });
-
- if (!buckets) {
- return res.status(500).send({
- decorator: "SERVER_BUCKET_INIT_FAILURE",
- error: true,
- });
- }
-
- // TODO(jim): Put this call into a file for all Textile related calls.
- let r = null;
- try {
- r = await buckets.list();
- } catch (e) {
- Social.sendTextileSlackMessage({
- file: "/pages/api/data/remove-multiple.js",
- user,
- message: e.message,
- code: e.code,
- functionName: `buckets.list`,
- });
- }
-
- if (!r) {
- return res.status(500).send({ decorator: "SERVER_REMOVE_MULTIPLE_NO_TEXTILE", error: true });
- }
-
- // TODO(jim): Put this call into a file for all Textile related calls.
- let items = [];
- try {
- for (let i = 0; i < r.length; i++) {
- if (r[i].name === DEFAULT_BUCKET_NAME) {
- const next = await buckets.listPath(r[i].key, "/");
- const set = next.item.items;
- items = [...set, ...items];
- }
- }
- } catch (e) {
- Social.sendTextileSlackMessage({
- file: "/pages/api/data/remove-multiple.js",
- user,
- message: e.message,
- code: e.code,
- functionName: `buckets.listIpfsPath`,
- });
- }
-
- if (!items || !items.length) {
- return res.status(500).send({ decorator: "SERVER_NO_ITEMS_FOUND", error: true });
- }
-
- //NOTE(martina): get the cids of the corresponding coverImages that are to be deleted (if they do not exist elsewhere in library)
- let coverImageCids = [];
-
- let children = user.data.library[0].children.filter((o) => {
- for (let cid of req.body.data.cids) {
- if (o.cid && o.cid === cid) {
- if (o.coverImage) {
- coverImageCids.push(o.coverImage.cid);
- }
- return false;
- }
- }
- return true;
- });
-
- let libraryCids = user.data.library[0].children.map((item) => item.cid);
- coverImageCids = coverImageCids.filter((cid) => {
- if (libraryCids.includes(cid)) {
- return false;
- }
- return true;
- });
-
- let entities = [];
- let ids = req.body.data.ids && req.body.data.ids.length ? req.body.data.ids : [];
- for (let i = 0; i < items.length; i++) {
- if (req.body.data.cids.includes(items[i].cid)) {
- entities.push(items[i]);
- continue;
- }
-
- if (coverImageCids.includes(items[i].cid)) {
- entities.push(items[i]);
- continue;
- }
-
- // NOTE(jim): Maybe the CID is missing, but our names/ids are guaranteed to be unique.
- if (ids.includes(items[i].name)) {
- entities.push(items[i]);
- continue;
- }
-
- // NOTE(jim): Perform path check against cid as a last resort.
- for (let j = 0; j < req.body.data.cids.length; j++) {
- if (items[i].path.includes(req.body.data.cids[j])) {
- entities.push(items[i]);
- continue;
- }
- }
-
- // NOTE(jim): Perform path check against name as a last resort.
- for (let j = 0; j < ids.length; j++) {
- if (items[i].path.includes(ids[j])) {
- entities.push(items[i]);
- continue;
- }
- }
- }
-
- if (entities.length) {
- // remove from your bucket
- for (let entity of entities) {
- try {
- // NOTE(jim):
- // We use name instead of path because the second argument is for
- // a subpath, not the full path.
- await buckets.removePath(bucketKey, entity.name);
- } catch (e) {
- Social.sendTextileSlackMessage({
- file: "/pages/api/data/remove.js",
- user: user,
- message: e.message,
- code: e.code,
- functionName: `buckets.removePath`,
- });
-
- continue;
- }
- }
- }
-
- let refreshSlates = false;
- // NOTE(martina):
- // Removes the file from all of your slates and any slates it was reposted to from yours
- for (let cid of req.body.data.cids) {
- let slates = await Data.getSlateObjectsByCID({
- url: Strings.getCIDGatewayURL(cid),
- ownerId: id,
- });
- for (let slate of slates) {
- let objects = slate.data.objects.filter((o) => {
- if (o.url.includes(cid)) return false;
- return true;
- });
- let newSlate = await Data.updateSlateById({
- id: slate.id,
- updated_at: new Date(),
- data: {
- ...slate.data,
- objects,
- },
- });
- if (slate.data.ownerId === id) {
- refreshSlates = true;
- }
- SearchManager.updateSlate(newSlate, "EDIT");
- }
- }
-
- if (refreshSlates) {
- let slates = await Data.getSlatesByUserId({ userId: id });
- ViewerManager.hydratePartialSlates(slates, id);
- }
-
- // NOTE(jim):
- // Removes the file reference from your library
- const unsafeResponse = await Data.updateUserById({
- id: user.id,
- data: {
- ...user.data,
- library: [
- {
- ...user.data.library[0],
- children,
- },
- ],
- },
- });
-
- if (unsafeResponse) {
- ViewerManager.hydratePartialViewer(unsafeResponse);
- }
-
- return res.status(200).send({
- decorator: "SERVER_REMOVE_DATA",
- success: true,
- bucketItems: items,
- });
-};
diff --git a/pages/api/data/save-copy.js b/pages/api/data/save-copy.js
new file mode 100644
index 00000000..e3648c08
--- /dev/null
+++ b/pages/api/data/save-copy.js
@@ -0,0 +1,99 @@
+import * as Utilities from "~/node_common/utilities";
+import * as Data from "~/node_common/data";
+import * as SearchManager from "~/node_common/managers/search";
+import * as ViewerManager from "~/node_common/managers/viewer";
+
+import { Buckets, PrivateKey, Filecoin, Client, ThreadID } from "@textile/hub";
+
+/**
+ * Save copy is equivalent to downloading then reuploading. So an entirely new files table entry should
+ * be created with a new id, ownerId, and createdAt
+ */
+export default async (req, res) => {
+ const id = Utilities.getIdFromCookie(req);
+ if (!id) {
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
+ }
+ console.log(req.body.data);
+
+ if (!req.body.data.files?.length) {
+ return res.status(400).send({
+ decorator: "SERVER_SAVE_COPY_NO_CIDS",
+ error: true,
+ });
+ }
+
+ const user = await Data.getUserById({
+ id,
+ });
+
+ if (!user) {
+ return res.status(404).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
+ }
+
+ if (user.error) {
+ return res.status(500).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
+ }
+
+ let { buckets, bucketKey, bucketRoot, bucketName } = await Utilities.getBucketAPIFromUserToken({
+ user,
+ });
+
+ if (!buckets) {
+ return res.status(500).send({
+ decorator: "SERVER_NO_BUCKET_DATA",
+ error: true,
+ });
+ }
+
+ const duplicateFiles = await Data.getFilesByCids({
+ ownerId: user.id,
+ cids: req.body.data.files.map((file) => file.cid),
+ });
+
+ const duplicateCids = duplicateFiles.map((file) => file.cid);
+
+ const foundFiles = await Data.getFilesByIds({ ids: req.body.data.files.map((file) => file.id) });
+
+ const foundIds = foundFiles.map((file) => file.id);
+
+ let newFiles = [];
+ for (let file of req.body.data.files) {
+ const cid = file.cid;
+ if (duplicateCids.includes(cid)) continue; //NOTE(martina): cannot have two of the same cid in a person's files
+
+ if (!foundIds.includes(file.id)) continue; //NOTE(martina): make sure the file being copied exists
+
+ let response = await Utilities.addExistingCIDToData({
+ buckets,
+ key: bucketKey,
+ path: bucketRoot.path,
+ cid,
+ });
+
+ if (!response || response.error) {
+ continue;
+ }
+
+ //NOTE(martina): remove the old file's id, ownerId, createdAt, and privacy so new fields can be used
+ delete file.createdAt;
+ delete file.id;
+ delete file.isPublic;
+ file.ownerId = user.id;
+ newFiles.push(file);
+ }
+ let response = [];
+ if (newFiles?.length) {
+ response = await Data.createFile(newFiles);
+ }
+
+ ViewerManager.hydratePartial(id, { library: true });
+
+ const added = response?.length || 0;
+ const skipped = req.body.data.files.length - added;
+
+ return res.status(200).send({
+ decorator: "SERVER_SAVE_COPY",
+ data: { added, skipped },
+ });
+};
diff --git a/pages/api/data/toggle-privacy.js b/pages/api/data/toggle-privacy.js
index f4171440..f1426991 100644
--- a/pages/api/data/toggle-privacy.js
+++ b/pages/api/data/toggle-privacy.js
@@ -1,82 +1,51 @@
import * as Data from "~/node_common/data";
import * as Utilities from "~/node_common/utilities";
-import * as LibraryManager from "~/node_common/managers/library";
import * as ViewerManager from "~/node_common/managers/viewer";
import * as SearchManager from "~/node_common/managers/search";
export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
if (!id) {
- return res.status(500).send({ decorator: "SERVER_EDIT_DATA", error: true });
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
}
const user = await Data.getUserById({ id });
- if (!user || user.error) {
- return res.status(403).send({ decorator: "SERVER_EDIT_DATA_USER_NOT_FOUND", error: true });
+
+ if (!user) {
+ return res.status(404).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
}
- let newUserData = LibraryManager.editItem({ user, update: req.body.data });
- let response = await Data.updateUserById({
- id: user.id,
- data: newUserData,
+ if (user.error) {
+ return res.status(500).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
+ }
+
+ if (!req.body.data?.id) {
+ return res.status(500).send({ decorator: "SERVER_TOGGLE_FILE_PRIVACY_NO_FILE", error: true });
+ }
+ let file = req.body.data;
+
+ let response = await Data.updateFilePrivacy({
+ ownerId: file.ownerId,
+ id: file.id,
+ isPublic: !file.isPublic,
});
+
if (!response || response.error) {
- return res.status(500).send({ decorator: "SERVER_EDIT_DATA_NOT_UPDATED", error: true });
+ return res
+ .status(500)
+ .send({ decorator: "SERVER_TOGGLE_FILE_PRIVACY_UPDATE_FAILED", error: true });
}
- let slates = await Data.getSlatesByUserId({ userId: id });
- if (!slates || slates.error) {
- return res.status(500).send({ decorator: "SERVER_SLATES_NOT_FOUND", error: true });
- }
- if (!req.body.data.data.public) {
- //NOTE(martina): if toggling a file to private, must remove it from any public slates as well
- let slatesChanged = false;
- for (let slate of slates) {
- let edited = false;
- if (!slate.data.public) {
- continue;
- }
- let objects = slate.data.objects.filter((obj) => {
- if (obj.id === req.body.data.data.id) {
- edited = true;
- slatesChanged = true;
- return false;
- }
- return true;
- });
-
- if (edited) {
- await Data.updateSlateById({
- id: slate.id,
- updated_at: new Date(),
- data: {
- ...slate.data,
- objects,
- },
- });
- SearchManager.updateSlate(slate, "EDIT");
- }
- }
-
- if (slatesChanged) {
- let userSlates = await Data.getSlatesByUserId({ userId: id });
- if (!userSlates || userSlates.error) {
- return res.status(500).send({ decorator: "SERVER_SLATES_NOT_FOUND", error: true });
- }
- ViewerManager.hydratePartialSlates(userSlates, id);
- } else {
- //remove it from the search index as an individual file
- }
+ if (response.isPublic) {
+ SearchManager.updateFile(response, "ADD");
} else {
- //add to search index as an individual file
+ SearchManager.updateFile(response, "REMOVE");
}
- if (newUserData && newUserData.library) {
- ViewerManager.hydratePartialLibrary(newUserData.library, id);
- }
+ ViewerManager.hydratePartial(id, { library: true, slates: true });
return res.status(200).send({
- decorator: "SERVER_EDIT_DATA",
+ decorator: "SERVER_TOGGLE_FILE_PRIVACY",
data: {},
});
};
diff --git a/pages/api/data/update.js b/pages/api/data/update.js
index fcdc154a..35be64d9 100644
--- a/pages/api/data/update.js
+++ b/pages/api/data/update.js
@@ -1,70 +1,42 @@
import * as Data from "~/node_common/data";
import * as Utilities from "~/node_common/utilities";
-import * as LibraryManager from "~/node_common/managers/library";
import * as ViewerManager from "~/node_common/managers/viewer";
import * as SearchManager from "~/node_common/managers/search";
export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
if (!id) {
- return res.status(500).send({ decorator: "SERVER_EDIT_DATA", error: true });
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
}
const user = await Data.getUserById({ id });
- if (!user || user.error) {
- return res.status(403).send({ decorator: "SERVER_EDIT_DATA_USER_NOT_FOUND", error: true });
+
+ if (!user) {
+ return res.status(404).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
}
- let newUserData = LibraryManager.editItem({ user, update: req.body.data });
- let response = await Data.updateUserById({
- id: user.id,
- data: newUserData,
- });
+ if (user.error) {
+ return res.status(500).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
+ }
+
+ let updates = req.body.data;
+ if (!updates?.id) {
+ return res.status(500).send({ decorator: "SERVER_EDIT_DATA_NO_FILE", error: true });
+ }
+
+ let response = await Data.updateFileById(updates);
+
if (!response || response.error) {
- return res.status(500).send({ decorator: "SERVER_EDIT_DATA_NOT_UPDATED", error: true });
+ return res.status(500).send({ decorator: "SERVER_EDIT_DATA_FAILED", error: true });
}
- let slates = await Data.getSlatesByUserId({ userId: id });
- if (!slates || slates.error) {
- return res.status(500).send({ decorator: "SERVER_SLATES_NOT_FOUND", error: true });
+ const publicFiles = await Data.getFilesByIds({ ids: [response.id], publicOnly: true });
+
+ if (publicFiles.length) {
+ SearchManager.updateFile(publicFiles, "EDIT");
}
- let slatesChanged = false;
- for (let slate of slates) {
- let edited = false;
- let objects = slate.data.objects.map((obj) => {
- if (obj.id === req.body.data.id) {
- edited = true;
- slatesChanged = true;
- obj = { ...obj, ...req.body.data };
- }
- return obj;
- });
-
- if (edited) {
- await Data.updateSlateById({
- id: slate.id,
- updated_at: new Date(),
- data: {
- ...slate.data,
- objects,
- },
- });
- SearchManager.updateSlate(slate, "EDIT");
- }
- }
-
- if (slatesChanged) {
- let userSlates = await Data.getSlatesByUserId({ userId: id });
- if (!userSlates || userSlates.error) {
- return res.status(500).send({ decorator: "SERVER_SLATES_NOT_FOUND", error: true });
- }
- ViewerManager.hydratePartialSlates(userSlates, id);
- }
-
- if (newUserData && newUserData.library) {
- ViewerManager.hydratePartialLibrary(newUserData.library, id);
- }
+ ViewerManager.hydratePartial(id, { library: true, slates: true });
return res.status(200).send({
decorator: "SERVER_EDIT_DATA",
diff --git a/pages/api/directory.js b/pages/api/directory.js
deleted file mode 100644
index 08177f15..00000000
--- a/pages/api/directory.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import * as Data from "~/node_common/data";
-import * as Serializers from "~/node_common/serializers";
-
-export default async (req, res) => {
- const users = await Data.getEveryUser();
- const slates = await Data.getEverySlate();
-
- const { serializedSlates, userToSlatesMap } = await Serializers.doSlates({
- serializedUsers: users,
- slates,
- });
-
- for (let i = 0; i < users.length; i++) {
- users[i].slates = userToSlatesMap[users[i].id];
- }
-
- return res.status(200).send({
- decorator: "SERVER_DIRECTORY",
- data: { users, slates: serializedSlates },
- });
-};
diff --git a/pages/api/hydrate.js b/pages/api/hydrate.js
index 46615ccf..f1c986a8 100644
--- a/pages/api/hydrate.js
+++ b/pages/api/hydrate.js
@@ -4,7 +4,7 @@ import * as Utilities from "~/node_common/utilities";
export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
if (!id) {
- return res.status(500).send({ decorator: "SERVER_HYDRATE_FAILURE", error: true });
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
}
const data = await ViewerManager.getById({ id });
diff --git a/pages/api/keys/delete.js b/pages/api/keys/delete.js
index 0f94ea89..144c9f1e 100644
--- a/pages/api/keys/delete.js
+++ b/pages/api/keys/delete.js
@@ -6,7 +6,7 @@ import * as ViewerManager from "~/node_common/managers/viewer";
export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
if (!id) {
- return res.status(500).send({ decorator: "SERVER_DELETE_API_KEY_AUTH", error: true });
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
}
const user = await Data.getUserById({
@@ -15,21 +15,21 @@ export default async (req, res) => {
if (!user) {
return res.status(404).send({
- decorator: "SERVER_DELETE_API_KEY_USER_NOT_FOUND",
+ decorator: "SERVER_USER_NOT_FOUND",
error: true,
});
}
if (user.error) {
return res.status(500).send({
- decorator: "SERVER_DELETE_API_KEY_USER_NOT_FOUND",
+ decorator: "SERVER_USER_NOT_FOUND",
error: true,
});
}
const key = await Data.getAPIKey({ id: req.body.data.id });
- if (!key || key.owner_id !== user.id) {
+ if (!key || key.ownerId !== user.id) {
return res.status(403).send({
decorator: "SERVER_DELETE_API_KEY_NOT_FOUND",
error: true,
@@ -50,7 +50,7 @@ export default async (req, res) => {
});
}
- const response = await Data.deleteAPIKeyById({ id: key.id });
+ const response = await Data.deleteAPIKeyById({ id: req.body.data.id });
if (!response) {
return res.status(404).send({
@@ -66,8 +66,10 @@ export default async (req, res) => {
});
}
- let keys = await Data.getAPIKeysByUserId({ userId: user.id });
- ViewerManager.hydratePartialKeys(keys, user.id);
+ // let keys = await Data.getAPIKeysByUserId({ userId: user.id });
+ // ViewerManager.hydratePartialKeys(keys, user.id);
+
+ ViewerManager.hydratePartial(id, { keys: true });
return res.status(200).send({ decorator: "SERVER_DELETE_API_KEY" });
};
diff --git a/pages/api/keys/generate.js b/pages/api/keys/generate.js
index 49c06e7b..33695178 100644
--- a/pages/api/keys/generate.js
+++ b/pages/api/keys/generate.js
@@ -8,7 +8,7 @@ import { v4 as uuid } from "uuid";
export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
if (!id) {
- return res.status(500).send({ decorator: "SERVER_GENERATE_API_KEY_AUTH", error: true });
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
}
const user = await Data.getUserById({
@@ -17,14 +17,14 @@ export default async (req, res) => {
if (!user) {
return res.status(404).send({
- decorator: "SERVER_GENERATE_API_KEY_USER_NOT_FOUND",
+ decorator: "SERVER_USER_NOT_FOUND",
error: true,
});
}
if (user.error) {
return res.status(500).send({
- decorator: "SERVER_GENERATE_API_KEY_USER_NOT_FOUND",
+ decorator: "SERVER_USER_NOT_FOUND",
error: true,
});
}
@@ -38,7 +38,7 @@ export default async (req, res) => {
});
}
- const key = await Data.createAPIKeyForUserId({
+ const key = await Data.createAPIKey({
userId: user.id,
key: `SLA${uuid()}TE`,
});
@@ -57,8 +57,10 @@ export default async (req, res) => {
});
}
- keys = await Data.getAPIKeysByUserId({ userId: user.id });
- ViewerManager.hydratePartialKeys(keys, user.id);
+ // keys = await Data.getAPIKeysByUserId({ userId: user.id });
+ // ViewerManager.hydratePartialKeys(keys, user.id);
+
+ ViewerManager.hydratePartial(id, { keys: true });
return res.status(200).send({ decorator: "SERVER_GENERATE_API_KEY", key });
};
diff --git a/pages/api/network-deals.js b/pages/api/network-deals.js
index d92fa413..d07f274e 100644
--- a/pages/api/network-deals.js
+++ b/pages/api/network-deals.js
@@ -4,9 +4,7 @@ import * as Utilities from "~/node_common/utilities";
export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
if (!id) {
- return res
- .status(500)
- .send({ decorator: "SERVER_FILECOIN_NETWORK_DEALS_FAILURE", error: true });
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
}
const data = await ViewerManager.getDealHistory({ id });
diff --git a/pages/api/network.js b/pages/api/network.js
index cf55b00f..cd1881f3 100644
--- a/pages/api/network.js
+++ b/pages/api/network.js
@@ -4,24 +4,18 @@ import * as Utilities from "~/node_common/utilities";
export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
if (!id) {
- return res
- .status(500)
- .send({ decorator: "SERVER_FILECOIN_NETWORK_FAILURE", error: true });
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
}
const data = await ViewerManager.getTextileById({ id });
if (!data) {
- return res
- .status(500)
- .send({
- decorator: "SERVER_FILECOIN_NETWORK_ERROR",
- error: true,
- data: null,
- });
+ return res.status(500).send({
+ decorator: "SERVER_FILECOIN_NETWORK_ERROR",
+ error: true,
+ data: null,
+ });
}
- return res
- .status(200)
- .send({ decorator: "SERVER_FILECOIN_NETWORK", success: true, data });
+ return res.status(200).send({ decorator: "SERVER_FILECOIN_NETWORK", success: true, data });
};
diff --git a/pages/api/search/update.js b/pages/api/search/update.js
index 96c47f36..870235aa 100644
--- a/pages/api/search/update.js
+++ b/pages/api/search/update.js
@@ -6,9 +6,8 @@ import * as SearchManager from "~/node_common/managers/search";
export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
- console.log(req.body);
if (!id) {
- return res.status(500).send({ decorator: "SERVER_SEARCH_UPDATE", error: true });
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
}
const user = await Data.getUserById({
@@ -16,11 +15,11 @@ export default async (req, res) => {
});
if (!user) {
- return res.status(404).send({ decorator: "SERVER_SEARCH_UPDATE_USER_NOT_FOUND", error: true });
+ return res.status(404).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
}
if (user.error) {
- return res.status(500).send({ decorator: "SERVER_SEARCH_UPDATE_USER_NOT_FOUND", error: true });
+ return res.status(500).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
}
let action;
diff --git a/pages/api/sign-in.js b/pages/api/sign-in.js
index 623ed3b6..ffd3fd00 100644
--- a/pages/api/sign-in.js
+++ b/pages/api/sign-in.js
@@ -7,16 +7,16 @@ import JWT from "jsonwebtoken";
export default async (req, res) => {
if (!Strings.isEmpty(Environment.ALLOWED_HOST) && req.headers.host !== Environment.ALLOWED_HOST) {
- return res.status(403).send({ decorator: "YOU_ARE_NOT_ALLOWED", error: true });
+ return res.status(403).send({ decorator: "SERVER_SIGN_IN_NOT_ALLOWED", error: true });
}
// NOTE(jim): We don't need to validate here.
if (Strings.isEmpty(req.body.data.username)) {
- return res.status(500).send({ decorator: "SERVER_SIGN_IN", error: true });
+ return res.status(500).send({ decorator: "SERVER_SIGN_IN_NO_USERNAME", error: true });
}
if (Strings.isEmpty(req.body.data.password)) {
- return res.status(500).send({ decorator: "SERVER_SIGN_IN", error: true });
+ return res.status(500).send({ decorator: "SERVER_SIGN_IN_NO_PASSWORD", error: true });
}
let user;
@@ -33,15 +33,17 @@ export default async (req, res) => {
}
if (user.error) {
- return res.status(500).send({ decorator: "SERVER_SIGN_IN_ERROR", error: true });
+ return res.status(500).send({ decorator: "SERVER_SIGN_IN_USER_NOT_FOUND", error: true });
}
const hash = await Utilities.encryptPassword(req.body.data.password, user.salt);
if (hash !== user.password) {
- return res.status(403).send({ decorator: "SERVER_SIGN_IN_AUTH", error: true });
+ return res.status(403).send({ decorator: "SERVER_SIGN_IN_WRONG_PASSWORD", error: true });
}
+ await Data.updateUserById({ id: user.id, lastActive: new Date() });
+
const authorization = Utilities.parseAuthHeader(req.headers.authorization);
if (authorization && !Strings.isEmpty(authorization.value)) {
const verfied = JWT.verify(authorization.value, Environment.JWT_SECRET);
diff --git a/pages/api/slates/add-file.js b/pages/api/slates/add-file.js
new file mode 100644
index 00000000..f98a4fda
--- /dev/null
+++ b/pages/api/slates/add-file.js
@@ -0,0 +1,134 @@
+import * as Constants from "~/node_common/constants";
+import * as Utilities from "~/node_common/utilities";
+import * as Data from "~/node_common/data";
+import * as Strings from "~/common/strings";
+import * as ViewerManager from "~/node_common/managers/viewer";
+import * as Monitor from "~/node_common/monitor";
+import * as SearchManager from "~/node_common/managers/search";
+
+/**
+ * SLATEID: id of the slate you are adding the files to
+ * FILES: to pass in an array of files
+ * FILE: to pass in a single file
+ */
+export default async (req, res) => {
+ const id = Utilities.getIdFromCookie(req);
+ if (!id) {
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
+ }
+ console.log(req.body.data);
+
+ const user = await Data.getUserById({
+ id,
+ });
+
+ if (!user) {
+ return res.status(404).send({
+ decorator: "SERVER_USER_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ if (user.error) {
+ return res.status(500).send({
+ decorator: "SERVER_USER_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ const slateId = req.body.data.slate?.id;
+
+ if (!slateId) {
+ return res.status(400).send({
+ decorator: "SERVER_ADD_TO_SLATE_NO_SLATE",
+ error: true,
+ });
+ }
+
+ const slate = await Data.getSlateById({ id: slateId });
+
+ if (!slate) {
+ return res.status(404).send({
+ decorator: "SERVER_ADD_TO_SLATE_SLATE_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ if (slate.error) {
+ return res.status(500).send({
+ decorator: "SERVER_ADD_TO_SLATE_SLATE_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ let files;
+ if (req.body.data.files) {
+ files = req.body.data.files;
+ } else if (req.body.data.file) {
+ files = [req.body.data.file];
+ } else {
+ return res.status(400).send({
+ decorator: "SERVER_ADD_TO_SLATE_NO_FILES",
+ error: true,
+ });
+ }
+ console.log(files);
+
+ let duplicateCids = await Data.getSlateFilesByCids({
+ slateId: slateId,
+ cids: files.map((file) => file.cid),
+ });
+
+ if (duplicateCids?.length) {
+ duplicateCids = duplicateCids.map((file) => file.cid);
+ files = files.filter((file) => {
+ if (duplicateCids.includes(file.cid)) return false;
+ return true;
+ });
+ }
+
+ if (!files.length) {
+ return res.status(200).send({
+ decorator: "SERVER_SLATE_ADD_TO_SLATE",
+ added: 0,
+ skipped: req.body.data.files.length,
+ slate,
+ });
+ }
+
+ let slateFiles = files.map((file) => {
+ return { slateId: slateId, fileId: file.id };
+ });
+
+ let response = await Data.createSlateFiles(slateFiles);
+ if (!response || response.error) {
+ return res.status(500).send({
+ decorator: "SERVER_ADD_TO_SLATE_FAILED",
+ error: true,
+ });
+ }
+
+ await Data.updateSlateById({ id: slateId, updatedAt: new Date() });
+
+ if (slate.isPublic) {
+ Monitor.createSlateObjects({ slate, user, files });
+
+ const publicFiles = await Data.getFilesByIds({
+ ids: req.body.data.files.map((file) => file.id),
+ publicOnly: true,
+ });
+
+ if (publicFiles.length) {
+ SearchManager.updateFile(publicFiles, "ADD");
+ }
+ }
+
+ ViewerManager.hydratePartial(id, { slates: true });
+
+ return res.status(200).send({
+ decorator: "SERVER_SLATE_ADD_TO_SLATE",
+ added: files.length,
+ skipped: req.body.data.files.length - files.length,
+ slate,
+ });
+};
diff --git a/pages/api/slates/create.js b/pages/api/slates/create.js
index 8dc8cf34..a5ae97b1 100644
--- a/pages/api/slates/create.js
+++ b/pages/api/slates/create.js
@@ -5,12 +5,10 @@ import * as Monitor from "~/node_common/monitor";
import * as ViewerManager from "~/node_common/managers/viewer";
import * as SearchManager from "~/node_common/managers/search";
-const SLATE_LIMIT = 50;
-
export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
if (!id) {
- return res.status(500).send({ decorator: "SERVER_FIND_USER_CREATE_SLATE", error: true });
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
}
const user = await Data.getUserById({
@@ -19,86 +17,54 @@ export default async (req, res) => {
if (!user) {
return res.status(404).json({
- decorator: "SERVER_FIND_USER_CREATE_SLATE_USER_NOT_FOUND",
+ decorator: "SERVER_USER_NOT_FOUND",
error: true,
});
}
if (user.error) {
return res.status(500).json({
- decorator: "SERVER_FIND_USER_CREATE_SLATE_USER_NOT_FOUND",
+ decorator: "SERVER_USER_NOT_FOUND",
error: true,
});
}
const slatename = Strings.createSlug(req.body.data.name);
- const found = await Data.getSlateByName({
+ const existingSlate = await Data.getSlateByName({
slatename,
ownerId: user.id,
});
- if (found) {
- return res.status(500).send({ decorator: "SERVER_EXISTING_SLATE", error: true });
- }
-
- let slates = await Data.getSlatesByUserId({ userId: id });
- if (slates.length >= SLATE_LIMIT) {
- return res.status(500).send({ decorator: "SERVER_SLATE_LIMIT", error: true });
+ if (existingSlate) {
+ return res
+ .status(500)
+ .send({ decorator: "SERVER_CREATE_SLATE_EXISTING_SLATE_NAME", error: true });
}
const slate = await Data.createSlate({
+ ownerId: id,
slatename: Strings.createSlug(req.body.data.name),
+ isPublic: req.body.data.isPublic,
data: {
- public: req.body.data.public,
- ownerId: id,
name: req.body.data.name,
body: req.body.data.body,
tags: req.body.data.tags,
- objects: [],
},
});
- if (!slate) {
- return res.status(500).send({ decorator: "SERVER_CREATE_SLATE", error: true });
+ if (!slate || slate.error) {
+ return res.status(500).send({ decorator: "SERVER_CREATE_SLATE_FAILED", error: true });
}
- if (slate.error) {
- return res.status(500).send({ decorator: "SERVER_CREATE_SLATE", error: true });
- }
+ ViewerManager.hydratePartial(id, { slates: true });
- slates = await Data.getSlatesByUserId({ userId: id });
- if (slates) {
- ViewerManager.hydratePartialSlates(slates, id);
- }
+ SearchManager.updateSlate(slate, "ADD");
- if (slate.data.public) {
- SearchManager.updateSlate(slate, "ADD");
+ if (slate.isPublic) {
+ Monitor.createSlate({ user, slate });
}
-
- Monitor.createSlate({
- userId: user.id,
- data: {
- actorUserId: user.id,
- context: {
- user: {
- id: user.id,
- username: user.username,
- data: {
- photo: user.data.photo,
- name: user.data.name,
- },
- },
- slate: {
- slatename: slate.slatename,
- id: slate.id,
- data: {
- name: slate.data.name,
- },
- },
- },
- },
- });
+ console.log(slate);
return res.status(200).send({ decorator: "SERVER_CREATE_SLATE", slate });
};
diff --git a/pages/api/slates/delete.js b/pages/api/slates/delete.js
index dde24531..b16ebf65 100644
--- a/pages/api/slates/delete.js
+++ b/pages/api/slates/delete.js
@@ -7,7 +7,7 @@ import * as SearchManager from "~/node_common/managers/search";
export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
if (!id) {
- return res.status(500).send({ decorator: "SERVER_DELETE_SLATE", error: true });
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
}
const user = await Data.getUserById({
@@ -16,18 +16,18 @@ export default async (req, res) => {
if (!user) {
return res.status(404).send({
- decorator: "SERVER_DELETE_SLATE_USER_NOT_FOUND",
+ decorator: "SERVER_USER_NOT_FOUND",
error: true,
});
}
if (user.error) {
return res.status(500).send({
- decorator: "SERVER_DELETE_SLATE_USER_NOT_FOUND",
+ decorator: "SERVER_USER_NOT_FOUND",
error: true,
});
}
- const slate = await Data.getSlateById({ id: req.body.data.id });
+ const slate = await Data.getSlateById({ id: req.body.data.id, includeFiles: true });
if (!slate) {
return res.status(404).send({ decorator: "SERVER_DELETE_SLATE_SLATE_NOT_FOUND", error: true });
@@ -40,20 +40,32 @@ export default async (req, res) => {
const deleteResponse = await Data.deleteSlateById({ id: slate.id });
if (!deleteResponse) {
- return res.status(404).send({ decorator: "SERVER_DELETE_SLATE", error: true });
+ return res.status(404).send({ decorator: "SERVER_DELETE_SLATE_FAILED", error: true });
}
if (deleteResponse.error) {
- return res.status(500).send({ decorator: "SERVER_DELETE_SLATE", error: true });
+ return res.status(500).send({ decorator: "SERVER_DELETE_SLATE_FAILED", error: true });
}
- let slates = await Data.getSlatesByUserId({ userId: id });
- if (slates) {
- ViewerManager.hydratePartialSlates(slates, id);
- }
+ ViewerManager.hydratePartial(id, { slates: true });
- if (slate.data.public) {
- SearchManager.updateSlate(slate, "REMOVE");
+ SearchManager.updateSlate(slate, "REMOVE");
+
+ if (slate.isPublic) {
+ //NOTE(martina): if any of the files in it are now private (because they are no longer in any public slates) remove them from search
+ const files = slate.objects;
+
+ const publicFiles = await Data.getFilesByIds({
+ ids: files.map((file) => file.id),
+ publicOnly: true,
+ });
+ const publicIds = publicFiles.map((file) => file.id);
+
+ let privateFiles = files.filter((file) => !publicIds.includes(file.id));
+
+ if (privateFiles.length) {
+ SearchManager.updateFile(privateFiles, "REMOVE");
+ }
}
return res.status(200).send({ decorator: "SERVER_DELETE_SLATE", error: false });
diff --git a/pages/api/slates/get-serialized.js b/pages/api/slates/get-serialized.js
index 14141517..80e98a80 100644
--- a/pages/api/slates/get-serialized.js
+++ b/pages/api/slates/get-serialized.js
@@ -5,41 +5,67 @@ import * as Strings from "~/common/strings";
export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
+ if (!id) {
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
+ }
+
+ const user = await Data.getUserById({
+ id,
+ });
+
+ if (!user) {
+ return res.status(404).send({
+ decorator: "SERVER_USER_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ if (user.error) {
+ return res.status(500).send({
+ decorator: "SERVER_USER_NOT_FOUND",
+ error: true,
+ });
+ }
+
let slate;
if (req.body.data.id) {
- slate = await Data.getSlateById({ id: req.body.data.id });
+ slate = await Data.getSlateById({ id: req.body.data.id, includeFiles: true, sanitize: true });
} else if (req.body.data.username && req.body.data.slatename) {
slate = await Data.getSlateByName({
username: req.body.data.username,
slatename: req.body.data.slatename,
+ includeFiles: true,
+ sanitize: true,
});
}
+
if (!slate || slate.error) {
return res.status(404).send({
- decorator: "SLATE_NOT_FOUND",
+ decorator: "SERVER_GET_SERIALIZED_SLATE_SLATE_NOT_FOUND",
error: true,
});
}
- slate = Serializers.slate(slate);
- if (!slate.data.public && slate.data.ownerId !== id) {
+ if (!slate.isPublic && slate.ownerId !== id) {
return res.status(403).send({
- decorator: "SLATE_PRIVATE_ACCESS_DENIED",
+ decorator: "SERVER_GET_SERIALIZED_SLATE_PRIVATE_ACCESS_DENIED",
error: true,
});
}
- let user = await Data.getUserById({ id: slate.data.ownerId });
- if (!user || user.error) {
+ let owner = await Data.getUserById({ id: slate.ownerId, sanitize: true });
+
+ if (!owner || owner.error) {
return res.status(200).send({
- decorator: "SLATE_OWNER_NOT_FOUND",
+ decorator: "SERVER_GET_SERIALIZED_SLATE_OWNER_NOT_FOUND",
data: slate,
});
}
- slate.user = Serializers.user(user);
+
+ slate.user = owner;
return res.status(200).send({
- decorator: "SERIALIZED_SLATE",
- data: slate,
+ decorator: "SERVER_GET_SERIALIZED_SLATE",
+ slate,
});
};
diff --git a/pages/api/slates/get.js b/pages/api/slates/get.js
index e3cfece8..848f1b7e 100644
--- a/pages/api/slates/get.js
+++ b/pages/api/slates/get.js
@@ -1,11 +1,12 @@
import * as Utilities from "~/node_common/utilities";
import * as Data from "~/node_common/data";
+import * as Serializers from "~/node_common/serializers";
import * as Strings from "~/common/strings";
export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
if (!id) {
- return res.status(500).send({ decorator: "SERVER_GET_SLATE", error: true });
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
}
const user = await Data.getUserById({
@@ -14,38 +15,38 @@ export default async (req, res) => {
if (!user) {
return res.status(404).send({
- decorator: "SERVER_GET_SLATE_USER_NOT_FOUND",
+ decorator: "SERVER_USER_NOT_FOUND",
error: true,
});
}
if (user.error) {
return res.status(500).send({
- decorator: "SERVER_GET_SLATE_USER_NOT_FOUND",
+ decorator: "SERVER_USER_NOT_FOUND",
error: true,
});
}
- if (Array.isArray(req.body.data.id)) {
- const responseMultiple = await Data.getSlatesByIds({ ids: req.body.data.id });
- if (!responseMultiple) {
- return res.status(404).send({ decorator: "SERVER_GET_SLATES_NOT_FOUND", error: true });
- }
- if (responseMultiple.error) {
- return res.status(500).send({ decorator: "SERVER_GET_SLATES_NOT_FOUND", error: true });
- }
+ const response = await Data.getSlateById({
+ id: req.body.data.id,
+ includeFiles: true,
+ sanitize: true,
+ });
- return res.status(200).send({ decorator: "SERVER_GET_SLATES", slate: responseMultiple });
- } else {
- const response = await Data.getSlateById({ id: req.body.data.id });
- if (!response) {
- return res.status(404).send({ decorator: "SERVER_GET_SLATE_NOT_FOUND", error: true });
- }
-
- if (response.error) {
- return res.status(500).send({ decorator: "SERVER_GET_SLATE_NOT_FOUND", error: true });
- }
-
- return res.status(200).send({ decorator: "SERVER_GET_SLATE", slate: response });
+ if (!response) {
+ return res.status(404).send({ decorator: "SERVER_GET_SLATE_NOT_FOUND", error: true });
}
+
+ if (response.error) {
+ return res.status(500).send({ decorator: "SERVER_GET_SLATE_NOT_FOUND", error: true });
+ }
+
+ if (!response.isPublic && response.ownerId !== id) {
+ return res.status(403).send({
+ decorator: "SERVER_GET_SLATE_PRIVATE_ACCESS_DENIED",
+ error: true,
+ });
+ }
+
+ return res.status(200).send({ decorator: "SERVER_GET_SLATE", slate: response });
};
diff --git a/pages/api/slates/remove.js b/pages/api/slates/remove-file.js
similarity index 57%
rename from pages/api/slates/remove.js
rename to pages/api/slates/remove-file.js
index 8ae4c834..182ffdd2 100644
--- a/pages/api/slates/remove.js
+++ b/pages/api/slates/remove-file.js
@@ -8,9 +8,7 @@ import * as SearchManager from "~/node_common/managers/search";
export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
if (!id) {
- return res
- .status(403)
- .send({ decorator: "SERVER_REMOVE_FROM_SLATE_USER_NOT_FOUND", error: true });
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
}
const user = await Data.getUserById({
@@ -19,19 +17,21 @@ export default async (req, res) => {
if (!user) {
return res.status(404).send({
- decorator: "SERVER_REMOVE_FROM_SLATE_USER_NOT_FOUND",
+ decorator: "SERVER_USER_NOT_FOUND",
error: true,
});
}
if (user.error) {
return res.status(500).send({
- decorator: "SERVER_REMOVE_FROM_SLATE_USER_NOT_FOUND",
+ decorator: "SERVER_USER_NOT_FOUND",
error: true,
});
}
- if (!req.body.data.ids || !req.body.data.ids.length) {
+ const fileIds = req.body.data.ids;
+
+ if (!fileIds?.length) {
return res.status(500).send({
decorator: "SERVER_REMOVE_FROM_SLATE_NO_ID_PROVIDED",
error: true,
@@ -54,41 +54,31 @@ export default async (req, res) => {
});
}
- const objects = slate.data.objects.filter((each) => {
- return !req.body.data.ids.includes(each.id);
- });
+ let response = await Data.deleteSlateFiles({ slateId: slate.id, ids: fileIds });
- const update = await Data.updateSlateById({
- id: slate.id,
- updated_at: new Date(),
- data: {
- ...slate.data,
- objects,
- },
- });
-
- if (!update) {
+ if (!response || response.error) {
return res.status(500).send({
- decorator: "SERVER_REMOVE_FROM_SLATE_ERROR",
+ decorator: "SERVER_REMOVE_FROM_SLATE_FAILED",
error: true,
});
}
- if (update.error) {
- return res.status(500).send({
- decorator: "SERVER_REMOVE_FROM_SLATE_ERROR",
- error: true,
- });
+ if (slate.isPublic) {
+ const publicFiles = await Data.getFilesByIds({ ids: fileIds, publicOnly: true });
+ const publicIds = publicFiles.map((file) => file.id);
+
+ let privateFiles = fileIds
+ .filter((id) => !publicIds.includes(id))
+ .map((id) => {
+ return { id };
+ });
+
+ if (privateFiles.length) {
+ SearchManager.updateFile(privateFiles, "REMOVE");
+ }
}
- let slates = await Data.getSlatesByUserId({ userId: id });
- if (slates) {
- ViewerManager.hydratePartialSlates(slates, id);
- }
-
- if (update.data.public) {
- SearchManager.updateSlate(update, "EDIT");
- }
+ ViewerManager.hydratePartial(id, { slates: true });
return res.status(200).send({
decorator: "SERVER_SLATE_REMOVE_FROM_SLATE",
diff --git a/pages/api/slates/update-layout.js b/pages/api/slates/update-layout.js
new file mode 100644
index 00000000..34bbc538
--- /dev/null
+++ b/pages/api/slates/update-layout.js
@@ -0,0 +1,47 @@
+import * as Utilities from "~/node_common/utilities";
+import * as Data from "~/node_common/data";
+import * as Strings from "~/common/strings";
+import * as ViewerManager from "~/node_common/managers/viewer";
+
+export default async (req, res) => {
+ if (!req.body.data) {
+ return res.status(500).send({
+ decorator: "SERVER_UPDATE_SLATE_LAYOUT_MUST_PROVIDE_DATA",
+ error: true,
+ });
+ }
+
+ const slate = await Data.getSlateById({ id: req.body.data.id });
+
+ if (!slate) {
+ return res.status(404).send({ decorator: "SERVER_UPDATE_SLATE_LAYOUT_NOT_FOUND", error: true });
+ }
+
+ if (slate.error) {
+ return res.status(500).send({ decorator: "SERVER_UPDATE_SLATE_LAYOUT_NOT_FOUND", error: true });
+ }
+
+ let update = await Data.updateSlateById({
+ id: slate.id,
+ data: {
+ ...slate.data,
+ layouts: req.body.data.layouts,
+ },
+ });
+
+ if (!update) {
+ return res.status(404).send({ decorator: "SERVER_UPDATE_SLATE_LAYOUT", error: true });
+ }
+
+ if (update.error) {
+ return res.status(500).send({ decorator: "SERVER_UPDATE_SLATE_LAYOUT", error: true });
+ }
+
+ const id = Utilities.getIdFromCookie(req);
+
+ if (id && slate.ownerId === id) {
+ ViewerManager.hydratePartial(id, { slates: true });
+ }
+
+ return res.status(200).send({ decorator: "SERVER_UPDATE_SLATE_LAYOUT", slate });
+};
diff --git a/pages/api/slates/update.js b/pages/api/slates/update.js
index 1ae6b911..7114f656 100644
--- a/pages/api/slates/update.js
+++ b/pages/api/slates/update.js
@@ -1,47 +1,31 @@
import * as Utilities from "~/node_common/utilities";
import * as Data from "~/node_common/data";
import * as Strings from "~/common/strings";
+import * as Validations from "~/common/validations";
+import * as Serializers from "~/node_common/serializers";
import * as ViewerManager from "~/node_common/managers/viewer";
import * as SearchManager from "~/node_common/managers/search";
export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
- let layoutOnly = req.body.data.layoutOnly && req.body.data.data.layouts;
+ if (!id) {
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
+ }
- let user;
+ let user = await Data.getUserById({ id });
- if (!layoutOnly) {
- if (!id) {
- return res.status(500).send({ decorator: "SERVER_FIND_USER_UPDATE_SLATE", error: true });
- }
-
- user = await Data.getUserById({
- id,
+ if (!user) {
+ return res.status(404).send({
+ decorator: "SERVER_USER_NOT_FOUND",
+ error: true,
});
-
- if (!user) {
- return res.status(404).send({
- decorator: "SERVER_FIND_USER_UPDATE_SLATE_USER_NOT_FOUND",
- error: true,
- });
- }
-
- if (user.error) {
- return res.status(500).send({
- decorator: "SERVER_FIND_USER_UPDATE_SLATE_USER_NOT_FOUND",
- error: true,
- });
- }
}
- const response = await Data.getSlateById({ id: req.body.data.id });
-
- if (!response) {
- return res.status(404).send({ decorator: "SERVER_UPDATE_SLATE_NOT_FOUND", error: true });
- }
-
- if (response.error) {
- return res.status(500).send({ decorator: "SERVER_UPDATE_SLATE_NOT_FOUND", error: true });
+ if (user.error) {
+ return res.status(500).send({
+ decorator: "SERVER_USER_NOT_FOUND",
+ error: true,
+ });
}
if (!req.body.data) {
@@ -51,72 +35,104 @@ export default async (req, res) => {
});
}
- if (!layoutOnly && req.body.data.data.name) {
+ let updates = req.body.data;
+
+ const slate = await Data.getSlateById({ id: updates.id, includeFiles: true });
+
+ if (!slate) {
+ return res.status(404).send({ decorator: "SERVER_UPDATE_SLATE_NOT_FOUND", error: true });
+ }
+
+ if (slate.error) {
+ return res.status(500).send({ decorator: "SERVER_UPDATE_SLATE_NOT_FOUND", error: true });
+ }
+
+ if (typeof updates.isPublic !== "undefined" && slate.isPublic !== updates.isPublic) {
+ let privacyResponse = await Data.updateSlatePrivacy({
+ id: slate.id,
+ isPublic: updates.isPublic,
+ });
+
+ if (!privacyResponse) {
+ return res
+ .status(404)
+ .send({ decorator: "SERVER_UPDATE_SLATE_UPDATE_PRIVACY_FAILED", error: true });
+ }
+
+ if (privacyResponse.error) {
+ return res
+ .status(500)
+ .send({ decorator: "SERVER_UPDATE_SLATE_UPDATE_PRIVACY_FAILED", error: true });
+ }
+
+ if (!updates.isPublic) {
+ //NOTE(martina): if any of the files in it are now private (because they are no longer in any public slates) remove them from search
+ const files = slate.objects;
+
+ const publicFiles = await Data.getFilesByIds({
+ ids: files.map((file) => file.id),
+ publicOnly: true,
+ });
+ const publicIds = publicFiles.map((file) => file.id);
+
+ let privateFiles = files.filter((file) => !publicIds.includes(file.id));
+
+ if (privateFiles.length) {
+ SearchManager.updateFile(privateFiles, "REMOVE");
+ }
+ } else {
+ //NOTE(martina): make sure all the now-public files are in search if they weren't already
+ const files = slate.objects;
+
+ SearchManager.updateFile(files, "ADD");
+ }
+ }
+
+ if (updates.data.name && updates.data.name !== slate.data.name) {
+ if (!Validations.slatename(slate.data.name)) {
+ return res.status(400).send({
+ decorator: "SERVER_UPDATE_SLATE_INVALID_NAME",
+ error: true,
+ });
+ }
+
const existingSlate = await Data.getSlateByName({
- slatename: req.body.data.data.name,
+ slatename: updates.data.name,
ownerId: user.id,
});
- if (existingSlate && existingSlate.id !== req.body.data.id) {
+
+ if (existingSlate) {
return res.status(500).send({
decorator: "SERVER_UPDATE_SLATE_NAME_TAKEN",
error: true,
});
+ } else {
+ updates.slatename = Strings.createSlug(updates.data.name);
}
}
- let isOwner = id && response.data.ownerId === id;
+ updates.updatedAt = new Date();
- let slate;
- if (!isOwner && req.body.data.data.layouts) {
- slate = await Data.updateSlateById({
- id: response.id,
- slatename: response.slatename,
- updated_at: response.updated_at,
- data: {
- ...response.data,
- layouts: req.body.data.data.layouts,
- },
- });
- } else if (isOwner) {
- slate = await Data.updateSlateById({
- id: response.id,
- slatename: req.body.data.data.name
- ? Strings.createSlug(req.body.data.data.name)
- : response.slatename,
- updated_at: layoutOnly || req.body.data.autoSave ? response.updated_at : new Date(),
- data: {
- ...response.data,
- ...req.body.data.data,
- },
- });
+ let response = await Data.updateSlateById(updates);
+
+ if (!response) {
+ return res.status(404).send({ decorator: "SERVER_UPDATE_SLATE_FAILED", error: true });
}
- if (!slate) {
- return res.status(404).send({ decorator: "SERVER_UPDATE_SLATE", error: true });
+ if (response.error) {
+ return res.status(500).send({ decorator: "SERVER_UPDATE_SLATE_FAILED", error: true });
+ }
+ console.log(response);
+
+ ViewerManager.hydratePartial(id, { slates: true });
+
+ if (slate.isPublic && !updates.isPublic) {
+ SearchManager.updateSlate(response, "REMOVE");
+ } else if (!slate.isPublic && updates.isPublic) {
+ SearchManager.updateSlate(response, "ADD");
+ } else {
+ SearchManager.updateSlate(response, "EDIT");
}
- if (slate.error) {
- return res.status(500).send({ decorator: "SERVER_UPDATE_SLATE", error: true });
- }
-
- if (isOwner) {
- let slates = await Data.getSlatesByUserId({ userId: id });
- if (slates) {
- ViewerManager.hydratePartialSlates(slates, id);
- }
- }
-
- if (!layoutOnly && !req.body.data.autoSave) {
- if (response.data.public !== slate.data.public) {
- if (slate.data.public) {
- SearchManager.updateSlate(slate, "ADD");
- } else {
- SearchManager.updateSlate(slate, "REMOVE");
- }
- } else if (slate.data.public) {
- SearchManager.updateSlate(slate, "EDIT");
- }
- }
-
- return res.status(200).send({ decorator: "SERVER_UPDATE_SLATE", slate });
+ return res.status(200).send({ decorator: "SERVER_UPDATE_SLATE", slate: response });
};
diff --git a/pages/api/subscribe.js b/pages/api/subscribe.js
index 70c9effc..ff49022e 100644
--- a/pages/api/subscribe.js
+++ b/pages/api/subscribe.js
@@ -8,7 +8,7 @@ import * as ViewerManager from "~/node_common/managers/viewer";
export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
if (!id) {
- return res.status(500).send({ decorator: "SERVER_SUBSCRIBE", error: true });
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
}
const user = await Data.getUserById({
@@ -16,11 +16,11 @@ export default async (req, res) => {
});
if (!user) {
- return res.status(404).send({ decorator: "SERVER_SUBSCRIBE_USER_NOT_FOUND", error: true });
+ return res.status(404).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
}
if (user.error) {
- return res.status(500).send({ decorator: "SERVER_SUBSCRIBE_USER_NOT_FOUND", error: true });
+ return res.status(500).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
}
if (!req.body.data || (!req.body.data.userId && !req.body.data.slateId)) {
@@ -77,40 +77,12 @@ export default async (req, res) => {
}
}
- const existingResponse = await Data.getSubscriptionById({
- subscriberUserId: user.id,
+ const existingResponse = await Data.getSubscription({
+ ownerId: user.id,
slateId: targetSlate ? targetSlate.id : null,
userId: targetUser ? targetUser.id : null,
});
- if (targetUser) {
- Monitor.subscribeUser({
- userId: user.id,
- data: {
- actorUserId: user.id,
- context: {
- username: user.username,
- targetUsername: targetUser.username,
- targetUserId: targetUser.id,
- },
- },
- });
- }
-
- if (targetSlate) {
- Monitor.subscribeSlate({
- slateId: targetSlate.id,
- data: {
- actorUserId: user.id,
- context: {
- slateId: targetSlate.id,
- slatename: targetSlate.slatename,
- username: user.username,
- },
- },
- });
- }
-
if (existingResponse && existingResponse.error) {
return res.status(500).send({
decorator: "SERVER_SUBSCRIBE_SUBSCRIPTION_CHECK_ERROR",
@@ -118,48 +90,61 @@ export default async (req, res) => {
});
}
+ let response;
+
// NOTE(jim): If it exists, we unsubscribe instead.
if (existingResponse) {
- const unsubscribeResponse = await Data.deleteSubscriptionById({
+ response = await Data.deleteSubscriptionById({
id: existingResponse.id,
});
- if (!unsubscribeResponse) {
- return res.status(404).send({ decorator: "SERVER_UNSUBSCRIBE_NOT_FOUND", error: true });
+ if (!response) {
+ return res.status(404).send({ decorator: "SERVER_UNSUBSCRIBE_FAILED", error: true });
}
- if (unsubscribeResponse.error) {
- return res.status(500).send({ decorator: "SERVER_UNSUBSCRIBE_ERROR", error: true });
+ if (response.error) {
+ return res.status(500).send({ decorator: "SERVER_UNSUBSCRIBE_FAILED", error: true });
+ }
+ } else {
+ response = await Data.createSubscription({
+ ownerId: user.id,
+ slateId: targetSlate ? targetSlate.id : null,
+ userId: targetUser ? targetUser.id : null,
+ });
+
+ if (!response) {
+ return res.status(404).send({ decorator: "SERVER_SUBSCRIBE_FAILED", error: true });
}
- ViewerManager.hydratePartialSubscriptions({ subscriptions: true }, user.id);
-
- return res.status(200).send({ decorator: "SERVER_UNSUBSCRIBE", data: unsubscribeResponse });
+ if (response.error) {
+ return res.status(500).send({ decorator: "SERVER_SUBSCRIBE_FAILED", error: true });
+ }
}
- const subscribeResponse = await Data.createSubscription({
- subscriberUserId: user.id,
- slateId: targetSlate ? targetSlate.id : null,
- userId: targetUser ? targetUser.id : null,
- });
+ if (targetUser) {
+ ViewerManager.hydratePartial(id, { following: true });
- if (!subscribeResponse) {
- return res.status(404).send({ decorator: "SERVER_SUBSCRIBE_NOT_FOUND", error: true });
+ if (!existingResponse) {
+ Monitor.subscribeUser({
+ user,
+ targetUser,
+ });
+ }
}
- if (subscribeResponse.error) {
- return res.status(500).send({ decorator: "SERVER_SUBSCRIBE_ERROR", error: true });
- }
+ if (targetSlate) {
+ ViewerManager.hydratePartial(id, { subscriptions: true });
- ViewerManager.hydratePartialSubscriptions({ subscriptions: true }, user.id);
+ if (!existingResponse) {
+ Monitor.subscribeSlate({
+ user,
+ targetSlate,
+ });
+ }
+ }
return res.status(200).send({
decorator: "SERVER_SUBSCRIBE",
- data: {
- ...subscribeResponse,
- owner: Serializers.user(user),
- slate: targetSlate ? Serializers.slate(targetSlate) : null,
- user: targetUser ? Serializers.user(targetUser) : null,
- },
+ data: response,
});
};
diff --git a/pages/api/support-message.js b/pages/api/support-message.js
index 1c488b52..502b8e39 100644
--- a/pages/api/support-message.js
+++ b/pages/api/support-message.js
@@ -6,7 +6,7 @@ import * as Support from "~/node_common/support";
export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
if (!id) {
- return res.status(500).send({ decorator: "SERVER_SUPPORT", error: true });
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
}
const user = await Data.getUserById({
@@ -14,11 +14,11 @@ export default async (req, res) => {
});
if (!user) {
- return res.status(404).send({ decorator: "SERVER_SUPPORT_USER_NOT_FOUND", error: true });
+ return res.status(404).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
}
if (user.error) {
- return res.status(500).send({ decorator: "SERVER_SUPPORT_USER_NOT_FOUND", error: true });
+ return res.status(500).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
}
if (!req.body.data) {
@@ -43,10 +43,7 @@ export default async (req, res) => {
}
if (!req.body.data.username) {
- return res.status(500).send({
- decorator: "SERVER_SUPPORT_NO_DATA_PROVIDED",
- error: true,
- });
+ req.body.data.username = user.username;
}
let status = await Support.sendSlackMessage(req.body.data);
diff --git a/pages/api/users/check-username.js b/pages/api/users/check-username.js
new file mode 100644
index 00000000..3a1ac47c
--- /dev/null
+++ b/pages/api/users/check-username.js
@@ -0,0 +1,20 @@
+import * as Environment from "~/node_common/environment";
+import * as Data from "~/node_common/data";
+import * as Utilities from "~/node_common/utilities";
+import * as Serializers from "~/node_common/serializers";
+
+export default async (req, res) => {
+ const user = await Data.getUserByUsername({
+ username: req.body.data.username.toLowerCase(),
+ });
+
+ if (!user) {
+ return res.status(200).send({ decorator: "SERVER_USER_NOT_FOUND" });
+ }
+
+ if (user.error) {
+ return res.status(500).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
+ }
+
+ return res.status(200).send({ decorator: "SERVER_CHECK_USERNAME", data: user });
+};
diff --git a/pages/api/users/check.js b/pages/api/users/check.js
deleted file mode 100644
index f239f604..00000000
--- a/pages/api/users/check.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import * as Environment from "~/node_common/environment";
-import * as Data from "~/node_common/data";
-import * as Utilities from "~/node_common/utilities";
-import * as Serializers from "~/node_common/serializers";
-
-import { Buckets, PrivateKey } from "@textile/hub";
-
-import JWT from "jsonwebtoken";
-
-const TEXTILE_KEY_INFO = {
- key: Environment.TEXTILE_HUB_KEY,
- secret: Environment.TEXTILE_HUB_SECRET,
-};
-
-export default async (req, res) => {
- const user = await Data.getUserByUsername({
- username: req.body.data.username,
- });
-
- if (!user) {
- return res.status(200).send({ decorator: "USER_NOT_FOUND" });
- }
-
- if (user.error) {
- return res.status(500).send({ decorator: "USER_NOT_FOUND", error: true });
- }
-
- return res
- .status(200)
- .send({ decorator: "USER_FOUND", data: Serializers.user(user) });
-};
diff --git a/pages/api/users/create.js b/pages/api/users/create.js
index 419d60b5..62189885 100644
--- a/pages/api/users/create.js
+++ b/pages/api/users/create.js
@@ -2,7 +2,6 @@ import * as Environment from "~/node_common/environment";
import * as Data from "~/node_common/data";
import * as Utilities from "~/node_common/utilities";
import * as SlateManager from "~/node_common/managers/slate";
-import * as LibraryManager from "~/node_common/managers/library";
import * as Monitor from "~/node_common/monitor";
import * as Validations from "~/common/validations";
import * as Strings from "~/common/strings";
@@ -13,27 +12,27 @@ import { PrivateKey } from "@textile/hub";
export default async (req, res) => {
if (!Strings.isEmpty(Environment.ALLOWED_HOST) && req.headers.host !== Environment.ALLOWED_HOST) {
- return res.status(403).send({ decorator: "YOU_ARE_NOT_ALLOWED", error: true });
+ return res.status(403).send({ decorator: "SERVER_CREATE_USER_NOT_ALLOWED", error: true });
}
if (Strings.isEmpty(req.body.data.accepted)) {
- return res.status(403).send({ decorator: "YOU_MUST_ACCEPT_TERMS", error: true });
+ return res.status(403).send({ decorator: "SERVER_CREATE_USER_ACCEPT_TERMS", error: true });
}
const existing = await Data.getUserByUsername({
- username: req.body.data.username,
+ username: req.body.data.username.toLowerCase(),
});
if (existing) {
- return res.status(403).send({ decorator: "SERVER_EXISTING_USER_ALREADY", error: true });
+ return res.status(403).send({ decorator: "SERVER_CREATE_USER_USERNAME_TAKEN", error: true });
}
if (!Validations.username(req.body.data.username)) {
- return res.status(500).send({ decorator: "SERVER_INVALID_USERNAME", error: true });
+ return res.status(500).send({ decorator: "SERVER_CREATE_USER_INVALID_USERNAME", error: true });
}
if (!Validations.password(req.body.data.password)) {
- return res.status(500).send({ decorator: "SERVER_INVALID_PASSWORD", error: true });
+ return res.status(500).send({ decorator: "SERVER_CREATE_USER_INVALID_PASSWORD", error: true });
}
const rounds = Number(Environment.LOCAL_PASSWORD_ROUNDS);
@@ -57,7 +56,9 @@ export default async (req, res) => {
});
if (!buckets) {
- return res.status(500).send({ decorator: "SERVER_BUCKET_INIT_FAILURE", error: true });
+ return res
+ .status(500)
+ .send({ decorator: "SERVER_CREATE_USER_BUCKET_INIT_FAILURE", error: true });
}
const photo = await SlateManager.getRandomSlateElementURL({
@@ -73,35 +74,28 @@ export default async (req, res) => {
data: {
photo,
body: "",
- settings_deals_auto_approve: false,
- allow_filecoin_directory_listing: false,
- allow_automatic_data_storage: true,
- allow_encrypted_data_storage: true,
+ settings: {
+ settings_deals_auto_approve: false,
+ allow_filecoin_directory_listing: false,
+ allow_automatic_data_storage: true,
+ allow_encrypted_data_storage: true,
+ },
tokens: { api },
- library: LibraryManager.init({ bucketName, readableName: "Data" }),
},
});
if (!user) {
- return res.status(404).send({ decorator: "SERVER_USER_CREATE_USER_NOT_FOUND", error: true });
+ return res.status(404).send({ decorator: "SERVER_CREATE_USER_FAILED", error: true });
}
if (user.error) {
- return res.status(500).send({ decorator: "SERVER_USER_CREATE_USER_NOT_FOUND", error: true });
+ return res.status(500).send({ decorator: "SERVER_CREATE_USER_FAILED", error: true });
}
- Monitor.createUser({
- userId: user.id,
- data: {
- actorUserId: user.id,
- context: {
- username: user.username,
- },
- },
- });
+ Monitor.createUser({ user });
return res.status(200).send({
- decorator: "SERVER_USER_CREATE",
+ decorator: "SERVER_CREATE_USER",
user: { username: user.username, id: user.id },
});
};
diff --git a/pages/api/users/delete.js b/pages/api/users/delete.js
index 9cc1f49a..960cfd6c 100644
--- a/pages/api/users/delete.js
+++ b/pages/api/users/delete.js
@@ -4,30 +4,35 @@ import * as Utilities from "~/node_common/utilities";
import * as Social from "~/node_common/social";
import * as SearchManager from "~/node_common/managers/search";
-import { Buckets, PrivateKey } from "@textile/hub";
-
-import JWT from "jsonwebtoken";
-
-const TEXTILE_KEY_INFO = {
- key: Environment.TEXTILE_HUB_KEY,
- secret: Environment.TEXTILE_HUB_SECRET,
-};
-
-export const deleteUser = async (user) => {
- // NOTE(jim): remove their slates from the live site cache.
- let slates = await Data.getSlatesByUserId({ userId: user.id, publicOnly: true });
- for (let slate of slates) {
- SearchManager.updateSlate(slate, "REMOVE");
+export default async (req, res) => {
+ const id = Utilities.getIdFromCookie(req);
+ if (!id) {
+ return res.status(500).send({ decorator: "SERVER_USER_DELETE", error: true });
}
- // NOTE(jim): revoke all of their API keys
- await Data.deleteAPIKeysForUserId({ userId: user.id });
+ const user = await Data.getUserById({ id, includeFiles: true });
+
+ if (!user) {
+ return res.status(404).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
+ }
+
+ if (user.error) {
+ return res.status(500).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
+ }
+
+ // NOTE(jim): remove their public slates and files from the search cache.
+ let slates = await Data.getSlatesByUserId({ ownerId: user.id, publicOnly: true });
+ SearchManager.updateSlate(slates, "REMOVE");
+
+ let files = await Data.getFilesByUserId({ id: user.id, publicOnly: true });
+ SearchManager.updateFile(files, "REMOVE");
// NOTE(jim): delete all of their public and private slates.
- await Data.deleteSlatesForUserId({ userId: user.id });
+ await Data.deleteSlatesByUserId({ ownerId: user.id });
+
+ // NOTE(martina): delete all of their public and private files.
+ await Data.deleteFilesByUserId({ ownerId: user.id });
- const i = await PrivateKey.fromString(user.data.tokens.api);
- const b = await Buckets.withKeyInfo(TEXTILE_KEY_INFO);
const defaultData = await Utilities.getBucketAPIFromUserToken({ user });
// NOTE(jim): delete every bucket
@@ -47,7 +52,6 @@ export const deleteUser = async (user) => {
});
}
- // NOTE(jim): remove user from live site cache.
SearchManager.updateUser(user, "REMOVE");
// NOTE(jim): remove orphan
@@ -55,33 +59,8 @@ export const deleteUser = async (user) => {
data: { token: user.data.tokens.api },
});
- // NOTE(jim): finally delete user by username (irreversible)
- const deleted = await Data.deleteUserByUsername({
- username: user.username,
- });
-
- return deleted;
-};
-
-export default async (req, res) => {
- const id = Utilities.getIdFromCookie(req);
- if (!id) {
- return res.status(500).send({ decorator: "SERVER_USER_DELETE", error: true });
- }
-
- const user = await Data.getUserById({
- id,
- });
-
- if (!user) {
- return res.status(404).send({ decorator: "SERVER_USER_DELETE_USER_NOT_FOUND", error: true });
- }
-
- if (user.error) {
- return res.status(500).send({ decorator: "SERVER_USER_DELETE_USER_NOT_FOUND", error: true });
- }
-
- const deleted = await deleteUser(user);
+ // NOTE(jim): finally delete user by id (irreversible)
+ const deleted = await Data.deleteUserById({ id: user.id });
if (!deleted || deleted.error) {
return res.status(500).send({ decorator: "SERVER_USER_DELETE", error: true });
diff --git a/pages/api/users/get-serialized.js b/pages/api/users/get-serialized.js
index 4b4e4a6e..d00a6b0d 100644
--- a/pages/api/users/get-serialized.js
+++ b/pages/api/users/get-serialized.js
@@ -1,83 +1,67 @@
import * as Data from "~/node_common/data";
-import * as Serializers from "~/node_common/serializers";
import * as Strings from "~/common/strings";
import * as Utilities from "~/node_common/utilities";
export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
- let user;
- if (req.body.data.id) {
- user = await Data.getUserById({ id: req.body.data.id });
- } else if (req.body.data.username) {
- user = await Data.getUserByUsername({ username: req.body.data.username });
+ if (!id) {
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
}
- if (!user || user.error) {
- return res.status(404).send({
- decorator: "USER_NOT_FOUND",
+ let user;
+
+ if (req.body.data.id) {
+ user = await Data.getUserById({
+ id: req.body.data.id,
+ includeFiles: true,
+ sanitize: true,
+ publicOnly: true,
+ });
+ } else if (req.body.data.username) {
+ user = await Data.getUserByUsername({
+ username: req.body.data.username,
+ includeFiles: true,
+ sanitize: true,
+ publicOnly: true,
+ });
+ } else {
+ return res.status(400).send({
+ decorator: "SERVER_GET_USER_NO_USER_PROVIDED",
error: true,
});
}
- let library = user.data.library;
- user = Serializers.user(user);
-
- let slates = await Data.getSlatesByUserId({
- userId: user.id,
- publicOnly: id === req.body.data.id ? false : true,
- });
- if (slates.error) {
- if (!user || user.error) {
- return res.status(404).send({
- decorator: "SLATES_NOT_FOUND",
- error: true,
- });
- }
- }
- let publicFileIds = [];
- user.slates = [];
- for (let slate of slates) {
- user.slates.push(Serializers.slate(slate));
- if (slate.data.public) {
- publicFileIds.push(...slate.data.objects.map((obj) => obj.id));
- }
- }
-
- if (library && library.length) {
- library[0].children = library[0].children.filter((file) => {
- return file.public || publicFileIds.includes(file.id);
+ if (!user) {
+ return res.status(404).send({
+ decorator: "SERVER_GET_USER_USER_NOT_FOUND",
+ error: true,
});
}
- user.library = library;
- // const subscriptions = await Data.getSubscriptionsByUserId({ userId: user.id });
- // const subscribers = await Data.getSubscribersByUserId({ userId: user.id });
+ if (user.error) {
+ return res.status(500).send({
+ decorator: "SERVER_GET_USER_USER_NOT_FOUND",
+ error: true,
+ });
+ }
- // let serializedUsersMap = { [user.id]: Serializers.user(user) };
- // let serializedSlatesMap = {};
+ let slates = await Data.getSlatesByUserId({
+ ownerId: user.id,
+ includeFiles: true,
+ publicOnly: true,
+ sanitize: true,
+ });
- // // NOTE(jim): The most expensive call first.
- // const r1 = await Serializers.doSubscriptions({
- // users: [],
- // slates: [],
- // subscriptions,
- // serializedUsersMap,
- // serializedSlatesMap,
- // });
-
- // user.subscriptions = r1.serializedSubscriptions;
-
- // const r2 = await Serializers.doSubscribers({
- // users: [],
- // slates: [],
- // subscribers,
- // serializedUsersMap: r1.serializedUsersMap,
- // serializedSlatesMap: r1.serializedSlatesMap,
- // });
-
- // user.subscribers = r2.serializedSubscribers;
+ if (slates && !slates.error) {
+ user.slates = slates;
+ } else {
+ return res.status(200).send({
+ decorator: "SERVER_GET_SERIALIZED_USER_MISSING_SERIALIZATION",
+ data: user,
+ });
+ }
return res.status(200).send({
- decorator: "SERIALIZED_USER",
+ decorator: "SERVER_GET_SERIALIZED_USER",
data: user,
});
};
diff --git a/pages/api/users/get-social.js b/pages/api/users/get-social.js
index 28a6deb0..51108b9d 100644
--- a/pages/api/users/get-social.js
+++ b/pages/api/users/get-social.js
@@ -2,52 +2,57 @@ import * as Data from "~/node_common/data";
import * as Serializers from "~/node_common/serializers";
export default async (req, res) => {
- if (!req.body.data.userId) {
- return res.status(404).send({ decorator: "SERVER_USER_SUBSCRIPTIONS_NOT_FOUND", error: true });
+ let id = req.body.data.id;
+ if (!id) {
+ return res.status(404).send({ decorator: "SERVER_USER_SOCIAL_NO_USER_ID", error: true });
}
- const subscriptions = await Data.getSubscriptionsByUserId({ userId: req.body.data.userId });
+ const subscriptions = await Data.getSubscriptionsByUserId({ ownerId: id });
if (!subscriptions) {
- return res.status(404).send({ decorator: "SERVER_USER_SUBSCRIPTIONS_NOT_FOUND", error: true });
+ return res
+ .status(404)
+ .send({ decorator: "SERVER_USER_SOCIAL_SUBSCRIPTIONS_NOT_FOUND", error: true });
}
if (subscriptions.error) {
- return res.status(500).send({ decorator: "SERVER_USER_SUBSCRIPTIONS_NOT_FOUND", error: true });
+ return res
+ .status(500)
+ .send({ decorator: "SERVER_USER_SOCIAL_SUBSCRIPTIONS_NOT_FOUND", error: true });
}
- const subscribers = await Data.getSubscribersByUserId({ userId: req.body.data.userId });
+ const following = await Data.getFollowingByUserId({ ownerId: id });
- if (!subscribers) {
- return res.status(404).send({ decorator: "SERVER_USER_SUBSCRIBERS_NOT_FOUND", error: true });
+ if (!following) {
+ return res
+ .status(404)
+ .send({ decorator: "SERVER_USER_SOCIAL_FOLLOWING_NOT_FOUND", error: true });
}
- if (subscribers.error) {
- return res.status(500).send({ decorator: "SERVER_USER_SUBSCRIBERS_NOT_FOUND", error: true });
+ if (following.error) {
+ return res
+ .status(500)
+ .send({ decorator: "SERVER_USER_SOCIAL_FOLLOWING_NOT_FOUND", error: true });
}
- let serializedUsersMap = { [req.body.data.userId]: req.body.data };
- let serializedSlatesMap = {};
+ const followers = await Data.getFollowersByUserId({ userId: id });
- const serializedSubscriptions = await Serializers.doSubscriptions({
- users: [],
- slates: [],
- subscriptions,
- serializedUsersMap,
- serializedSlatesMap,
- });
+ if (!followers) {
+ return res
+ .status(404)
+ .send({ decorator: "SERVER_USER_SOCIAL_FOLLOWERS_NOT_FOUND", error: true });
+ }
- const serializedSubscribers = await Serializers.doSubscribers({
- users: [],
- slates: [],
- subscribers,
- serializedUsersMap: serializedSubscriptions.serializedUsersMap,
- serializedSlatesMap: serializedSubscriptions.serializedSlatesMap,
- });
+ if (followers.error) {
+ return res
+ .status(500)
+ .send({ decorator: "SERVER_USER_SOCIAL_FOLLOWERS_NOT_FOUND", error: true });
+ }
return res.status(200).send({
decorator: "SERVER_USER_SOCIAL",
- subscriptions: serializedSubscriptions.serializedSubscriptions,
- subscribers: serializedSubscribers.serializedSubscribers,
+ following,
+ followers,
+ subscriptions,
});
};
diff --git a/pages/api/users/get.js b/pages/api/users/get.js
index 24b65763..b5af1a72 100644
--- a/pages/api/users/get.js
+++ b/pages/api/users/get.js
@@ -4,22 +4,44 @@ import * as Strings from "~/common/strings";
export default async (req, res) => {
let user;
+
if (req.body.data.id) {
- user = await Data.getUserById({ id: req.body.data.id });
+ user = await Data.getUserById({
+ id: req.body.data.id,
+ sanitize: true,
+ includeFiles: true,
+ publicOnly: true,
+ });
} else if (req.body.data.username) {
- user = await Data.getUserByUsername({ username: req.body.data.username });
- }
- if (!user || user.error) {
- return res.status(404).send({
- decorator: "USER_NOT_FOUND",
+ user = await Data.getUserByUsername({
+ username: req.body.data.username.toLowerCase(),
+ includeFiles: true,
+ sanitize: true,
+ publicOnly: true,
+ });
+ } else {
+ return res.status(400).send({
+ decorator: "SERVER_GET_USER_NO_USER_PROVIDED",
error: true,
});
}
- user = Serializers.user(user);
+ if (!user) {
+ return res.status(404).send({
+ decorator: "SERVER_GET_USER_USER_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ if (user.error) {
+ return res.status(500).send({
+ decorator: "SERVER_GET_USER_USER_NOT_FOUND",
+ error: true,
+ });
+ }
return res.status(200).send({
- decorator: "GET_USER",
+ decorator: "SERVER_GET_USER",
data: user,
});
};
diff --git a/pages/api/users/status-update.js b/pages/api/users/status-update.js
index ded95eb8..e7954f5e 100644
--- a/pages/api/users/status-update.js
+++ b/pages/api/users/status-update.js
@@ -8,7 +8,7 @@ import * as ViewerManager from "~/node_common/managers/viewer";
export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
if (!id) {
- return res.status(500).send({ decorator: "SERVER_STATUS_UPDATE", error: true });
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
}
const user = await Data.getUserById({
@@ -17,40 +17,40 @@ export default async (req, res) => {
if (!user) {
return res.status(404).send({
- decorator: "SERVER_STATUS_UPDATE_USER_NOT_FOUND",
+ decorator: "SERVER_USER_NOT_FOUND",
error: true,
});
}
if (user.error) {
return res.status(500).send({
- decorator: "SERVER_STATUS_UPDATE_USER_NOT_FOUND",
+ decorator: "SERVER_USER_NOT_FOUND",
error: true,
});
}
let updateResponse;
- if (req.body.data && req.body.data.onboarding && req.body.data.onboarding.length) {
+ if (req.body.data?.onboarding) {
let onboarding = user.data.onboarding;
if (!onboarding) {
onboarding = {};
}
- for (let item of req.body.data.onboarding) {
- onboarding[item] = true;
+ for (let key of req.body.data.onboarding) {
+ onboarding[key] = true;
}
updateResponse = await Data.updateUserById({
id: user.id,
- data: { ...user.data, onboarding },
+ data: { onboarding },
});
if (!updateResponse || updateResponse.error) {
- return res.status(404).send({
- decorator: "SERVER_STATUS_UPDATE_USER_NOT_FOUND",
+ return res.status(500).send({
+ decorator: "SERVER_STATUS_UPDATE_FAILED",
error: true,
});
}
- } else if (req.body.data && req.body.data.status) {
+ } else if (req.body.data?.status) {
let status = user.data.status;
if (!status) {
status = {};
@@ -61,17 +61,15 @@ export default async (req, res) => {
updateResponse = await Data.updateUserById({
id: user.id,
- data: { ...user.data, status },
+ data: { status },
});
if (!updateResponse || updateResponse.error) {
return res.status(404).send({
- decorator: "SERVER_STATUS_UPDATE_USER_NOT_FOUND",
+ decorator: "SERVER_STATUS_UPDATE_FAILED",
error: true,
});
}
-
- ViewerManager.hydratePartialStatus(status, user.id);
} else {
return res.status(500).send({
decorator: "SERVER_STATUS_UPDATE_MUST_PROVIDE_UPDATE",
@@ -79,6 +77,8 @@ export default async (req, res) => {
});
}
+ ViewerManager.hydratePartial(id, { viewer: true });
+
return res.status(200).send({
decorator: "SERVER_STATUS_UPDATE",
data: updateResponse,
diff --git a/pages/api/users/trust-delete.js b/pages/api/users/trust-delete.js
deleted file mode 100644
index c763c6b0..00000000
--- a/pages/api/users/trust-delete.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import * as Environment from "~/node_common/environment";
-import * as Data from "~/node_common/data";
-import * as Utilities from "~/node_common/utilities";
-import * as Validations from "~/common/validations";
-import * as ViewerManager from "~/node_common/managers/viewer";
-
-export default async (req, res) => {
- const id = Utilities.getIdFromCookie(req);
- if (!id) {
- return res.status(500).send({ decorator: "SERVER_TRUST_DELETE", error: true });
- }
-
- const user = await Data.getUserById({
- id,
- });
-
- if (!user) {
- return res.status(404).send({
- decorator: "SERVER_TRUST_DELETE_USER_NOT_FOUND",
- error: true,
- });
- }
-
- if (user.error) {
- return res.status(500).send({
- decorator: "SERVER_TRUST_DELETE_USER_NOT_FOUND",
- error: true,
- });
- }
-
- if (!req.body.data) {
- return res.status(500).send({
- decorator: "SERVER_TRUST_DELETE_MUST_PROVIDE_ID",
- error: true,
- });
- }
-
- const response = await Data.deleteTrustedRelationshipById({
- id: req.body.data.id,
- });
-
- ViewerManager.hydratePartialSubscriptions({ trusted: true, pendingTrusted: true }, id);
-
- return res.status(200).send({ decorator: "SERVER_TRUST_UPDATE", data: response });
-};
diff --git a/pages/api/users/trust-update.js b/pages/api/users/trust-update.js
deleted file mode 100644
index c6adfc3c..00000000
--- a/pages/api/users/trust-update.js
+++ /dev/null
@@ -1,114 +0,0 @@
-import * as Environment from "~/node_common/environment";
-import * as Data from "~/node_common/data";
-import * as Utilities from "~/node_common/utilities";
-import * as Serializers from "~/node_common/serializers";
-import * as Validations from "~/common/validations";
-import * as ViewerManager from "~/node_common/managers/viewer";
-import * as Monitor from "~/node_common/monitor";
-
-export default async (req, res) => {
- const id = Utilities.getIdFromCookie(req);
- if (!id) {
- return res.status(500).send({ decorator: "SERVER_TRUST_UPDATE", error: true });
- }
-
- const user = await Data.getUserById({
- id,
- });
-
- if (!user) {
- return res.status(404).send({
- decorator: "SERVER_TRUST_UPDATE_USER_NOT_FOUND",
- error: true,
- });
- }
-
- if (user.error) {
- return res.status(500).send({
- decorator: "SERVER_TRUST_UPDATE_USER_NOT_FOUND",
- error: true,
- });
- }
-
- if (!req.body.data || !req.body.data.userId) {
- return res.status(500).send({
- decorator: "SERVER_TRUST_UPDATE_MUST_PROVIDE_SOMEONE_TO_TRUST",
- error: true,
- });
- }
-
- if (user.id === req.body.data.userId) {
- return res.status(500).send({
- decorator: "SERVER_TRUST_UPDATE_CAN_NOT_TRUST_YOURSELF",
- error: true,
- });
- }
-
- const targetUser = await Data.getUserById({
- id: req.body.data.userId,
- });
-
- if (!targetUser) {
- return res.status(404).send({
- decorator: "SERVER_TRUST_UPDATE_TARGET_USER_NOT_FOUND",
- error: true,
- });
- }
-
- if (targetUser.error) {
- return res.status(500).send({
- decorator: "SERVER_TRUST_UPDATE_TARGET_USER_NOT_FOUND",
- error: true,
- });
- }
-
- const existingResponse = await Data.getTrustedRelationshipByUserIds({
- ownerUserId: targetUser.id,
- targetUserId: user.id,
- });
-
- if (!existingResponse) {
- return res.status(404).send({
- decorator: "SERVER_TRUST_UPDATE_CHECK_ERROR",
- error: true,
- });
- }
-
- if (existingResponse.error) {
- return res.status(500).send({
- decorator: "SERVER_TRUST_UPDATE_CHECK_ERROR",
- error: true,
- });
- }
-
- const updateResponse = await Data.updateTrustedRelationshipById({
- id: existingResponse.id,
- data: { ...existingResponse.data, verified: true },
- });
-
- // NOTE(jim):
- // , ACCEPTED YOUR REQUEST.
- Monitor.verifyPeer({
- userId: targetUser.id,
- data: {
- actorUserId: user.id,
- context: {
- username: user.username,
- targetUsername: targetUser.username,
- targetUserId: targetUser.id,
- },
- },
- });
-
- ViewerManager.hydratePartialSubscriptions({ trusted: true, pendingTrusted: true }, id);
-
- return res.status(200).send({
- decorator: "SERVER_TRUST_UPDATE",
- data: {
- type: "TRUSTED_RELATIONSHIP",
- ...updateResponse,
- owner: Serializers.user(targetUser),
- user: Serializers.user(user),
- },
- });
-};
diff --git a/pages/api/users/trust.js b/pages/api/users/trust.js
deleted file mode 100644
index 69d336bc..00000000
--- a/pages/api/users/trust.js
+++ /dev/null
@@ -1,158 +0,0 @@
-import * as Environment from "~/node_common/environment";
-import * as Data from "~/node_common/data";
-import * as Utilities from "~/node_common/utilities";
-import * as Serializers from "~/node_common/serializers";
-import * as Validations from "~/common/validations";
-import * as ViewerManager from "~/node_common/managers/viewer";
-import * as Monitor from "~/node_common/monitor";
-
-export default async (req, res) => {
- const id = Utilities.getIdFromCookie(req);
- if (!id) {
- return res.status(500).send({ decorator: "SERVER_TRUST", error: true });
- }
-
- const user = await Data.getUserById({
- id,
- });
-
- if (!user) {
- return res.status(404).send({
- decorator: "SERVER_TRUSTED_RELATIONSHIP_USER_NOT_FOUND",
- error: true,
- });
- }
-
- if (user.error) {
- return res.status(500).send({
- decorator: "SERVER_TRUSTED_RELATIONSHIP_USER_NOT_FOUND",
- error: true,
- });
- }
-
- if (!req.body.data || !req.body.data.userId) {
- return res.status(500).send({
- decorator: "SERVER_TRUSTED_RELATIONSHIP_MUST_PROVIDE_SOMEONE_TO_TRUST",
- error: true,
- });
- }
-
- if (user.id === req.body.data.userId) {
- return res.status(500).send({
- decorator: "SERVER_TRUSTED_RELATIONSHIP_CAN_NOT_TRUST_YOURSELF",
- error: true,
- });
- }
-
- const targetUser = await Data.getUserById({
- id: req.body.data.userId,
- });
-
- if (!targetUser) {
- return res.status(404).send({
- decorator: "SERVER_TRUSTED_RELATIONSHIP_TARGET_USER_NOT_FOUND",
- error: true,
- });
- }
-
- if (targetUser.error) {
- return res.status(500).send({
- decorator: "SERVER_TRUSTED_RELATIONSHIP_TARGET_USER_NOT_FOUND",
- error: true,
- });
- }
-
- let existingResponse = await Data.getTrustedRelationshipByUserIds({
- ownerUserId: user.id,
- targetUserId: targetUser.id,
- });
-
- if (existingResponse && existingResponse.error) {
- return res.status(500).send({
- decorator: "SERVER_TRUSTED_RELATIONSHIP_CHECK_ERROR",
- error: true,
- });
- }
-
- let invertedResponse = await Data.getTrustedRelationshipByUserIds({
- targetUserId: user.id,
- ownerUserId: targetUser.id,
- });
-
- if (invertedResponse) {
- return res.status(500).send({
- decorator: "SERVER_TRUSTED_RELATIONSHIP_INVERTED_CHECK_ERROR",
- error: true,
- });
- }
-
- // NOTE(jim)
- // Treat trust as an API method you can call again to remove a trusted relationship.
- if (existingResponse) {
- const deleteRelationshipResponse = await Data.deleteTrustedRelationshipById({
- id: existingResponse.id,
- });
-
- if (!deleteRelationshipResponse) {
- return res.status(404).send({
- decorator: "SERVER_DELETE_TRUSTED_RELATIONSHIP_NOT_FOUND",
- error: true,
- });
- }
-
- if (deleteRelationshipResponse.error) {
- return res.status(500).send({
- decorator: "SERVER_DELETE_TRUSTED_RELATIONSHIP_ERROR",
- error: true,
- });
- }
-
- ViewerManager.hydratePartialSubscriptions({ trusted: true, pendingTrusted: true }, id);
-
- return res.status(200).send({
- decorator: "SERVER_DELETE_TRUSTED_RELATIONSHIP",
- data: deleteRelationshipResponse,
- });
- }
-
- const trustResponse = await Data.createTrustedRelationship({
- ownerUserId: user.id,
- targetUserId: targetUser.id,
- });
-
- if (!trustResponse) {
- return res.status(404).send({
- decorator: "SERVER_TRUSTED_RELATIONSHIP_NOT_FOUND",
- error: true,
- });
- }
-
- if (trustResponse.error) {
- return res.status(500).send({ decorator: "SERVER_TRUSTED_RELATIONSHIP_ERROR", error: true });
- }
-
- // NOTE(jim):
- // , WANTS TO BE YOUR PEER.
- Monitor.requestPeer({
- userId: targetUser.id,
- data: {
- actorUserId: user.id,
- context: {
- username: user.username,
- targetUsername: targetUser.username,
- targetUserId: targetUser.id,
- },
- },
- });
-
- ViewerManager.hydratePartialSubscriptions({ trusted: true, pendingTrusted: true }, id);
-
- return res.status(200).send({
- decorator: "SERVER_TRUSTED_RELATIONSHIP",
- data: {
- ...trustResponse,
- owner: Serializers.user(user),
- user: Serializers.user(targetUser),
- },
- });
-};
diff --git a/pages/api/users/update.js b/pages/api/users/update.js
index 87f8d567..ff35ad20 100644
--- a/pages/api/users/update.js
+++ b/pages/api/users/update.js
@@ -1,6 +1,7 @@
import * as Environment from "~/node_common/environment";
import * as Data from "~/node_common/data";
import * as Utilities from "~/node_common/utilities";
+import * as Serializers from "~/node_common/serializers";
import * as Validations from "~/common/validations";
import * as Social from "~/node_common/social";
import * as ViewerManager from "~/node_common/managers/viewer";
@@ -11,7 +12,7 @@ import BCrypt from "bcrypt";
export default async (req, res) => {
const id = Utilities.getIdFromCookie(req);
if (!id) {
- return res.status(500).send({ decorator: "SERVER_USER_UPDATE", error: true });
+ return res.status(401).send({ decorator: "SERVER_NOT_AUTHENTICATED", error: true });
}
const user = await Data.getUserById({
@@ -19,20 +20,31 @@ export default async (req, res) => {
});
if (!user) {
- return res.status(404).send({ decorator: "SERVER_USER_UPDATE_USER_NOT_FOUND", error: true });
+ return res.status(404).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
}
if (user.error) {
- return res.status(500).send({ decorator: "SERVER_USER_UPDATE_USER_NOT_FOUND", error: true });
+ return res.status(500).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
}
- if (req.body.data.username) {
+ let updates = req.body.data;
+
+ if (updates.username && updates.username !== user.username) {
+ if (!Validations.username(req.body.data.username)) {
+ return res.status(400).send({
+ decorator: "SERVER_USER_UPDATE_INVALID_USERNAME",
+ error: true,
+ });
+ }
+
const existing = await Data.getUserByUsername({
username: req.body.data.username.toLowerCase(),
});
if (existing && existing.id !== id) {
- return res.status(500).send({ decorator: "SERVER_USERNAME_IS_TAKEN", error: true });
+ return res
+ .status(500)
+ .send({ decorator: "SERVER_USER_UPDATE_USERNAME_IS_TAKEN", error: true });
}
}
@@ -53,7 +65,7 @@ export default async (req, res) => {
functionName: `Utilities.getBucketAPIFromUserToken`,
});
- return res.status(500).send({ decorator: "SERVER_FAILED_TO_GET_BUCKET", error: true });
+ return res.status(500).send({ decorator: "SERVER_NO_BUCKET_DATA", error: true });
}
try {
@@ -71,38 +83,30 @@ export default async (req, res) => {
functionName: `b.buckets.setDefaultArchiveConfig`,
});
- return res.status(500).send({ decorator: "SERVER_DEFAULT_ARCHIVE_CONFIG", error: true });
+ return res
+ .status(500)
+ .send({ decorator: "SERVER_USER_UPDATE_DEFAULT_ARCHIVE_CONFIG", error: true });
}
}
- let unsafeResponse;
- if (req.body.data.password) {
+ if (req.body.data.type === "CHANGE_PASSWORD" && req.body.data.password) {
if (!Validations.password(req.body.data.password)) {
- return res.status(500).send({ decorator: "SERVER_INVALID_PASSWORD", error: true });
+ return res
+ .status(500)
+ .send({ decorator: "SERVER_USER_UPDATE_INVALID_PASSWORD", error: true });
}
const rounds = Number(Environment.LOCAL_PASSWORD_ROUNDS);
const salt = await BCrypt.genSalt(rounds);
const hash = await Utilities.encryptPassword(req.body.data.password, salt);
- unsafeResponse = await Data.updateUserById({
- id: user.id,
- salt,
- password: hash,
- username: req.body.data.username ? req.body.data.username.toLowerCase() : user.username,
- data: req.body.data.data ? { ...user.data, ...req.body.data.data } : user.data,
- });
- } else {
- unsafeResponse = await Data.updateUserById({
- id: user.id,
- username: req.body.data.username ? req.body.data.username.toLowerCase() : user.username,
- data: req.body.data.data ? { ...user.data, ...req.body.data.data } : user.data,
- });
+ updates.salt = salt;
+ updates.password = hash;
}
- if (unsafeResponse && !unsafeResponse.error) {
- ViewerManager.hydratePartialViewer(unsafeResponse);
+ let unsafeResponse = await Data.updateUserById({ id, ...updates });
+ if (unsafeResponse && !unsafeResponse.error) {
if (
user.username !== unsafeResponse.username ||
user.data.name !== unsafeResponse.data.name ||
@@ -112,5 +116,7 @@ export default async (req, res) => {
}
}
+ ViewerManager.hydratePartial(id, { viewer: true });
+
return res.status(200).send({ decorator: "SERVER_USER_UPDATE" });
};
diff --git a/pages/api/v1/deals.js b/pages/api/v1/deals.js
deleted file mode 100644
index f4c60253..00000000
--- a/pages/api/v1/deals.js
+++ /dev/null
@@ -1,64 +0,0 @@
-import * as Utilities from "~/node_common/utilities";
-import * as Data from "~/node_common/data";
-import * as Strings from "~/common/strings";
-import * as Filecoin from "~/common/filecoin";
-import * as Powergate from "~/node_common/powergate";
-
-export default async (req, res) => {
- const response = await Data.getAllDeals();
-
- let totals = {
- size: 0,
- deals: 0,
- cost: 0,
- };
-
- let slingshot = {
- root: "t3xhj6odc2cjj3z6kmxqugjjai2unacme65gnwigse4xx6jcpmfmi6jg6miqintibacluxi4ydlmolfpruznba",
- total: 0,
- addresses: [],
- };
-
- response.forEach((each) => {
- totals.deals += 1;
- totals.size += each.data.size;
- totals.cost += each.data.totalCostAttoFIL;
-
- if (!slingshot.addresses.includes(each.data.addr)) {
- slingshot.total += 1;
- slingshot.addresses.push(each.data.addr);
- }
- });
-
- totals.costFormatted = Filecoin.formatAsFilecoinConversion(totals.cost);
- totals.sizeFormatted = Strings.bytesToSize(totals.size);
- totals.averages = {
- costPerDealFIL: Filecoin.formatAsFilecoinConversion(totals.cost / totals.deals),
- costPerDealAttoFIL: totals.cost / totals.deals,
- sizePerDealBytes: totals.size / totals.deals,
- sizePerDealBytesFormatted: Strings.bytesToSize(totals.size / totals.deals),
- costPerByteAttoFIL: totals.cost / totals.size,
- costPerByteFIL: Filecoin.formatAsFilecoinConversion(totals.cost / totals.size),
- costPerGBFIL: Filecoin.formatAsFilecoinConversion((totals.cost / totals.size) * 1073741824),
- };
-
- if (!response) {
- return res.status(500).send({
- decorator: "V1_GET_ALL_DEALS_ERROR",
- error: true,
- });
- }
-
- if (response.error) {
- return res.status(500).send({
- decorator: "V1_GET_ALL_DEALS_ERROR",
- error: true,
- });
- }
-
- return res
- .status(200)
- .send(
- JSON.stringify({ decorator: "V1_GET_ALL_DEALS", totals, slingshot, deals: response }, null, 4)
- );
-};
diff --git a/pages/api/v1/get-slate-objects.js b/pages/api/v1/get-slate-objects.js
deleted file mode 100644
index 288af3d9..00000000
--- a/pages/api/v1/get-slate-objects.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import * as Data from "~/node_common/data";
-import * as Strings from "~/common/strings";
-
-export default async (req, res) => {
- // TODO(martina): Get rid of URL after the CID property is available on a
- // Slate object.
- const response = await Data.getSlateObjectsByCID({
- url: `https://slate.textile.io/ipfs/${req.params.cid}`,
- cid: req.params.cid,
- });
-
- return res.status(200).json({ decorator: "V1_GET_SLATE_OBJECTS", data: response });
-};
diff --git a/pages/api/v1/get-slate.js b/pages/api/v1/get-slate.js
index 54f49e5e..5fc5a3a6 100644
--- a/pages/api/v1/get-slate.js
+++ b/pages/api/v1/get-slate.js
@@ -32,44 +32,24 @@ export default async (req, res) => {
}
const user = await Data.getUserById({
- id: key.owner_id,
+ id: key.ownerId,
});
if (!user) {
- return res
- .status(404)
- .send({ decorator: "V1_GET_SLATE_USER_NOT_FOUND", error: true });
+ return res.status(404).send({ decorator: "V1_GET_SLATE_USER_NOT_FOUND", error: true });
}
if (user.error) {
- return res
- .status(500)
- .send({ decorator: "V1_GET_SLATE_USER_NOT_FOUND", error: true });
+ return res.status(500).send({ decorator: "V1_GET_SLATE_USER_NOT_FOUND", error: true });
}
let slateId = req.body.data ? req.body.data.id : null;
- let slate;
if (Strings.isEmpty(slateId)) {
- const slates = await Data.getSlatesByUserId({ userId: user.id });
- if (!slates) {
- return res
- .status(404)
- .send({ decorator: "V1_GET_SLATE_SLATE_NOT_FOUND", error: true });
- }
-
- if (slates.error || !slates.length) {
- return res
- .status(500)
- .send({ decorator: "V1_GET_SLATE_SLATE_NOT_FOUND", error: true });
- }
-
- return res
- .status(200)
- .send({ decorator: "V1_GET_SLATE_MOST_RECENT", slate: slates[0] });
+ return res.status(400).send({ decorator: "V1_GET_SLATE_NO_ID_PROVIDED", error: true });
}
- slate = await Data.getSlateById({ id: slateId });
+ let slate = await Data.getSlateById({ id: slateId, includeFiles: true, sanitize: true });
if (!slate) {
return res.status(404).send({
@@ -85,5 +65,38 @@ export default async (req, res) => {
});
}
- return res.status(200).send({ decorator: "V1_GET_SLATE", slate });
+ if (!slate.isPublic) {
+ return res.status(400).send({ decorator: "V1_GET_SLATE_NOT_PUBLIC", error: true });
+ }
+
+ //NOTE(martina): convert the new database structure to the old structure
+ let reformattedObjects = slate.objects.map((file) => {
+ return {
+ id: file.id,
+ name: file.filename,
+ title: file.data.name,
+ ownerId: file.ownerId,
+ body: file.data.body,
+ author: file.data.author,
+ source: file.data.source,
+ url: Strings.getURLfromCID(file.cid),
+ };
+ });
+
+ let reformattedSlate = {
+ id: slate.id,
+ updated_at: slate.updatedAt,
+ created_at: slate.createdAt,
+ published_at: null,
+ slatename: slate.slatename,
+ data: {
+ name: slate.data.name,
+ public: slate.isPublic,
+ objects: reformattedObjects,
+ ownerId: slate.ownerId,
+ layouts: slate.data.layouts,
+ },
+ };
+
+ return res.status(200).send({ decorator: "V1_GET_SLATE", slate: reformattedSlate });
};
diff --git a/pages/api/v1/get.js b/pages/api/v1/get.js
index 05a61d83..0b3e4b38 100644
--- a/pages/api/v1/get.js
+++ b/pages/api/v1/get.js
@@ -32,7 +32,7 @@ export default async (req, res) => {
}
let user = await Data.getUserById({
- id: key.owner_id,
+ id: key.ownerId,
});
if (!user) {
@@ -43,14 +43,20 @@ export default async (req, res) => {
return res.status(500).send({ decorator: "V1_GET_SLATE_USER_NOT_FOUND", error: true });
}
- let slates = await Data.getSlatesByUserId({
- userId: user.id,
- publicOnly: req.body.data && req.body.data.private ? false : true,
- });
+ let reformattedUser = {
+ username: user.username,
+ data: {
+ name: user.data.name,
+ photo: user.data.photo,
+ body: user.data.body,
+ },
+ };
- slates = slates.map((each) => {
- each.data.url = `https://slate.host/${user.username}/${each.slatename}`;
- return each;
+ let slates = await Data.getSlatesByUserId({
+ ownerId: user.id,
+ sanitize: true,
+ includeFiles: true,
+ publicOnly: req.body.data && req.body.data.private ? false : true,
});
if (!slates) {
@@ -67,16 +73,38 @@ export default async (req, res) => {
});
}
- const { name, photo } = user.data;
- const username = user.username;
+ let reformattedSlates = slates.map((slate) => {
+ let reformattedObjects = slate.objects.map((file) => {
+ return {
+ id: file.id,
+ name: file.filename,
+ title: file.data.name,
+ ownerId: file.ownerId,
+ body: file.data.body,
+ author: file.data.author,
+ source: file.data.source,
+ url: Strings.getURLfromCID(file.cid),
+ };
+ });
- user = {
- username: username,
- data: {
- name: name,
- photo: photo,
- },
- };
+ return {
+ id: slate.id,
+ updated_at: slate.updatedAt,
+ created_at: slate.createdAt,
+ published_at: null,
+ slatename: slate.slatename,
+ url: `https://slate.host/${user.username}/${each.slatename}`,
+ data: {
+ name: slate.data.name,
+ public: slate.isPublic,
+ objects: reformattedObjects,
+ ownerId: slate.ownerId,
+ layouts: slate.data.layouts,
+ },
+ };
+ });
- return res.status(200).send({ decorator: "V1_GET", slates, user });
+ return res
+ .status(200)
+ .send({ decorator: "V1_GET", slates: reformattedSlates, user: reformattedUser });
};
diff --git a/pages/api/v1/stats.js b/pages/api/v1/stats.js
deleted file mode 100644
index 048c1158..00000000
--- a/pages/api/v1/stats.js
+++ /dev/null
@@ -1,76 +0,0 @@
-import * as Data from "~/node_common/data";
-import * as Strings from "~/common/strings";
-
-export default async (req, res) => {
- const response = await Data.getOrCreateGlobalStats(new Date(), async () => {
- const users = await Data.getEveryUser(false);
- const slates = await Data.getEverySlate(false);
- let stats = await Data.getAllStats();
- const activity = await Data.getAllActivity();
-
- let userCount = 0;
- let slateCount = 0;
- let slateObjectCount = 0;
- let averageNewUsersDaily = 0;
- let averageNewSlatesDaily = 0;
- let averageNewObjectsDaily = 0;
- let bytes = 0;
- let userMap = {};
- let slateMap = {};
-
- users.forEach((user) => {
- userCount = userCount + 1;
-
- let userBytes = 0;
- user.data.library[0].children.forEach((each) => {
- userBytes = each.size + userBytes;
- bytes = each.size + bytes;
- });
-
- userMap[user.id] = {
- userBytes,
- username: user.username,
- userBytesFormatted: Strings.bytesToSize(userBytes),
- };
- });
-
- slates.forEach((slate) => {
- slateCount = slateCount + 1;
- slateObjectCount = slateObjectCount + slate.data.objects.length;
-
- slateMap[slate.id] = {
- count: slate.data.objects.length,
- slatename: slate.slatename,
- owner: userMap[slate.data.ownerId],
- };
- });
-
- stats.forEach((stat) => {
- averageNewObjectsDaily = averageNewObjectsDaily + stat.data.objects;
- averageNewSlatesDaily = averageNewSlatesDaily + stat.data.slates;
- averageNewUsersDaily = averageNewUsersDaily + stat.data.users;
- });
-
- averageNewObjectsDaily = Math.floor(averageNewObjectsDaily / stats.length);
- averageNewSlatesDaily = Math.floor(averageNewSlatesDaily / stats.length);
- averageNewUsersDaily = Math.floor(averageNewUsersDaily / stats.length);
-
- return {
- userCount,
- slateCount,
- slateObjectCount,
- bytes,
- bytesConverted: Strings.bytesToSize(bytes),
- activityCount: activity.length,
- stats,
- averageNewObjectsDaily,
- averageNewSlatesDaily,
- averageNewUsersDaily,
- };
- });
-
- return res.status(200).send({
- decorator: "STATS",
- data: response,
- });
-};
diff --git a/pages/api/v1/update-slate.js b/pages/api/v1/update-slate.js
index 6c4c6319..0d16d7e3 100644
--- a/pages/api/v1/update-slate.js
+++ b/pages/api/v1/update-slate.js
@@ -32,7 +32,7 @@ export default async (req, res) => {
}
const user = await Data.getUserById({
- id: key.owner_id,
+ id: key.ownerId,
});
if (!user) {
@@ -49,60 +49,121 @@ export default async (req, res) => {
});
}
- const response = await Data.getSlateById({ id: req.body.data.id });
-
- if (!response) {
- return res.status(404).send({ decorator: "V1_UPDATE_SLATE_NOT_FOUND", error: true });
- }
-
- if (response.error) {
- return res.status(500).send({ decorator: "V1_UPDATE_SLATE_NOT_FOUND", error: true });
- }
-
- if (!req.body.data) {
+ if (!req.body.data?.id) {
return res.status(500).send({
decorator: "V1_UPDATE_SLATE_MUST_PROVIDE_DATA",
error: true,
});
}
- if (!Strings.isEmpty(req.body.data.data.name)) {
- const existingSlate = await Data.getSlateByName({
- slatename: req.body.data.data.name,
- ownerId: user.id,
- });
-
- if (existingSlate && existingSlate.id !== req.body.data.id) {
- return res.status(500).send({
- decorator: "V1_UPDATE_SLATE_NAME_TAKEN",
- error: true,
- });
- }
- }
-
- let slate = await Data.updateSlateById({
- id: response.id,
- slatename: !Strings.isEmpty(req.body.data.data.name)
- ? Strings.createSlug(req.body.data.data.name)
- : response.slatename,
- updated_at: new Date(),
- data: {
- ...response.data,
- ...req.body.data.data,
- },
- });
+ const slate = await Data.getSlateById({ id: req.body.data.id });
if (!slate) {
- return res.status(404).send({ decorator: "V1_UPDATE_SLATE", error: true });
+ return res.status(404).send({ decorator: "V1_UPDATE_SLATE_NOT_FOUND", error: true });
}
if (slate.error) {
- return res.status(500).send({ decorator: "V1_UPDATE_SLATE", error: true });
+ return res.status(500).send({ decorator: "V1_UPDATE_SLATE_NOT_FOUND", error: true });
}
- let slates = await Data.getSlatesByUserId({ userId: id });
- if (slates) {
- ViewerManager.hydratePartialSlates(slates, id);
+ if (slate.ownerId !== user.id) {
+ return res.status(400).send({
+ decorator: "V1_UPDATE_NOT_PERMITTED",
+ error: true,
+ });
+ }
+
+ const updates = {
+ id: req.body.data.id,
+ slatename: req.body.data.slatename,
+ isPublic: req.body.data.data.public,
+ updatedAt: new Date(),
+ data: {
+ name: req.body.data.data.name,
+ body: req.body.data.data.body,
+ },
+ };
+
+ if (typeof updates.isPublic !== "undefined" && slate.isPublic !== updates.isPublic) {
+ let privacyResponse = await Data.updateSlatePrivacy({
+ id: updates.id,
+ isPublic: updates.isPublic,
+ });
+
+ if (!privacyResponse) {
+ return res
+ .status(404)
+ .send({ decorator: "SERVER_UPDATE_SLATE_UPDATE_PRIVACY_FAILED", error: true });
+ }
+
+ if (privacyResponse.error) {
+ return res
+ .status(500)
+ .send({ decorator: "SERVER_UPDATE_SLATE_UPDATE_PRIVACY_FAILED", error: true });
+ }
+
+ if (!updates.isPublic) {
+ //NOTE(martina): if any of the files in it are now private (because they are no longer in any public slates) remove them from search
+ const files = slate.objects;
+
+ const publicFiles = await Data.getFilesByIds({
+ ids: files.map((file) => file.id),
+ publicOnly: true,
+ });
+ const publicIds = publicFiles.map((file) => file.id);
+
+ let privateFiles = files.filter((file) => !publicIds.includes(file.id));
+
+ if (privateFiles.length) {
+ SearchManager.updateFile(privateFiles, "REMOVE");
+ }
+ } else {
+ //NOTE(martina): make sure all the now-public files are in search if they weren't already
+ const files = slate.objects;
+
+ SearchManager.updateFile(files, "ADD");
+ }
+ }
+
+ if (updates.data.name && updates.data.name !== slate.data.name) {
+ if (!Validations.slatename(slate.data.name)) {
+ return res.status(400).send({
+ decorator: "SERVER_UPDATE_SLATE_INVALID_NAME",
+ error: true,
+ });
+ }
+
+ const existingSlate = await Data.getSlateByName({
+ slatename: updates.data.name,
+ ownerId: user.id,
+ });
+
+ if (existingSlate) {
+ return res.status(500).send({
+ decorator: "SERVER_UPDATE_SLATE_NAME_TAKEN",
+ error: true,
+ });
+ } else {
+ updates.slatename = Strings.createSlug(updates.data.name);
+ }
+ }
+
+ let updatedSlate = await Data.updateSlateById(updates);
+
+ if (!updatedSlate) {
+ return res.status(404).send({ decorator: "SERVER_UPDATE_SLATE_FAILED", error: true });
+ }
+
+ if (updatedSlate.error) {
+ return res.status(500).send({ decorator: "SERVER_UPDATE_SLATE_FAILED", error: true });
+ }
+
+ if (slate.isPublic && !updates.isPublic) {
+ SearchManager.updateSlate(updatedSlate, "REMOVE");
+ } else if (!slate.isPublic && updates.isPublic) {
+ SearchManager.updateSlate(updatedSlate, "ADD");
+ } else {
+ SearchManager.updateSlate(updatedSlate, "EDIT");
}
return res.status(200).send({ decorator: "V1_UPDATE_SLATE", slate });
diff --git a/pages/api/v2/get-slate.js b/pages/api/v2/get-slate.js
new file mode 100644
index 00000000..53e2b959
--- /dev/null
+++ b/pages/api/v2/get-slate.js
@@ -0,0 +1,77 @@
+import * as Utilities from "~/node_common/utilities";
+import * as Data from "~/node_common/data";
+import * as Strings from "~/common/strings";
+import * as Powergate from "~/node_common/powergate";
+
+export default async (req, res) => {
+ if (Strings.isEmpty(req.headers.authorization)) {
+ return res.status(404).send({
+ decorator: "SERVER_API_KEY_MISSING",
+ error: true,
+ });
+ }
+
+ const parsed = Strings.getKey(req.headers.authorization);
+
+ const key = await Data.getAPIKeyByKey({
+ key: parsed,
+ });
+
+ if (!key) {
+ return res.status(403).send({
+ decorator: "V2_GET_SLATE_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ if (key.error) {
+ return res.status(500).send({
+ decorator: "V2_GET_SLATE_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ const user = await Data.getUserById({
+ id: key.ownerId,
+ });
+
+ if (!user) {
+ return res.status(404).send({ decorator: "V2_GET_SLATE_USER_NOT_FOUND", error: true });
+ }
+
+ if (user.error) {
+ return res.status(500).send({ decorator: "V2_GET_SLATE_USER_NOT_FOUND", error: true });
+ }
+
+ let slateId = req.body.data ? req.body.data.id : null;
+ let slate;
+
+ if (Strings.isEmpty(slateId)) {
+ return res.status(400).send({ decorator: "V2_GET_SLATE_NO_ID_PROVIDED", error: true });
+ }
+
+ slate = await Data.getSlateById({ id: slateId, includeFiles: true, sanitize: true });
+
+ if (!slate) {
+ return res.status(404).send({
+ decorator: "V2_GET_SLATE_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ if (slate.error) {
+ return res.status(500).send({
+ decorator: "V2_GET_SLATE_SLATE_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ if (!slate.isPublic) {
+ return res.status(400).send({
+ decorator: "V2_GET_SLATE_NOT_PUBLIC",
+ error: true,
+ });
+ }
+
+ return res.status(200).send({ decorator: "V2_GET_SLATE", slate });
+};
diff --git a/pages/api/v2/get-user.js b/pages/api/v2/get-user.js
new file mode 100644
index 00000000..8fefc03b
--- /dev/null
+++ b/pages/api/v2/get-user.js
@@ -0,0 +1,74 @@
+import * as Utilities from "~/node_common/utilities";
+import * as Data from "~/node_common/data";
+import * as Strings from "~/common/strings";
+import * as Powergate from "~/node_common/powergate";
+
+export default async (req, res) => {
+ if (Strings.isEmpty(req.headers.authorization)) {
+ return res.status(404).send({
+ decorator: "SERVER_API_KEY_MISSING",
+ error: true,
+ });
+ }
+
+ const parsed = Strings.getKey(req.headers.authorization);
+
+ const key = await Data.getAPIKeyByKey({
+ key: parsed,
+ });
+
+ if (!key) {
+ return res.status(403).send({
+ decorator: "V2_GET_USER_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ if (key.error) {
+ return res.status(500).send({
+ decorator: "V2_GET_USER_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ const user = await Data.getUserById({
+ id: key.ownerId,
+ });
+
+ if (!user) {
+ return res.status(404).send({ decorator: "V2_GET_USER_NOT_FOUND", error: true });
+ }
+
+ if (user.error) {
+ return res.status(500).send({ decorator: "V2_GET_USER_NOT_FOUND", error: true });
+ }
+
+ let userId = req.body.data ? req.body.data.id : null;
+
+ if (Strings.isEmpty(userId)) {
+ return res.status(400).send({ decorator: "V2_GET_USER_NO_ID_PROVIDED", error: true });
+ }
+
+ let targetUser = await Data.getUserById({
+ id: userId,
+ sanitize: true,
+ publicOnly: true,
+ includeFiles: true,
+ });
+
+ if (!targetUser) {
+ return res.status(404).send({
+ decorator: "V2_GET_USER_FAILED",
+ error: true,
+ });
+ }
+
+ if (targetUser.error) {
+ return res.status(500).send({
+ decorator: "V2_GET_USER_FAILED",
+ error: true,
+ });
+ }
+
+ return res.status(200).send({ decorator: "V2_GET_USER", user: targetUser });
+};
diff --git a/pages/api/v2/get.js b/pages/api/v2/get.js
new file mode 100644
index 00000000..b70ebada
--- /dev/null
+++ b/pages/api/v2/get.js
@@ -0,0 +1,76 @@
+import * as Utilities from "~/node_common/utilities";
+import * as Data from "~/node_common/data";
+import * as Strings from "~/common/strings";
+import * as Powergate from "~/node_common/powergate";
+
+export default async (req, res) => {
+ if (Strings.isEmpty(req.headers.authorization)) {
+ return res.status(404).send({
+ decorator: "SERVER_API_KEY_MISSING",
+ error: true,
+ });
+ }
+
+ const parsed = Strings.getKey(req.headers.authorization);
+
+ const key = await Data.getAPIKeyByKey({
+ key: parsed,
+ });
+
+ if (!key) {
+ return res.status(403).send({
+ decorator: "V2_GET_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ if (key.error) {
+ return res.status(500).send({
+ decorator: "V2_GET_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ const id = key.ownerId;
+
+ let user = await Data.getUserById({
+ id,
+ includeFiles: true,
+ sanitize: true,
+ });
+
+ if (!user) {
+ return res.status(404).send({ decorator: "V2_GET_USER_NOT_FOUND", error: true });
+ }
+
+ if (user.error) {
+ return res.status(500).send({ decorator: "V2_GET_USER_NOT_FOUND", error: true });
+ }
+
+ const slates = await Data.getSlatesByUserId({
+ ownerId: id,
+ sanitize: true,
+ includeFiles: true,
+ });
+
+ if (!slates) {
+ return res.status(404).send({
+ decorator: "V2_GET_SLATES_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ if (slates.error) {
+ return res.status(500).send({
+ decorator: "V2_GET_SLATES_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ slates = slates.map((each) => {
+ each.data.url = `https://slate.host/${user.username}/${each.slatename}`;
+ return each;
+ });
+
+ return res.status(200).send({ decorator: "V2_GET", user, slates });
+};
diff --git a/pages/api/v2/update-file.js b/pages/api/v2/update-file.js
new file mode 100644
index 00000000..31747ada
--- /dev/null
+++ b/pages/api/v2/update-file.js
@@ -0,0 +1,100 @@
+import * as Data from "~/node_common/data";
+import * as SearchManager from "~/node_common/managers/search";
+
+export default async (req, res) => {
+ if (Strings.isEmpty(req.headers.authorization)) {
+ return res.status(404).send({
+ decorator: "SERVER_API_KEY_MISSING",
+ error: true,
+ });
+ }
+
+ const parsed = Strings.getKey(req.headers.authorization);
+
+ const key = await Data.getAPIKeyByKey({
+ key: parsed,
+ });
+
+ if (!key) {
+ return res.status(403).send({
+ decorator: "V2_UPDATE_FILE_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ if (key.error) {
+ return res.status(500).send({
+ decorator: "V2_UPDATE_FILE_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ const user = await Data.getUserById({
+ id: key.ownerId,
+ });
+
+ if (!user) {
+ return res.status(404).send({
+ decorator: "V2_UPDATE_FILE_USER_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ if (user.error) {
+ return res.status(500).send({
+ decorator: "V2_UPDATE_FILE_USER_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ if (!req.body.data?.id) {
+ return res.status(500).send({ decorator: "V2_UPDATE_FILE_NO_FILE_PROVIDED", error: true });
+ }
+
+ //NOTE(martina): cleans the input to remove fields they should not be changing like ownerId, createdAt, filename, size, type etc.
+ let updates = {
+ id: req.body.data.id,
+ isPublic: req.body.data.isPublic,
+ data: {
+ name: req.body.data.data?.name,
+ body: req.body.data.data?.body,
+ source: req.body.data.data?.source,
+ author: req.body.data.data?.author,
+ },
+ };
+
+ const file = await Data.getFileById({ id: updates.id });
+
+ if (typeof updates.isPublic !== "undefined" && updates.isPublic !== file.id) {
+ let response = await Data.updateFilePrivacy({
+ ownerId: updates.ownerId,
+ id: updates.id,
+ isPublic: updates.isPublic,
+ });
+
+ if (!response || response.error) {
+ return res.status(500).send({ decorator: "V2_UPDATE_FILE_PRIVACY_FAILED", error: true });
+ }
+
+ if (response.isPublic) {
+ SearchManager.updateFile(response, "ADD");
+ } else {
+ SearchManager.updateFile(response, "REMOVE");
+ }
+ }
+
+ let response = await Data.updateFileById(updates);
+
+ if (!response || response.error) {
+ return res.status(500).send({ decorator: "V2_UPDATE_FILE_FAILED", error: true });
+ }
+
+ if (response.isPublic) {
+ SearchManager.updateFile(publicFiles, "EDIT");
+ }
+
+ return res.status(200).send({
+ decorator: "V2_UPDATE_FILE",
+ file: response,
+ });
+};
diff --git a/pages/api/v2/update-slate.js b/pages/api/v2/update-slate.js
new file mode 100644
index 00000000..7c625eb7
--- /dev/null
+++ b/pages/api/v2/update-slate.js
@@ -0,0 +1,165 @@
+import * as Utilities from "~/node_common/utilities";
+import * as Data from "~/node_common/data";
+import * as Strings from "~/common/strings";
+import * as ViewerManager from "~/node_common/managers/viewer";
+import * as SearchManager from "~/node_common/managers/search";
+
+export default async (req, res) => {
+ if (Strings.isEmpty(req.headers.authorization)) {
+ return res.status(404).send({
+ decorator: "SERVER_API_KEY_MISSING",
+ error: true,
+ });
+ }
+
+ const parsed = Strings.getKey(req.headers.authorization);
+
+ const key = await Data.getAPIKeyByKey({
+ key: parsed,
+ });
+
+ if (!key) {
+ return res.status(403).send({
+ decorator: "V2_UPDATE_SLATE_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ if (key.error) {
+ return res.status(500).send({
+ decorator: "V2_UPDATE_SLATE_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ const user = await Data.getUserById({
+ id: key.ownerId,
+ });
+
+ if (!user) {
+ return res.status(404).send({
+ decorator: "V2_UPDATE_SLATE_USER_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ if (user.error) {
+ return res.status(500).send({
+ decorator: "V2_UPDATE_SLATE_USER_NOT_FOUND",
+ error: true,
+ });
+ }
+
+ if (!req.body.data) {
+ return res.status(500).send({
+ decorator: "V2_UPDATE_SLATE_MUST_PROVIDE_DATA",
+ error: true,
+ });
+ }
+
+ const slate = await Data.getSlateById({ id: req.body.data.id, includeFiles: true });
+
+ if (!slate) {
+ return res.status(404).send({ decorator: "V2_UPDATE_SLATE_NOT_FOUND", error: true });
+ }
+
+ if (slate.error) {
+ return res.status(500).send({ decorator: "V2_UPDATE_SLATE_NOT_FOUND", error: true });
+ }
+
+ //NOTE(martina): cleans the input to remove fields they should not be changing like ownerId, createdAt, etc.
+ let updates = {
+ id: req.body.data.id,
+ updatedAt: new Date(),
+ slatename: req.body.data.slatename,
+ isPublic: req.body.data.isPublic,
+ data: {
+ name: req.body.data.data?.name,
+ body: req.body.data.data?.body,
+ },
+ };
+
+ if (typeof updates.isPublic !== "undefined" && slate.isPublic !== updates.isPublic) {
+ let privacyResponse = await Data.updateSlatePrivacy({
+ id: updates.id,
+ isPublic: updates.isPublic,
+ });
+
+ if (!privacyResponse) {
+ return res
+ .status(404)
+ .send({ decorator: "SERVER_UPDATE_SLATE_UPDATE_PRIVACY_FAILED", error: true });
+ }
+
+ if (privacyResponse.error) {
+ return res
+ .status(500)
+ .send({ decorator: "SERVER_UPDATE_SLATE_UPDATE_PRIVACY_FAILED", error: true });
+ }
+
+ if (!updates.isPublic) {
+ //NOTE(martina): if any of the files in it are now private (because they are no longer in any public slates) remove them from search
+ const files = slate.objects;
+
+ const publicFiles = await Data.getFilesByIds({
+ ids: files.map((file) => file.id),
+ publicOnly: true,
+ });
+ const publicIds = publicFiles.map((file) => file.id);
+
+ let privateFiles = files.filter((file) => !publicIds.includes(file.id));
+
+ if (privateFiles.length) {
+ SearchManager.updateFile(privateFiles, "REMOVE");
+ }
+ } else {
+ //NOTE(martina): make sure all the now-public files are in search if they weren't already
+ const files = slate.objects;
+
+ SearchManager.updateFile(files, "ADD");
+ }
+ }
+
+ if (updates.data.name && updates.data.name !== slate.data.name) {
+ if (!Validations.slatename(slate.data.name)) {
+ return res.status(400).send({
+ decorator: "SERVER_UPDATE_SLATE_INVALID_NAME",
+ error: true,
+ });
+ }
+
+ const existingSlate = await Data.getSlateByName({
+ slatename: updates.data.name,
+ ownerId: user.id,
+ });
+
+ if (existingSlate) {
+ return res.status(500).send({
+ decorator: "SERVER_UPDATE_SLATE_NAME_TAKEN",
+ error: true,
+ });
+ } else {
+ updates.slatename = Strings.createSlug(updates.data.name);
+ }
+ }
+
+ let updatedSlate = await Data.updateSlateById(updates);
+
+ if (!updatedSlate) {
+ return res.status(404).send({ decorator: "SERVER_UPDATE_SLATE_FAILED", error: true });
+ }
+
+ if (updatedSlate.error) {
+ return res.status(500).send({ decorator: "SERVER_UPDATE_SLATE_FAILED", error: true });
+ }
+
+ if (slate.isPublic && !updates.isPublic) {
+ SearchManager.updateSlate(updatedSlate, "REMOVE");
+ } else if (!slate.isPublic && updates.isPublic) {
+ SearchManager.updateSlate(updatedSlate, "ADD");
+ } else {
+ SearchManager.updateSlate(updatedSlate, "EDIT");
+ }
+
+ return res.status(200).send({ decorator: "V2_UPDATE_SLATE", slate: updatedSlate });
+};
diff --git a/pages/api/zip/get-paths.js b/pages/api/zip/get-paths.js
index 709cc354..dc55cb4c 100644
--- a/pages/api/zip/get-paths.js
+++ b/pages/api/zip/get-paths.js
@@ -9,9 +9,7 @@ export default async (req, res) => {
});
if (!user || user.error) {
- return res
- .status(403)
- .send({ decorator: "SERVER_GET_ZIP_FILES_PATHS_USER_NOT_FOUND", error: true });
+ return res.status(403).send({ decorator: "SERVER_USER_NOT_FOUND", error: true });
}
let { buckets, bucketKey } = await Utilities.getBucketAPIFromUserToken({
@@ -20,7 +18,7 @@ export default async (req, res) => {
if (!buckets) {
return res.status(500).send({
- decorator: "SERVER_GET_BUCKET_DATA",
+ decorator: "SERVER_NO_BUCKET_DATA",
error: true,
});
}
diff --git a/pages/index.js b/pages/index.js
index b2abeb69..7822a019 100644
--- a/pages/index.js
+++ b/pages/index.js
@@ -377,7 +377,7 @@ export default class IndexPage extends React.Component {
this.setState({ showText: false }) : () => {}}
>
- {isImage && (this.state.showText || this.props.mobile) ? (
+ {isImage && (this.state.showText || this.props.isMobile) ? (
) : null}
- {this.state.showText || !isImage || this.props.mobile ? (
+ {this.state.showText || !isImage || this.props.isMobile ? (
{isImage ? null : (
- {item.file.title || item.file.name}
+ {item.file.data.name || item.file.filename}
)}
{
let file;
- for (let obj of item.slate?.data?.objects || []) {
+ for (let obj of item.slate?.objects || []) {
if (Validations.isPreviewableImage(obj.type) || obj.coverImage) {
file = obj;
}
}
- let numObjects = item.slate?.data?.objects?.length || 0;
+ let numObjects = item.slate?.objects?.length || 0;
return (
{file ? (
) : null}
@@ -271,59 +265,45 @@ export default class SceneActivity extends React.Component {
};
fetchActivityItems = async (update = false) => {
+ const isExplore = this.props.tab === 1;
this.setState({ loading: "loading" });
- let activity =
- this.props.tab === 0 ? this.props.viewer.activity || [] : this.props.viewer.explore || [];
- let response;
+ let activity = isExplore ? this.props.viewer.explore || [] : this.props.viewer.activity || [];
+
+ let requestObject = {};
if (activity.length) {
if (update) {
- //NOTE(martina): fetch any new updates since last fetched
- response = await Actions.getActivity({
- explore: this.props.tab === 1,
- latestTimestamp: activity[0].created_at,
- });
- if (Events.hasError(response)) {
- this.setState({ loading: "failed" });
- return;
- }
- if (!response.activity.length) {
- this.setState({ loading: false });
- return;
- }
- activity.unshift(...response.activity);
- this.count = 0;
- activity = this.formatActivity(activity);
+ requestObject.latestTimestamp = activity[0].createdAt;
} else {
- //NOTE(martina): pagination -- fetch the next 100 events upon scrolling to the bottom
- response = await Actions.getActivity({
- explore: this.props.tab === 1,
- earliestTimestamp: activity[activity.length - 1].created_at,
- });
- if (Events.hasError(response)) {
- this.setState({ loading: "failed" });
- return;
- }
- if (!response.activity.length) {
- this.setState({ loading: false });
- return;
- }
- let newItems = this.formatActivity(response.activity) || [];
- activity.push(...newItems);
+ requestObject.earliestTimestamp = activity[activity.length - 1].createdAt;
}
- } else {
- //NOTE(martina): fetch the most recent 100 events
- response = await Actions.getActivity({ explore: this.props.tab === 1 });
- if (Events.hasError(response)) {
- this.setState({ loading: false });
- return;
- }
- if (!response.activity.length) {
- this.setState({ loading: false });
- return;
- }
- this.count = 0;
- activity = this.formatActivity(response.activity);
}
+
+ let response;
+ if (isExplore) {
+ response = await Actions.getExplore(requestObject);
+ } else {
+ requestObject.following = this.props.viewer.following.map((item) => item.id);
+ requestObject.subscriptions = this.props.viewer.subscriptions.map((item) => item.id);
+
+ response = await Actions.getActivity(requestObject);
+ }
+
+ if (Events.hasError(response)) {
+ this.setState({ loading: "failed" });
+ return;
+ }
+
+ let newItems = response.activity || response.explore;
+
+ if (update) {
+ activity.unshift(...newItems);
+ this.counter = 0;
+ activity = this.formatActivity(activity);
+ } else {
+ newItems = this.formatActivity(newItems);
+ activity.push(...newItems);
+ }
+
if (this.props.tab === 0) {
this.props.onUpdateViewer({ activity: activity });
} else {
@@ -333,30 +313,43 @@ export default class SceneActivity extends React.Component {
};
formatActivity = (userActivity) => {
- //NOTE(martina): rearrange order to always get an even row of 6 squares
- let activity = userActivity || [];
- for (let i = 0; i < activity.length; i++) {
- let item = activity[i];
- if (item.data.type === "SUBSCRIBED_CREATE_SLATE") {
- this.counter += 2;
- } else if (item.data.type === "SUBSCRIBED_ADD_TO_SLATE") {
- this.counter += 1;
+ let activity = [];
+ for (let item of userActivity) {
+ if (item.slate && !item.slate.isPublic) {
+ continue;
}
- if (this.counter === 6) {
- this.counter = 0;
- } else if (this.counter > 6) {
- let j = i - 1;
- while (activity[j].data.type !== "SUBSCRIBED_ADD_TO_SLATE") {
- j -= 1;
- }
- let temp = activity[j];
- activity[j] = activity[i];
- activity[i] = temp;
- this.counter = 0;
- i -= 1;
+ if (item.type === "CREATE_SLATE_OBJECT" && item.slate && item.file) {
+ activity.push(item);
+ } else if (item.type === "CREATE_SLATE" && item.slate) {
+ activity.push(item);
}
}
- return activity;
+ return activity; //NOTE(martina): because now it's only things of CREATE_SLATE_OBJECT type, so all square and don't need reordering
+ //NOTE(martina): rearrange order to always get an even row of 6 squares
+ //TODO(martina): improve this. will fail if there are no more squares left to "swap" with at the end, and you'll end up wtih an empty space
+ // let activity = userActivity || [];
+ // for (let i = 0; i < activity.length; i++) {
+ // let item = activity[i];
+ // if (item.type === "CREATE_SLATE") {
+ // this.counter += 2;
+ // } else if (item.type === "CREATE_SLATE_OBJECT") {
+ // this.counter += 1;
+ // }
+ // if (this.counter === 6) {
+ // this.counter = 0;
+ // } else if (this.counter > 6) {
+ // let j = i - 1;
+ // while (activity[j].type !== "CREATE_SLATE_OBJECT") {
+ // j -= 1;
+ // }
+ // let temp = activity[j];
+ // activity[j] = activity[i];
+ // activity[i] = temp;
+ // this.counter = 0;
+ // i -= 1;
+ // }
+ // }
+ // return activity;
};
_handleCreateSlate = () => {
@@ -379,7 +372,7 @@ export default class SceneActivity extends React.Component {
};
getItemIndexById = (items, item) => {
- const id = item.data?.context?.file?.id;
+ const id = item.file?.id;
return items.findIndex((i) => i.id === id);
};
@@ -387,12 +380,12 @@ export default class SceneActivity extends React.Component {
let activity =
this.props.tab === 0 ? this.props.viewer.activity || [] : this.props.viewer.explore || [];
let items = activity
- .filter((item) => item.data.type === "SUBSCRIBED_ADD_TO_SLATE")
+ .filter((item) => item.type === "CREATE_SLATE_OBJECT")
.map((item) => {
return {
- ...item.data.context.file,
- slate: item.data.context.slate,
- owner: item.data.context.user.username,
+ ...item.file,
+ slate: item.slate,
+ owner: item.owner?.username,
};
});
@@ -400,7 +393,7 @@ export default class SceneActivity extends React.Component {
{activity.length ? (
{activity.map((item, index) => {
- if (item.data.type === "SUBSCRIBED_CREATE_SLATE") {
+ if (item.type === "CREATE_SLATE") {
return (
);
- } else if (item.data.type === "SUBSCRIBED_ADD_TO_SLATE") {
+ } else if (item.type === "CREATE_SLATE_OBJECT") {
return (
{
this.props.onAction({
type: "NAVIGATE",
value: "NAV_SLATE",
data: {
decorator: "SLATE",
- ...item.data.context.slate,
+ ...item.slate,
},
});
}
@@ -494,10 +488,10 @@ export default class SceneActivity extends React.Component {
>
{}
: () => {
this.props.onAction({
@@ -505,7 +499,7 @@ export default class SceneActivity extends React.Component {
value: "NAV_SLATE",
data: {
decorator: "SLATE",
- ...item.data.context.slate,
+ ...item.slate,
},
});
}
@@ -538,29 +532,3 @@ export default class SceneActivity extends React.Component {
);
}
}
-
-{
- /*
- When you're ready, create a slate!
-
-
- Create a slate
-
-
- */
-}
diff --git a/scenes/SceneArchive.js b/scenes/SceneArchive.js
index 3e875001..0497f0da 100644
--- a/scenes/SceneArchive.js
+++ b/scenes/SceneArchive.js
@@ -32,9 +32,10 @@ export default class SceneArchive extends React.Component {
dealsLoaded: false,
tab: 0,
networkViewer: null,
- allow_filecoin_directory_listing: this.props.viewer.allow_filecoin_directory_listing,
- allow_automatic_data_storage: this.props.viewer.allow_automatic_data_storage,
- allow_encrypted_data_storage: this.props.viewer.allow_encrypted_data_storage,
+ allow_filecoin_directory_listing: this.props.viewer.data.settings
+ ?.allow_filecoin_directory_listing,
+ allow_automatic_data_storage: this.props.viewer.data.settings?.allow_automatic_data_storage,
+ allow_encrypted_data_storage: this.props.viewer.data.settings?.allow_encrypted_data_storage,
};
async componentDidMount() {
@@ -97,9 +98,11 @@ export default class SceneArchive extends React.Component {
await Actions.updateViewer({
data: {
- allow_filecoin_directory_listing: this.state.allow_filecoin_directory_listing,
- allow_automatic_data_storage: this.state.allow_automatic_data_storage,
- allow_encrypted_data_storage: this.state.allow_encrypted_data_storage,
+ settings: {
+ allow_filecoin_directory_listing: this.state.allow_filecoin_directory_listing,
+ allow_automatic_data_storage: this.state.allow_automatic_data_storage,
+ allow_encrypted_data_storage: this.state.allow_encrypted_data_storage,
+ },
},
});
diff --git a/scenes/SceneDataTransfer.js b/scenes/SceneDataTransfer[dep].js
similarity index 100%
rename from scenes/SceneDataTransfer.js
rename to scenes/SceneDataTransfer[dep].js
diff --git a/scenes/SceneDirectory.js b/scenes/SceneDirectory.js
index 6407f4c0..4ca1b122 100644
--- a/scenes/SceneDirectory.js
+++ b/scenes/SceneDirectory.js
@@ -91,8 +91,8 @@ const STYLES_STATUS_INDICATOR = css`
width: 7px;
height: 7px;
border-radius: 50%;
- border: 2px solid ${Constants.system.gray50};
- background-color: ${Constants.system.white};
+ border: 2px solid ${Constants.system.active};
+ background-color: ${Constants.system.active};
`;
const STYLES_MESSAGE = css`
@@ -119,13 +119,7 @@ function UserEntry({ user, button, onClick, message, checkStatus }) {
{user.data.name || `@${user.username}`}
@@ -200,56 +194,7 @@ export default class SceneDirectory extends React.Component {
};
render() {
- let following = this.props.viewer.subscriptions
- .filter((relation) => {
- return !!relation.target_user_id;
- })
- .map((relation) => {
- let button = (
- this._handleClick(e, relation.id)}>
-
- {this.state.contextMenu === relation.id ? (
-
this._handleClick(e, relation.id)}
- >
- this._handleFollow(e, relation.user.id),
- },
- ]}
- />
-
- ) : null}
-
- );
- return (
- {
- this.props.onAction({
- type: "NAVIGATE",
- value: this.props.sceneId,
- scene: "PROFILE",
- data: relation.user,
- });
- }}
- />
- );
- });
-
- let followers = this.props.viewer.subscribers.map((relation) => {
+ let following = this.props.viewer.following.map((relation) => {
let button = (
this._handleClick(e, relation.id)}>
@@ -267,12 +212,8 @@ export default class SceneDirectory extends React.Component {
}}
navigation={[
{
- text: this.props.viewer.subscriptions.filter((subscription) => {
- return subscription.target_user_id === relation.owner.id;
- }).length
- ? "Unfollow"
- : "Follow",
- onClick: (e) => this._handleFollow(e, relation.owner.id),
+ text: "Unfollow",
+ onClick: (e) => this._handleFollow(e, relation.id),
},
]}
/>
@@ -283,7 +224,7 @@ export default class SceneDirectory extends React.Component {
return (
{
@@ -291,7 +232,56 @@ export default class SceneDirectory extends React.Component {
type: "NAVIGATE",
value: this.props.sceneId,
scene: "PROFILE",
- data: relation.owner,
+ data: relation,
+ });
+ }}
+ />
+ );
+ });
+
+ let followers = this.props.viewer.followers.map((relation) => {
+ let button = (
+ this._handleClick(e, relation.id)}>
+
+ {this.state.contextMenu === relation.id ? (
+
this._handleClick(e, relation.id)}
+ >
+ {
+ return user.id === relation.id;
+ })
+ ? "Unfollow"
+ : "Follow",
+ onClick: (e) => this._handleFollow(e, relation.id),
+ },
+ ]}
+ />
+
+ ) : null}
+
+ );
+ return (
+ {
+ this.props.onAction({
+ type: "NAVIGATE",
+ value: this.props.sceneId,
+ scene: "PROFILE",
+ data: relation,
});
}}
/>
diff --git a/scenes/SceneEditAccount.js b/scenes/SceneEditAccount.js
index c1a5eca1..459184a5 100644
--- a/scenes/SceneEditAccount.js
+++ b/scenes/SceneEditAccount.js
@@ -47,9 +47,10 @@ export default class SceneEditAccount extends React.Component {
photo: this.props.viewer.data.photo,
name: this.props.viewer.data.name,
deleting: false,
- allow_filecoin_directory_listing: this.props.viewer.allow_filecoin_directory_listing,
- allow_automatic_data_storage: this.props.viewer.allow_automatic_data_storage,
- allow_encrypted_data_storage: this.props.viewer.allow_encrypted_data_storage,
+ allow_filecoin_directory_listing: this.props.viewer.data.settings
+ ?.allow_filecoin_directory_listing,
+ allow_automatic_data_storage: this.props.viewer.data.settings?.allow_automatic_data_storage,
+ allow_encrypted_data_storage: this.props.viewer.data.settings?.allow_encrypted_data_storage,
changingPassword: false,
changingAvatar: false,
savingNameBio: false,
@@ -59,17 +60,17 @@ export default class SceneEditAccount extends React.Component {
_handleUpload = async (e) => {
this.setState({ changingAvatar: true });
- let json = await UserBehaviors.uploadImage(e.target.files[0], this.props.resources, true);
- if (!json) {
+ let file = await UserBehaviors.uploadImage(e.target.files[0], this.props.resources, true);
+ if (!file) {
this.setState({ changingAvatar: false });
return;
}
- const cid = json.data.cid;
- const url = Strings.getCIDGatewayURL(cid);
+ const cid = file.cid;
+ const url = Strings.getURLfromCID(cid);
let updateResponse = await Actions.updateViewer({
data: {
- photo: Strings.getCIDGatewayURL(cid),
+ photo: Strings.getURLfromCID(cid),
},
});
@@ -82,9 +83,11 @@ export default class SceneEditAccount extends React.Component {
let response = await Actions.updateViewer({
data: {
- allow_filecoin_directory_listing: this.state.allow_filecoin_directory_listing,
- allow_automatic_data_storage: this.state.allow_automatic_data_storage,
- allow_encrypted_data_storage: this.state.allow_encrypted_data_storage,
+ settings: {
+ allow_filecoin_directory_listing: this.state.allow_filecoin_directory_listing,
+ allow_automatic_data_storage: this.state.allow_automatic_data_storage,
+ allow_encrypted_data_storage: this.state.allow_encrypted_data_storage,
+ },
},
});
@@ -134,12 +137,15 @@ export default class SceneEditAccount extends React.Component {
}
this.setState({ changingPassword: true });
+ console.log("got here");
let response = await Actions.updateViewer({
type: "CHANGE_PASSWORD",
password: this.state.password,
});
+ console.log("after response");
+ console.log(response);
if (Events.hasError(response)) {
this.setState({ changingPassword: false });
return;
diff --git a/scenes/SceneEncryptedData.js b/scenes/SceneEncryptedData[dep].js
similarity index 100%
rename from scenes/SceneEncryptedData.js
rename to scenes/SceneEncryptedData[dep].js
diff --git a/scenes/SceneFile.js b/scenes/SceneFile.js
index 8730d39c..1ec9f650 100644
--- a/scenes/SceneFile.js
+++ b/scenes/SceneFile.js
@@ -71,7 +71,7 @@ const STYLES_PATH = css`
export default class SceneFile extends React.Component {
render() {
const cid = this.props.data.cid;
- const fileURL = Strings.getCIDGatewayURL(cid);
+ const fileURL = Strings.getURLfromCID(cid);
return (
@@ -85,7 +85,7 @@ export default class SceneFile extends React.Component {
-
+
);
}
diff --git a/scenes/SceneFilesFolder.js b/scenes/SceneFilesFolder.js
index da25b753..139bfe97 100644
--- a/scenes/SceneFilesFolder.js
+++ b/scenes/SceneFilesFolder.js
@@ -124,7 +124,7 @@ export default class SceneFilesFolder extends React.Component {
},
filtersActive: false,
privacy: "ALL",
- filteredFiles: this.props.viewer?.library[0].children,
+ filteredFiles: this.props.viewer?.library,
keyboardTooltip: false,
};
@@ -133,7 +133,7 @@ export default class SceneFilesFolder extends React.Component {
};
componentDidUpdate = (prevProps, prevState) => {
- if (prevProps.viewer.library[0].children !== this.props.viewer.library[0].children) {
+ if (prevProps.viewer.library !== this.props.viewer.library) {
if (this.state.filtersActive) {
this._filterFiles();
}
@@ -155,7 +155,7 @@ export default class SceneFilesFolder extends React.Component {
let filter = this.state.privacy;
const viewer = this.props.viewer;
if (filter === "ALL") {
- return viewer.library[0].children;
+ return viewer.library;
}
const filtered = getPublicAndPrivateFiles({ viewer });
@@ -188,7 +188,7 @@ export default class SceneFilesFolder extends React.Component {
let filteredFiles = this._getPrivacyFilteredFiles();
- if (fileTypeFiltersActive && this.props.viewer?.library[0].children?.length) {
+ if (fileTypeFiltersActive && this.props.viewer?.library?.length) {
filteredFiles = filteredFiles.filter((file) => {
return (
(filters.image && file.type.startsWith("image/")) ||
@@ -213,7 +213,7 @@ export default class SceneFilesFolder extends React.Component {
if (page?.index) {
index = page.index;
} else {
- let library = this.props.viewer.library[0]?.children || [];
+ let library = this.props.viewer.library || [];
for (let i = 0; i < library.length; i++) {
let obj = library[i];
if ((obj.cid && obj.cid === page?.cid) || (obj.id && obj.id === page?.fileId)) {
@@ -233,16 +233,14 @@ export default class SceneFilesFolder extends React.Component {
};
render() {
- let files = this.state.filtersActive
- ? this.state.filteredFiles
- : this.props.viewer?.library[0].children;
+ let files = this.state.filtersActive ? this.state.filteredFiles : this.props.viewer?.library;
files = files || [];
return (
,
@@ -288,7 +286,7 @@ export default class SceneFilesFolder extends React.Component {
viewer={this.props.viewer}
objects={files}
onAction={this.props.onAction}
- mobile={this.props.mobile}
+ isMobile={this.props.isMobile}
isOwner={true}
/>
{
this.fetchProfile();
};
+ componentDidUpdate = (prevProps) => {
+ if (this.state.isOwner && this.props.viewer.library !== prevProps.viewer.library) {
+ let filteredViewer = this.getFilteredViewer();
+ this.setState({ profile: filteredViewer });
+ } else if (this.props.page !== prevProps.page) {
+ this.openCarouselToItem();
+ }
+ };
+
fetchProfile = async () => {
const username = this.props.page.user || this.props.page.data?.username;
+ let isOwner = false;
let query;
let targetUser;
if (username) {
if (username === this.props.viewer.username) {
+ isOwner = true;
targetUser = this.getFilteredViewer();
} else {
query = { username: username };
}
- } else if (this.props.data && this.props.data.id) {
+ } else if (this.props.data?.id) {
if (this.props.data.id === this.props.viewer.id) {
+ isOwner = true;
targetUser = this.getFilteredViewer();
} else {
query = { id: this.props.data.id };
@@ -61,52 +75,62 @@ export default class SceneProfile extends React.Component {
targetUser = response.data;
}
-
- const {
- page: { cid },
- } = this.props;
-
window.history.replaceState(
{ ...window.history.state, data: targetUser },
"A slate user",
`/${targetUser.username}`
);
+ this.props.onUpdateData(targetUser);
+ this.setState({ isOwner, profile: targetUser, loading: false }, this.openCarouselToItem);
+ };
- this.props.onUpdateData({ data: targetUser });
- this.setState({ profile: targetUser }, () => {
- if (Strings.isEmpty(cid)) {
- return;
- }
+ openCarouselToItem = () => {
+ if (!this.state.profile?.library?.length) {
+ return;
+ }
+ const { cid, fileId, index } = this.props.page;
- let library = targetUser.library[0].children || [];
- const index = library.findIndex((object) => object.cid === cid);
- if (index !== -1) {
- Events.dispatchCustomEvent({
- name: "slate-global-open-carousel",
- detail: { index },
- });
- } else {
- Events.dispatchCustomEvent({
- name: "create-alert",
- detail: {
- alert: {
- message:
- "The requested file could not be found. It could have been deleted or may be private",
- },
- },
- });
- }
- });
+ if (Strings.isEmpty(cid) && Strings.isEmpty(fileId) && typeof index === "undefined") {
+ return;
+ }
+
+ const library = this.state.profile.library;
+
+ let foundIndex = -1;
+ if (index) {
+ foundIndex = index;
+ } else if (cid) {
+ foundIndex = library.findIndex((object) => object.cid === cid);
+ } else if (fileId) {
+ foundIndex = library.findIndex((object) => object.id === fileId);
+ }
+ if (typeof foundIndex !== "undefined" && foundIndex !== -1) {
+ Events.dispatchCustomEvent({
+ name: "slate-global-open-carousel",
+ detail: { index: foundIndex },
+ });
+ }
+ // else {
+ // Events.dispatchCustomEvent({
+ // name: "create-alert",
+ // detail: {
+ // alert: {
+ // message:
+ // "The requested file could not be found. It could have been deleted or may be private",
+ // },
+ // },
+ // });
+ // }
};
getFilteredViewer = () => {
let viewer = this.props.viewer;
const res = Utilities.getPublicAndPrivateFiles({ viewer });
- viewer.library[0].children = res.publicFiles;
- return viewer;
+ return { ...viewer, library: res.publicFiles };
};
render() {
+ console.log(this.state.profile);
if (this.state.notFound) {
return (
@@ -118,24 +142,25 @@ export default class SceneProfile extends React.Component {
);
}
- if (!this.state.profile) {
+ if (this.state.loading) {
return (
-
-
-
+
+
+
+
+
+ );
+ } else if (this.state.profile?.id) {
+ return (
+
);
}
-
- return (
-
- );
+ return null;
}
}
diff --git a/scenes/SceneSlate.js b/scenes/SceneSlate.js
index da4c5650..361c869f 100644
--- a/scenes/SceneSlate.js
+++ b/scenes/SceneSlate.js
@@ -19,7 +19,7 @@ import { GlobalCarousel } from "~/components/system/components/GlobalCarousel";
import ProcessedText from "~/components/core/ProcessedText";
import ScenePage from "~/components/core/ScenePage";
import ScenePageHeader from "~/components/core/ScenePageHeader";
-import CircleButtonGray from "~/components/core/CircleButtonGray";
+import SquareButtonGray from "~/components/core/SquareButtonGray";
import EmptyState from "~/components/core/EmptyState";
const STYLES_LOADER = css`
@@ -58,6 +58,7 @@ const STYLES_MOBILE_ONLY = css`
export default class SceneSlate extends React.Component {
state = {
+ loading: true,
notFound: false,
accessDenied: false,
};
@@ -67,7 +68,7 @@ export default class SceneSlate extends React.Component {
};
componentDidUpdate = async (prevProps) => {
- if (this.props.data?.id && prevProps.data?.id && this.props.data.id !== prevProps.data.id) {
+ if (!this.props.data?.objects && !this.state.notFound) {
await this.fetchSlate();
} else if (this.props.page !== prevProps.page) {
this.openCarouselToItem();
@@ -125,54 +126,57 @@ export default class SceneSlate extends React.Component {
response = await Actions.getSerializedSlate(query);
}
if (response?.decorator == "SLATE_PRIVATE_ACCESS_DENIED") {
- this.setState({ accessDenied: true });
+ this.setState({ accessDenied: true, loading: false });
return;
}
if (Events.hasError(response)) {
- this.setState({ notFound: true });
+ this.setState({ notFound: true, loading: false });
return;
}
- slate = response.data;
+ slate = response.slate;
window.history.replaceState(
{ ...window.history.state, data: slate },
"Slate",
- `/${response.data.user.username}/${response.data.slatename}`
+ `/${slate.user.username}/${slate.slatename}`
);
}
-
- this.props.onUpdateData({ data: slate }, this.openCarouselToItem);
+ this.props.onUpdateData(slate, () => {
+ this.setState({ loading: false });
+ this.openCarouselToItem();
+ });
};
openCarouselToItem = () => {
- let slate = this.props.data;
- let index = -1;
- let page = this.props.page;
- if (page?.fileId || page?.cid || page?.index || !Strings.isEmpty(page.cid)) {
- if (page?.index) {
- index = page.index;
- } else {
- for (let i = 0; i < slate.data.objects.length; i++) {
- let obj = slate.data.objects[i];
- if (
- (obj.cid && (obj.cid === page.cid || obj.cid === page?.cid)) ||
- (obj.id && obj.id === page?.fileId)
- ) {
- index = i;
- break;
- }
- }
- }
+ if (!this.props.data?.objects?.length) {
+ return;
+ }
+ let objects = this.props.data.objects;
+
+ const { cid, fileId, index } = this.props.page;
+
+ if (Strings.isEmpty(cid) && Strings.isEmpty(fileId) && typeof index === "undefined") {
+ return;
}
- if (index !== -1) {
+ let foundIndex = -1;
+ if (index) {
+ foundIndex = index;
+ } else if (cid) {
+ foundIndex = objects.findIndex((object) => object.cid === cid);
+ } else if (fileId) {
+ foundIndex = objects.findIndex((object) => object.id === fileId);
+ }
+
+ if (typeof foundIndex !== "undefined" && foundIndex !== -1) {
Events.dispatchCustomEvent({
name: "slate-global-open-carousel",
- detail: { index },
+ detail: { index: foundIndex },
});
}
};
render() {
+ console.log(this.props.data);
if (this.state.notFound || this.state.accessDenied) {
return (
@@ -187,7 +191,7 @@ export default class SceneSlate extends React.Component {
);
}
- if (!this.props.data?.data?.objects) {
+ if (this.state.loading) {
return (
@@ -195,8 +199,10 @@ export default class SceneSlate extends React.Component {
);
+ } else if (this.props.data?.id) {
+ return ;
}
- return ;
+ return null;
}
}
@@ -208,9 +214,9 @@ class SlatePage extends React.Component {
state = {
...(this.props.current, this.props.viewer),
editing: false,
- isFollowing: !!this.props.viewer.subscriptions.filter((subscription) => {
- return subscription.target_slate_id === this.props.current.id;
- }).length,
+ isSubscribed: this.props.viewer.subscriptions.some((subscription) => {
+ return subscription.id === this.props.current.id;
+ }),
};
componentDidMount() {
@@ -224,7 +230,7 @@ class SlatePage extends React.Component {
return;
}
- const index = this.props.current.data.objects.findIndex((object) => object.cid === cid);
+ const index = this.props.current.objects.findIndex((object) => object.cid === cid);
if (index !== -1) {
Events.dispatchCustomEvent({
name: "slate-global-open-carousel",
@@ -246,51 +252,25 @@ class SlatePage extends React.Component {
componentDidUpdate(prevProps) {
if (this.props.viewer.subscriptions !== prevProps.viewer.subscriptions) {
this.setState({
- isFollowing: !!this.props.viewer.subscriptions.filter((subscription) => {
- return subscription.target_slate_id === this.props.current.id;
- }).length,
+ isSubscribed: this.props.viewer.subscriptions.some((subscription) => {
+ return subscription.id === this.props.current.id;
+ }),
});
}
}
- _handleFollow = () => {
- this.setState({ isFollowing: !this.state.isFollowing });
- Actions.createSubscription({
- slateId: this.props.current.id,
+ _handleSubscribe = () => {
+ this.setState({ isSubscribed: !this.state.isSubscribed }, () => {
+ Actions.createSubscription({
+ slateId: this.props.current.id,
+ });
});
};
_handleSaveLayout = async (layouts, autoSave) => {
- await this._handleSave(null, null, layouts, autoSave);
- };
-
- _handleSave = async (e, objects, layouts, autoSave = false, preview) => {
- let layoutOnly = layouts && !objects;
-
- let data = {};
- if (objects) {
- data.objects = objects;
- }
- if (layouts) {
- data.layouts = layouts;
- }
- if (preview) {
- let slates = this.props.viewer.slates;
- let slateId = this.props.current.id;
- for (let slate of slates) {
- if (slate.id === slateId) {
- slate.data.preview = preview;
- break;
- }
- }
- this.props.onUpdateViewer({ slates });
- data.preview = preview;
- }
- const response = await Actions.updateSlate({
+ const response = await Actions.updateSlateLayout({
id: this.props.current.id,
- layoutOnly,
- autoSave,
- data,
+ layouts,
});
if (!autoSave) {
@@ -298,6 +278,24 @@ class SlatePage extends React.Component {
}
};
+ _handleSavePreview = async (preview) => {
+ let updateObject = { id: this.props.current.id, data: { preview } };
+
+ let slates = this.props.viewer.slates;
+ let slateId = this.props.current.id;
+ for (let slate of slates) {
+ if (slate.id === slateId) {
+ slate.data.preview = preview;
+ break;
+ }
+ }
+ this.props.onUpdateViewer({ slates });
+
+ const response = await Actions.updateSlate(updateObject);
+
+ Events.hasError(response);
+ };
+
_handleSelect = (index) =>
Events.dispatchCustomEvent({
name: "slate-global-open-carousel",
@@ -332,9 +330,9 @@ class SlatePage extends React.Component {
}, 1000);
};
- _handleDownloadFiles = () => {
+ _handleDownload = () => {
const slateName = this.props.current.data.name;
- const slateFiles = this.props.current.data.objects;
+ const slateFiles = this.props.current.objects;
UserBehaviors.compressAndDownloadFiles({
files: slateFiles,
name: `${slateName}.zip`,
@@ -343,41 +341,38 @@ class SlatePage extends React.Component {
};
render() {
+ console.log(this.props.current);
+ console.log(this.props.data);
const { user, data } = this.props.current;
const { body = "", preview } = data;
- let objects = this.props.current.data.objects;
+ let objects = this.props.current.objects;
let layouts = this.props.current.data.layouts;
- const isPublic = data.public;
- const isOwner = this.props.current.data.ownerId === this.props.viewer.id;
- const isSlateEmpty = this.props.current.data.objects.length === 0;
+ const isPublic = this.props.current.isPublic;
+ const isOwner = this.props.current.ownerId === this.props.viewer.id;
const tags = data.tags;
let actions = isOwner ? (
- {!isSlateEmpty && (
-
-
-
- )}
-
+
+
+
+
-
-
+
+
-
+
) : (
- {!isSlateEmpty && (
-
- Download
-
- )}
-
- {this.state.isFollowing ? (
-
Unfollow
+
+
+
+
+ {this.state.isSubscribed ? (
+ Unsubscribe
) : (
- Follow
+ Subscribe
)}
@@ -387,7 +382,7 @@ class SlatePage extends React.Component {
@@ -437,11 +432,11 @@ class SlatePage extends React.Component {
objects={objects}
current={this.props.current}
onAction={this.props.onAction}
- mobile={this.props.mobile}
+ isMobile={this.props.isMobile}
isOwner={isOwner}
external={this.props.external}
/>
- {this.props.mobile ? (
+ {this.props.isMobile ? (
this._handleSave(null, null, null, false, preview)}
+ onSavePreview={this._handleSavePreview}
items={objects}
resources={this.props.resources}
onSelect={this._handleSelect}
diff --git a/scenes/SceneSlates.js b/scenes/SceneSlates.js
index a0ca6932..223f85ac 100644
--- a/scenes/SceneSlates.js
+++ b/scenes/SceneSlates.js
@@ -10,7 +10,7 @@ import { FileTypeGroup } from "~/components/core/FileTypeIcon";
import ScenePage from "~/components/core/ScenePage";
import ScenePageHeader from "~/components/core/ScenePageHeader";
import SlatePreviewBlocks from "~/components/core/SlatePreviewBlock";
-import CircleButtonGray from "~/components/core/CircleButtonGray";
+import SquareButtonGray from "~/components/core/SquareButtonGray";
import EmptyState from "~/components/core/EmptyState";
// TODO(jim): Slates design.
@@ -31,17 +31,13 @@ export default class SceneSlates extends React.Component {
};
render() {
- let subscriptions = this.props.viewer.subscriptions
- .filter((each) => {
- return !!each.target_slate_id;
- })
- .map((relation) => relation.slate);
+ let subscriptions = this.props.viewer.subscriptions;
return (
-
+
-
+
+
-
+
) : null
}
/> */}
diff --git a/scripts/adjust.js b/scripts/adjust.js
index d139e47c..e9a3a736 100644
--- a/scripts/adjust.js
+++ b/scripts/adjust.js
@@ -12,7 +12,7 @@ console.log(`RUNNING: adjust.js`);
const createGlobalTable = db.schema.createTable("global", function (table) {
table.uuid("id").primary().unique().notNullable().defaultTo(db.raw("uuid_generate_v4()"));
table.jsonb("data").nullable();
- table.timestamp("created_at").notNullable().defaultTo(db.raw("now()"));
+ table.timestamp("createdAt").notNullable().defaultTo(db.raw("now()"));
});
Promise.all([createGlobalTable]);
diff --git a/scripts/drop-database.js b/scripts/drop-database.js
index 1227c9ca..b4af7d0a 100644
--- a/scripts/drop-database.js
+++ b/scripts/drop-database.js
@@ -12,15 +12,13 @@ console.log(`RUNNING: drop-database.js`);
Promise.all([
db.schema.dropTable("users"),
db.schema.dropTable("slates"),
- db.schema.dropTable("pending"),
db.schema.dropTable("activity"),
- db.schema.dropTable("trusted"),
db.schema.dropTable("subscriptions"),
db.schema.dropTable("keys"),
- db.schema.dropTable("keys"),
+ db.schema.dropTable("global"),
db.schema.dropTable("stats"),
- db.schema.dropTable('deals'),
- db.schema.dropTable("orphans")
+ db.schema.dropTable("deals"),
+ db.schema.dropTable("orphans"),
]);
console.log(`FINISHED: drop-database.js`);
diff --git a/scripts/files-migration.js b/scripts/files-migration.js
new file mode 100644
index 00000000..ec7db564
--- /dev/null
+++ b/scripts/files-migration.js
@@ -0,0 +1,567 @@
+import configs from "~/knexfile";
+import knex from "knex";
+import { v4 as uuid } from "uuid";
+
+import * as Utilities from "~/node_common/utilities";
+import * as Data from "~/node_common/data";
+import * as Strings from "~/common/strings";
+import * as Constants from "~/common/constants";
+
+const envConfig = configs["development"];
+
+const DB = knex(envConfig);
+
+console.log(`RUNNING: files-migration.js`);
+
+// MARK: - check what parameters are in each table
+
+const printUsersTable = async () => {
+ const users = await DB.select("*").from("users");
+ let dataParams = {};
+ let fileParams = {};
+ let coverParams = {};
+ for (let user of users) {
+ for (let param of Object.keys(user.data)) {
+ if (!dataParams[param]) {
+ dataParams[param] = true;
+ }
+ }
+ if (user.data?.library[0]?.children?.length) {
+ let library = user.data.library[0].children;
+ for (let file of library) {
+ for (let param of Object.keys(file)) {
+ if (!fileParams[param]) {
+ fileParams[param] = true;
+ }
+ }
+ if (file.coverImage) {
+ for (let param of Object.keys(file.coverImage)) {
+ if (!coverParams[param]) {
+ coverParams[param] = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ console.log(Object.keys(dataParams));
+ console.log(Object.keys(fileParams));
+ console.log(Object.keys(coverParams));
+};
+
+const printSlatesTable = async () => {
+ const slates = await DB.select("*").from("slates");
+ let dataParams = {};
+ let fileParams = {};
+ let coverParams = {};
+ for (let slate of slates) {
+ for (let param of Object.keys(slate.data)) {
+ if (!dataParams[param]) {
+ dataParams[param] = true;
+ }
+ }
+ if (slate.data.objects?.length) {
+ let objects = slate.data.objects;
+ for (let file of objects) {
+ for (let param of Object.keys(file)) {
+ if (!fileParams[param]) {
+ fileParams[param] = true;
+ }
+ }
+ if (file.coverImage) {
+ for (let param of Object.keys(file.coverImage)) {
+ if (!coverParams[param]) {
+ coverParams[param] = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ console.log(Object.keys(dataParams));
+ console.log(Object.keys(fileParams));
+ console.log(Object.keys(coverParams));
+};
+
+// MARK: - add/modify tables
+
+const addTables = async () => {
+ await DB.schema.table("deals", function (table) {
+ table.renameColumn("owner_user_id", "ownerId"); //replaced
+ table.renameColumn("created_at", "createdAt");
+ table.renameColumn("updated_at", "updatedAt"); //replaced
+ });
+
+ await DB.schema.table("keys", function (table) {
+ table.renameColumn("owner_id", "ownerId"); //replaced
+ table.renameColumn("created_at", "createdAt");
+ });
+
+ await DB.schema.table("stats", function (table) {
+ table.renameColumn("created_at", "createdAt");
+ });
+
+ await DB.schema.table("orphans", function (table) {
+ table.renameColumn("created_at", "createdAt");
+ });
+
+ await DB.schema.table("global", function (table) {
+ table.renameColumn("created_at", "createdAt");
+ });
+
+ await DB.schema.createTable("files", function (table) {
+ table.uuid("id").primary().unique().notNullable().defaultTo(DB.raw("uuid_generate_v4()"));
+ table.uuid("ownerId").references("id").inTable("users");
+ table.timestamp("createdAt").notNullable().defaultTo(DB.raw("now()"));
+ table.string("cid").notNullable();
+ table.string("filename").nullable();
+ table.boolean("isPublic").notNullable().defaultTo(false);
+ table.jsonb("data").nullable();
+ });
+
+ await DB.schema.createTable("slate_files", function (table) {
+ table.uuid("id").primary().unique().notNullable().defaultTo(DB.raw("uuid_generate_v4()"));
+ table.uuid("fileId").references("id").inTable("files");
+ table.uuid("slateId").references("id").inTable("slates");
+ table.timestamp("createdAt").notNullable().defaultTo(DB.raw("now()"));
+ });
+
+ await DB.schema.renameTable("activity", "old_activity");
+
+ await DB.schema.createTable("activity", function (table) {
+ table.uuid("id").primary().unique().notNullable().defaultTo(DB.raw("uuid_generate_v4()"));
+ table.uuid("ownerId").references("id").inTable("users");
+ table.uuid("userId").references("id").inTable("users");
+ table.uuid("slateId").references("id").inTable("slates");
+ table.uuid("fileId").references("id").inTable("files");
+ table.string("type");
+ table.timestamp("createdAt").notNullable().defaultTo(DB.raw("now()"));
+ });
+
+ await DB.schema.table("slates", function (table) {
+ table.renameColumn("created_at", "createdAt");
+ table.renameColumn("updated_at", "updatedAt");
+ table.dropColumn("published_at");
+ table.uuid("ownerId").references("id").inTable("users");
+ table.boolean("isPublic").notNullable().defaultTo(false);
+ });
+
+ await DB.schema.table("users", function (table) {
+ table.string("email").secondary().unique().nullable();
+ table.renameColumn("created_at", "createdAt");
+ table.renameColumn("updated_at", "lastActive");
+ });
+
+ await DB.schema.table("subscriptions", function (table) {
+ table.renameColumn("created_at", "createdAt");
+ table.renameColumn("owner_user_id", "ownerId");
+ table.renameColumn("target_slate_id", "slateId");
+ table.renameColumn("target_user_id", "userId");
+ });
+
+ await DB.schema.table("subscriptions", function (table) {
+ table.uuid("ownerId").references("id").inTable("users").alter();
+ table.uuid("slateId").references("id").inTable("slates").alter();
+ table.uuid("userId").references("id").inTable("users").alter();
+ });
+
+ console.log("finished adding tables");
+};
+
+// MARK: - populate new tables
+
+//strip out the "data-" in the id so it can be a uuid
+//if there's a file with that id already existing, this is probably a save copy instance. So give this one a new id
+//when matching slate fiels to files, if you can't find it by id, match it by cid and ownerId. should only be one match.
+
+const migrateUsersTable = async (testing = false) => {
+ const users = await DB.select("*").from("users");
+ let count = 0;
+ for (let user of users) {
+ if (user.data.library) {
+ if (user.data?.library[0]?.children?.length) {
+ let library = user.data.library[0].children;
+ for (let file of library) {
+ let cid;
+ if (file.cid) {
+ cid = file.cid;
+ } else if (file.ipfs.includes("/ipfs/")) {
+ cid = Strings.getCIDFromIPFS(file.ipfs);
+ } else {
+ cid = file.ipfs;
+ }
+ if (!cid) {
+ console.log("file does not have cid or ipfs");
+ console.log(file);
+ return;
+ }
+ let id = file.id.replace("data-", "");
+ let duplicates = await DB.select("*").from("files").where({ cid: cid, ownerId: user.id });
+ if (duplicates.length) {
+ console.log(duplicates);
+ console.log(`skipped duplicate cid ${cid} in user ${user.id} ${user.username} files`);
+ continue;
+ }
+ let conflicts = await DB.select("*").from("files").where("id", id);
+ if (conflicts.length) {
+ console.log(conflicts);
+ console.log(`found conflicting id ${id} from saved copy in ${user.username} files`);
+ id = uuid();
+ }
+ let newFile = {
+ id,
+ ownerId: user.id,
+ cid,
+ isPublic: file.public,
+ createdAt: file.date,
+ filename: file.file,
+ data: {
+ name: file.name,
+ blurhash: file.blurhash,
+ size: file.size,
+ type: file.type,
+ tags: file.tags, //daniel is working on this, so keep it here
+ link: file.link, //chris is working on this, so keep it here
+ },
+ };
+ if (file.unityGameConfig || file.unityGameLoader) {
+ newFile.data.unity = {
+ config: file.unityGameConfig,
+ loader: file.unityGameLoader,
+ };
+ }
+ if (file.coverImage) {
+ let coverImage = file.coverImage;
+ let newCoverImage = {
+ id: coverImage.id,
+ cid: coverImage.cid,
+ createdAt: coverImage.date,
+ filename: coverImage.file,
+ data: {
+ name: coverImage.name,
+ blurhash: coverImage.blurhash,
+ size: coverImage.size,
+ type: coverImage.type,
+ },
+ };
+ newFile.data.coverImage = newCoverImage;
+ }
+ if (testing) {
+ console.log(newFile);
+ }
+
+ await DB.insert(newFile).into("files");
+ }
+ if (testing) {
+ if (count >= 10) {
+ return;
+ }
+ }
+ }
+ }
+ count += 1;
+ }
+ console.log("finished migrating users table");
+};
+
+const migrateSlatesTable = async (testing = false) => {
+ const slates = await DB.select("*").from("slates");
+ let count = 0;
+ for (let slate of slates) {
+ let objects = [];
+ if (slate.data.objects) {
+ for (let file of slate.data.objects) {
+ let fileId = file.id.replace("data-", "");
+ let cid = Strings.urlToCid(file.url);
+ //NOTE(martina): skip duplicates of the same cid in a slate
+ let matches = await DB.select("id").from("files").where({ id: fileId });
+ if (matches.length !== 1) {
+ //NOTE(martina): means that the id was changed b/c there was a saved copy somewhere, so we need to get that new id
+ matches = await DB.select("*").from("files").where({ cid: cid, ownerId: file.ownerId });
+ if (matches.length === 1) {
+ //NOTE(martina): repairing the file id in the event it was changed in migrateUsersTable because it was a save copy and needed a unique id or b/c was a duplicate file and consolidated
+ console.log(
+ `repaired id for save copy for cid ${cid} in user ${file.ownerId} files in slate ${slate.id} ${slate.slatename}`
+ );
+ fileId = matches.pop().id;
+ } else {
+ console.log(
+ `something went wrong repairing save copy id. there were ${matches.length} matching files with cid ${cid} and ownerId ${file.ownerId}`
+ );
+ console.log(matches);
+ continue;
+ }
+ }
+ //NOTE(martina): if you have the same cid file in data with different ids, just checking slateId and fileId match won't find it
+ //this happens if it was duplicated in data (so has diff ids), then both added to the same slate
+ //this function will catch same cid but diff id
+ let duplicates = await DB.select("*")
+ .from("slate_files")
+ .join("files", "files.id", "=", "slate_files.fileId")
+ .where({ "files.cid": cid, "slate_files.slateId": slate.id })
+ .orWhere({ fileId: fileId, slateId: slate.id });
+ if (duplicates.length) {
+ console.log(`found duplicate file id ${fileId} in slate`);
+ continue;
+ }
+ if (
+ slate.data.ownerId === file.ownerId &&
+ (file.name !== file.title ||
+ !Strings.isEmpty(file.body) ||
+ !Strings.isEmpty(file.source) ||
+ !Strings.isEmpty(file.author))
+ ) {
+ let query = await DB.from("files").where("id", fileId).select("data");
+
+ if (!query.length) {
+ console.log("Could not find matching file for file in slate");
+ continue;
+ }
+ let matchingFile = query[0];
+
+ if (!matchingFile.data) {
+ console.log("Matching file did not have data");
+ continue;
+ }
+
+ if (!testing) {
+ await DB.from("files")
+ .where("id", fileId)
+ .update({
+ data: {
+ ...matchingFile.data,
+ name: file.title,
+ body: file.body,
+ source: file.source,
+ author: file.author,
+ },
+ });
+ }
+ }
+ if (testing) {
+ objects.push({ fileId: fileId, slateId: slate.id });
+ } else {
+ await DB.insert({ fileId: fileId, slateId: slate.id }).into("slate_files");
+ }
+ }
+ }
+ // if (testing) {
+ // if (count >= 10) {
+ // return;
+ // }
+ // console.log(objects);
+ // count += 1;
+ // }
+ }
+ console.log("finished migrating slates table");
+};
+
+//make a function that double checks correctness: finds any duplicate fileId, ownerId in files. and any duplicate fileid slateid in slate_files
+
+/*
+ "CREATE_SLATE" - owner, slate
+ "CREATE_SLATE_OBJECT" - owner, slate, file
+ "CREATE_USER" - owner
+ "USER_DEAL" - owner
+ "SUBSCRIBE_USER" - owner, user
+ "SUBSCRIBE_SLATE" - owner, slate
+*/
+const migrateActivityTable = async (testing = false) => {
+ let acceptedTypes = [
+ "CREATE_SLATE",
+ "CREATE_SLATE_OBJECT",
+ // "CREATE_USER",
+ // "USER_DEAL",
+ // "SUBSCRIBE_USER",
+ // "SUBSCRIBE_SLATE",
+ ];
+ const query = await DB.select("*").from("old_activity");
+ const activity = JSON.parse(JSON.stringify(query));
+ let count = 0;
+ for (let event of activity) {
+ let type = event.data.type;
+ if (!acceptedTypes.includes(type)) {
+ continue;
+ }
+ const id = event.id;
+ const createdAt = event.created_at;
+ let ownerId = event.data.actorUserId;
+ let userId, slateId, fileId;
+ if (type === "CREATE_SLATE") {
+ slateId = event.data.context?.slate?.id;
+ if (!slateId) {
+ // console.log(event.data);
+ continue;
+ }
+ } else if (type === "CREATE_SLATE_OBJECT") {
+ slateId = event.data.context?.slate?.id;
+ fileId = event.data.context?.file?.id;
+ if (!slateId || !fileId) {
+ // console.log(event.data);
+ continue;
+ }
+ fileId = fileId.replace("data-", "");
+ }
+ // else if (type === "SUBSCRIBE_USER") {
+ // userId = event.data.context?.targetUserId;
+ // if (!userId) {
+ // // console.log(event.data);
+ // continue;
+ // }
+ // } else if (type === "SUBSCRIBE_SLATE") {
+ // slateId = event.data.context?.slateId;
+ // if (!slateId) {
+ // // console.log(event.data);
+ // continue;
+ // }
+ // }
+ if (!testing) {
+ try {
+ await DB.insert({
+ id,
+ ownerId,
+ userId,
+ slateId,
+ fileId,
+ type,
+ createdAt,
+ }).into("activity");
+ } catch (e) {
+ console.log(e);
+ }
+ }
+
+ if (testing) {
+ if (count === 10) {
+ return;
+ }
+ count += 1;
+ }
+ }
+ console.log("finished migrating activity table");
+};
+
+// MARK: - adding new fields and reformatting
+
+const modifySlatesTable = async (testing = false) => {
+ const slates = await DB.select("*").from("slates");
+ for (let slate of slates) {
+ const id = slate.id;
+ const ownerId = slate.data.ownerId;
+ if (!ownerId) {
+ console.log(slate);
+ continue;
+ }
+ if (!testing) {
+ await DB.from("slates").where("id", id).update({ ownerId, isPublic: slate.data.public });
+ }
+ }
+ console.log("finished modify slates table");
+};
+
+const modifyUsersTable = async (testing = false) => {
+ const users = await DB.select("*").from("users");
+ let count = 0;
+ for (let user of users) {
+ const id = user.id;
+ let data = {
+ photo: user.data.photo,
+ body: user.data.body,
+ name: user.data.name,
+ tokens: user.data.tokens,
+ settings: {
+ allow_automatic_data_storage: user.data.allow_automatic_data_storage,
+ allow_encrypted_data_storage: user.data.allow_encrypted_data_storage,
+ allow_filecoin_directory_listing: user.data.allow_filecoin_directory_listing,
+ settings_deals_auto_approve: user.data.settings_deals_auto_approve,
+ },
+ onboarding: user.data.onboarding,
+ status: user.data.status,
+ };
+ if (testing) {
+ if (count === 10) {
+ return;
+ }
+ console.log(data);
+ } else {
+ await Data.updateUserById({ id, data });
+ }
+ }
+ console.log("finished modify users table");
+};
+
+// MARK: - deleting original data source
+
+const cleanUsersTable = async () => {
+ const users = await DB.select("*").from("users");
+ for (let user of users) {
+ const id = user.id;
+ let data = user.data;
+ delete user.data.library;
+ let response = await Data.updateUserById({ id, data });
+ }
+};
+
+const cleanSlatesTable = async () => {
+ const slates = await DB.select("*").from("slates");
+ for (let slate of slates) {
+ const id = slate.id;
+ let data = slate.data;
+ delete data.ownerId;
+ let layouts = slate.data.layouts;
+ if (layouts.ver === "2.0") {
+ for (let position of layouts.layout) {
+ position.id = position.id.replace("data-", "");
+ }
+ }
+ await DB.from("slates").where("id", id).update({ data });
+ }
+};
+
+const dropOldTables = async () => {
+ await Promise.all([
+ DB.schema.dropTable("old_activity"),
+ DB.schema.dropTable("trusted"),
+ DB.schema.dropTable("pending"),
+ ]);
+};
+
+// MARK: - reset table
+
+const wipeNewTables = async () => {
+ let numDeleted = await DB("slate_files").del();
+ console.log(`${numDeleted} deleted from slate_files`);
+ numDeleted = await DB("activity").del();
+ console.log(`${numDeleted} deleted from activity`);
+ numDeleted = await DB("files").del();
+ console.log(`${numDeleted} deleted from files`);
+};
+
+const runScript = async () => {
+ //NOTE(martina): if need to reset
+ // await wipeNewTables();
+
+ //NOTE(martina): before starting, make sure you have all the parameters accounted for
+ // await printUsersTable()
+ // await printSlatesTable()
+
+ //NOTE(martina): add tables
+ await addTables();
+
+ //NOTE(martina): put data into new tables
+ let testing = false;
+ // await migrateUsersTable(testing);
+ // await migrateSlatesTable(testing);
+ // await migrateActivityTable(testing);
+
+ //NOTE(martina): fill in new fields and reformat
+ // await modifySlatesTable(testing);
+ // await modifyUsersTable(testing);
+
+ //NOTE(martina): once certain you don't need the data anymore, delete the original data
+ // await cleanUsersTable()
+ // await cleanSlatesTable()
+ // await dropOldTables()
+};
+
+runScript();
diff --git a/scripts/seed-database.js b/scripts/seed-database.js
index 49598e2f..449ff4db 100644
--- a/scripts/seed-database.js
+++ b/scripts/seed-database.js
@@ -13,23 +13,22 @@ console.log(`RUNNING: seed-database.js`);
// SCRIPTS
// --------------------------
+//replace createdat, updatedat, ownerid, owneruserid
+
const createDealsTable = db.schema.createTable("deals", function (table) {
table.uuid("id").primary().unique().notNullable().defaultTo(db.raw("uuid_generate_v4()"));
- table.string("owner_user_id").nullable();
+ table.string("ownerId").nullable();
table.jsonb("data").nullable();
- table.timestamp("created_at").notNullable().defaultTo(db.raw("now()"));
- table.timestamp("updated_at").notNullable().defaultTo(db.raw("now()"));
+ table.timestamp("createdAt").notNullable().defaultTo(db.raw("now()"));
+ table.timestamp("updatedAt").notNullable().defaultTo(db.raw("now()"));
});
const createUsersTable = db.schema.createTable("users", function (table) {
table.uuid("id").primary().unique().notNullable().defaultTo(db.raw("uuid_generate_v4()"));
-
- table.timestamp("created_at").notNullable().defaultTo(db.raw("now()"));
-
- table.timestamp("updated_at").notNullable().defaultTo(db.raw("now()"));
-
+ table.string("email").unique().nullable();
+ table.timestamp("createdAt").notNullable().defaultTo(db.raw("now()"));
+ table.timestamp("lastActive").notNullable().defaultTo(db.raw("now()"));
table.string("username").unique().notNullable();
-
table.string("password").nullable();
table.string("salt").nullable();
table.jsonb("data").nullable();
@@ -37,74 +36,74 @@ const createUsersTable = db.schema.createTable("users", function (table) {
const createSlatesTable = db.schema.createTable("slates", function (table) {
table.uuid("id").primary().unique().notNullable().defaultTo(db.raw("uuid_generate_v4()"));
-
- table.timestamp("created_at").notNullable().defaultTo(db.raw("now()"));
-
- table.timestamp("updated_at").notNullable().defaultTo(db.raw("now()"));
-
- table.timestamp("published_at").nullable();
-
- table.string("slatename").nullable();
-
+ table.uuid("ownerId").references("id").inTable("users");
+ table.timestamp("createdAt").notNullable().defaultTo(db.raw("now()"));
+ table.timestamp("updatedAt").notNullable().defaultTo(db.raw("now()"));
+ table.string("slatename").notNullable();
+ table.boolean("isPublic").notNullable().defaultTo(false);
table.jsonb("data").nullable();
});
const createKeysTable = db.schema.createTable("keys", function (table) {
table.uuid("id").primary().unique().notNullable().defaultTo(db.raw("uuid_generate_v4()"));
table.string("key").unique().nullable();
- table.uuid("owner_id").notNullable();
+ table.uuid("ownerId").notNullable();
table.integer("level").defaultTo(0);
- table.timestamp("created_at").notNullable().defaultTo(db.raw("now()"));
+ table.timestamp("createdAt").notNullable().defaultTo(db.raw("now()"));
});
-const createSubscriptionTable = db.schema.createTable("subscriptions", function (table) {
+const createFilesTable = await db.schema.createTable("files", function (table) {
table.uuid("id").primary().unique().notNullable().defaultTo(db.raw("uuid_generate_v4()"));
- table.string("owner_user_id").nullable();
- table.string("target_slate_id").nullable();
- table.string("target_user_id").nullable();
+ table.uuid("ownerId").references("id").inTable("users");
+ table.timestamp("createdAt").notNullable().defaultTo(db.raw("now()"));
+ table.string("cid").notNullable();
+ table.string("filename").nullable();
+ table.boolean("isPublic").notNullable().defaultTo(false);
table.jsonb("data").nullable();
- table.timestamp("created_at").notNullable().defaultTo(db.raw("now()"));
});
-const createTrustedTable = db.schema.createTable("trusted", function (table) {
+const createSlateFilesTable = await db.schema.createTable("slate_files", function (table) {
table.uuid("id").primary().unique().notNullable().defaultTo(db.raw("uuid_generate_v4()"));
- table.string("owner_user_id").nullable();
- table.string("target_user_id").nullable();
- table.jsonb("data").nullable();
- table.timestamp("created_at").notNullable().defaultTo(db.raw("now()"));
+ table.uuid("fileId").references("id").inTable("files");
+ table.uuid("slateId").references("id").inTable("slates");
+ table.timestamp("createdAt").notNullable().defaultTo(db.raw("now()"));
});
-const createActivityTable = db.schema.createTable("activity", function (table) {
+const createSubscriptionsTable = await db.schema.createTable("subscriptions", function (table) {
table.uuid("id").primary().unique().notNullable().defaultTo(db.raw("uuid_generate_v4()"));
- table.string("owner_slate_id").nullable();
- table.string("owner_user_id").nullable();
+ table.uuid("ownerId").references("id").inTable("users");
+ table.uuid("slateId").references("id").inTable("slates");
+ table.uuid("userId").references("id").inTable("users");
table.jsonb("data").nullable();
- table.timestamp("created_at").notNullable().defaultTo(db.raw("now()"));
+ table.timestamp("createdAt").notNullable().defaultTo(db.raw("now()"));
});
-const createPendingTable = db.schema.createTable("pending", function (table) {
+const createActivityTable = await db.schema.createTable("activity", function (table) {
table.uuid("id").primary().unique().notNullable().defaultTo(db.raw("uuid_generate_v4()"));
- table.string("owner_user_id").notNullable();
- table.jsonb("data").nullable();
- table.timestamp("created_at").notNullable().defaultTo(db.raw("now()"));
+ table.uuid("ownerId").references("id").inTable("users");
+ table.uuid("userId").references("id").inTable("users");
+ table.uuid("slateId").references("id").inTable("slates");
+ table.uuid("fileId").references("id").inTable("files");
+ table.string("type");
+ table.timestamp("createdAt").notNullable().defaultTo(db.raw("now()"));
});
const createStatsTable = db.schema.createTable("stats", function (table) {
table.uuid("id").primary().unique().notNullable().defaultTo(db.raw("uuid_generate_v4()"));
table.jsonb("data").nullable();
- table.timestamp("created_at").notNullable().defaultTo(db.raw("now()"));
+ table.timestamp("createdAt").notNullable().defaultTo(db.raw("now()"));
});
const createOrphansTable = db.schema.createTable("orphans", function (table) {
table.uuid("id").primary().unique().notNullable().defaultTo(db.raw("uuid_generate_v4()"));
table.jsonb("data").nullable();
- table.timestamp("created_at").notNullable().defaultTo(db.raw("now()"));
+ table.timestamp("createdAt").notNullable().defaultTo(db.raw("now()"));
});
const createGlobalTable = db.schema.createTable("global", function (table) {
table.uuid("id").primary().unique().notNullable().defaultTo(db.raw("uuid_generate_v4()"));
table.jsonb("data").nullable();
- table.timestamp("created_at").notNullable().defaultTo(db.raw("now()"));
+ table.timestamp("createdAt").notNullable().defaultTo(db.raw("now()"));
});
// --------------------------
@@ -116,10 +115,10 @@ Promise.all([
createUsersTable,
createSlatesTable,
createKeysTable,
- createSubscriptionTable,
+ createFilesTable,
+ createSlateFilesTable,
+ createSubscriptionsTable,
createActivityTable,
- createTrustedTable,
- createPendingTable,
createStatsTable,
createOrphansTable,
createGlobalTable,
diff --git a/scripts/worker-analytics.js b/scripts/worker-analytics.js
index 6d7bafc8..5858ebd1 100644
--- a/scripts/worker-analytics.js
+++ b/scripts/worker-analytics.js
@@ -19,7 +19,7 @@ function sortObject(obj) {
});
}
}
- arr.sort(function(a, b) {
+ arr.sort(function (a, b) {
return b.value - a.value;
});
//arr.sort(function(a, b) { a.value.toLowerCase().localeCompare(b.value.toLowerCase()); }); //use this to sort as strings
@@ -27,7 +27,7 @@ function sortObject(obj) {
}
const run = async () => {
- const response = await Data.getEveryUser(false);
+ const response = await Data.getEveryUser();
let count = 0;
let bytes = 0;
@@ -37,7 +37,7 @@ const run = async () => {
count = count + 1;
let userBytes = 0;
- user.data.library[0].children.forEach((each) => {
+ user.data.library.forEach((each) => {
userBytes = each.size + userBytes;
bytes = each.size + bytes;
});
@@ -55,7 +55,7 @@ const run = async () => {
console.log("TOTAL BYTES (CONVERTED)", Strings.bytesToSize(bytes));
};
-run();
+// run();
console.log(`FINISHED: worker-analytics.js`);
console.log(` CTRL +C to return to terminal.`);
diff --git a/scripts/worker-heavy-stones.js b/scripts/worker-heavy-stones.js
index cca98421..153e18ca 100644
--- a/scripts/worker-heavy-stones.js
+++ b/scripts/worker-heavy-stones.js
@@ -58,7 +58,7 @@ const run = async () => {
});
Logs.taskTimeless(`Fetching every user ...`);
- const response = await Data.getEveryUser(false);
+ const response = await Data.getEveryUser();
let storageUsers = [];
let bytes = 0;
@@ -70,12 +70,12 @@ const run = async () => {
for (let i = 0; i < response.length; i++) {
const user = response[i];
- if (user.data.allow_automatic_data_storage) {
+ if (user.data.settings?.allow_automatic_data_storage) {
storageUsers.unshift(user);
dealUsers = dealUsers + 1;
}
- if (user.data.allow_encrypted_data_storage) {
+ if (user.data.settings?.allow_encrypted_data_storage) {
encryptedUsers = encryptedUsers + 1;
}
@@ -87,7 +87,7 @@ const run = async () => {
const printData = {
username: storageUsers[i].username,
slateURL: `https://slate.host/${storageUsers[i].username}`,
- isForcingEncryption: user.data.allow_encrypted_data_storage,
+ isForcingEncryption: user.data.settings?.allow_encrypted_data_storage,
};
let buckets;
@@ -187,7 +187,7 @@ const run = async () => {
time: o.time,
pending: o.pending,
createdAt: Strings.toDateSinceEpoch(o.time),
- userEncryptsDeals: !!user.data.allow_encrypted_data_storage,
+ userEncryptsDeals: !!user.data.settings?.allow_encrypted_data_storage,
miner: minerMap[o.dealInfo.miner] ? minerMap[o.dealInfo.miner] : { id: o.dealInfo.miner },
phase: "MARCH",
user: {
@@ -231,7 +231,7 @@ const run = async () => {
Logs.note(`Inserting ${dealToSave.dealId} ...`);
await delay(1000);
- await db.insert({ data: dealToSave, owner_user_id: user.id }).into("deals").returning("*");
+ await db.insert({ data: dealToSave, ownerId: user.id }).into("deals").returning("*");
Logs.task(`Inserted ${dealToSave.dealId} !!!`);
}
}
@@ -343,7 +343,7 @@ const run = async () => {
userBuckets.length < BUCKET_LIMIT
) {
key = null;
- encrypt = !!user.data.allow_encrypted_data_storage;
+ encrypt = !!user.data.settings?.allow_encrypted_data_storage;
// NOTE(jim): Create a new bucket
const newBucketName = encrypt ? `encrypted-data-${uuid()}` : `open-data-${uuid()}`;
diff --git a/server.js b/server.js
index 20b5b39b..0b706dad 100644
--- a/server.js
+++ b/server.js
@@ -3,15 +3,12 @@ import * as Data from "~/node_common/data";
import * as Utilities from "~/node_common/utilities";
import * as Serializers from "~/node_common/serializers";
import * as ViewerManager from "~/node_common/managers/viewer";
-import * as AnalyticsManager from "~/node_common/managers/analytics";
import * as Websocket from "~/node_common/nodejs-websocket";
import * as NodeLogging from "~/node_common/node-logging";
import * as Validations from "~/common/validations";
import * as Window from "~/common/window";
import * as Strings from "~/common/strings";
-import ApiV1GetSlateObjects from "~/pages/api/v1/get-slate-objects";
-
import limit from "express-rate-limit";
import express from "express";
import next from "next";
@@ -81,10 +78,15 @@ const fetchExploreSlates = async () => {
"a0d6e2f2-564d-47ed-bf56-13c42634703d",
"0ba92c73-92e7-4b00-900e-afae4856c9ea",
],
+ includeFiles: true,
+ sanitize: true,
});
for (let exploreSlate of exploreSlates) {
- let user = await Data.getUserById({ id: exploreSlate.data.ownerId });
+ let user = await Data.getUserById({
+ id: exploreSlate.ownerId,
+ sanitize: true,
+ });
exploreSlate.username = user.username;
}
}
@@ -99,10 +101,12 @@ const fetchExploreSlates = async () => {
// "435035e6-dee4-4bbf-9521-64c219a527e7",
// "ac907aa3-2fb2-46fd-8eba-ec8ceb87b5eb",
// ],
+ // includeFiles: true,
+ // sanitize: true,
// });
// for (let exploreSlate of exploreSlates) {
- // let user = await Data.getUserById({ id: exploreSlate.data.ownerId });
+ // let user = await Data.getUserById({ id: exploreSlate.ownerId });
// exploreSlate.username = user.username;
// }
// }
@@ -126,11 +130,6 @@ app.prepare().then(async () => {
server.get("/system/:c", async (r, s) => s.redirect(`/_/system/${r.params.c}`));
server.get("/experiences/:m", async (r, s) => s.redirect(`/_/experiences/${r.params.m}`));
- // NOTE(jim): Example of simple query to query slates by CID.
- server.get("/api/v1/cid::cid", async (r, s) => {
- return await ApiV1GetSlateObjects(r, s);
- });
-
server.all("/api/users/create", createLimiter, async (r, s, next) => {
return handler(r, s, r.url);
});
@@ -152,8 +151,8 @@ app.prepare().then(async () => {
});
server.get("/_", async (req, res) => {
- let mobile = Window.isMobileBrowser(req.headers["user-agent"]);
- let mac = Window.isMac(req.headers["user-agent"]);
+ let isMobile = Window.isMobileBrowser(req.headers["user-agent"]);
+ let isMac = Window.isMac(req.headers["user-agent"]);
const isBucketsAvailable = await Utilities.checkTextile();
@@ -170,13 +169,10 @@ app.prepare().then(async () => {
});
}
- let analytics = await AnalyticsManager.get();
-
return app.render(req, res, "/_", {
viewer,
- analytics,
- mobile,
- mac,
+ isMobile,
+ isMac,
resources: EXTERNAL_RESOURCES,
});
});
@@ -184,15 +180,15 @@ app.prepare().then(async () => {
server.get("/_/integration-page", async (req, res) => {
const id = Utilities.getIdFromCookie(req);
- let viewer = null;
- if (id) {
- viewer = await ViewerManager.getById({
- id,
- });
- }
+ // let viewer = null;
+ // if (id) {
+ // viewer = await ViewerManager.getById({
+ // id,
+ // });
+ // }
return app.render(req, res, "/_/integration-page", {
- viewer,
+ viewer: null,
});
});
@@ -202,6 +198,8 @@ app.prepare().then(async () => {
server.get("/[$]/slate/:id", async (req, res) => {
const slate = await Data.getSlateById({
id: req.params.id,
+ includeFiles: true,
+ sanitize: true,
});
if (!slate) {
@@ -212,11 +210,14 @@ app.prepare().then(async () => {
return res.redirect("/404");
}
- if (!slate.data.public) {
+ if (!slate.isPublic) {
return res.redirect("/403");
}
- const creator = await Data.getUserById({ id: slate.data.ownerId });
+ const creator = await Data.getUserById({
+ id: slate.ownerId,
+ sanitize: true,
+ });
if (!creator) {
return res.redirect("/404");
@@ -230,7 +231,12 @@ app.prepare().then(async () => {
});
server.get("/[$]/user/:id", async (req, res) => {
- const creator = await Data.getUserById({ id: req.params.id });
+ const creator = await Data.getUserById({
+ id: req.params.id,
+ includeFiles: true,
+ publicOnly: true,
+ sanitize: true,
+ });
if (!creator) {
return res.redirect("/404");
@@ -244,11 +250,13 @@ app.prepare().then(async () => {
});
server.get("/[$]/:id", async (req, res) => {
- let mobile = Window.isMobileBrowser(req.headers["user-agent"]);
- let mac = Window.isMac(req.headers["user-agent"]);
+ let isMobile = Window.isMobileBrowser(req.headers["user-agent"]);
+ let isMac = Window.isMac(req.headers["user-agent"]);
const slate = await Data.getSlateById({
id: req.params.id,
+ includeFiles: true,
+ sanitize: true,
});
if (!slate) {
@@ -259,11 +267,14 @@ app.prepare().then(async () => {
return res.redirect("/404");
}
- if (!slate.data.public) {
+ if (!slate.isPublic) {
return res.redirect("/403");
}
- const creator = await Data.getUserById({ id: slate.data.ownerId });
+ const creator = await Data.getUserById({
+ id: slate.ownerId,
+ sanitize: true,
+ });
if (!creator) {
return res.redirect("/404");
@@ -275,31 +286,31 @@ app.prepare().then(async () => {
const id = Utilities.getIdFromCookie(req);
- let viewer = null;
- if (id) {
- viewer = await ViewerManager.getById({
- id,
- });
- }
+ // let viewer = null;
+ // if (id) {
+ // viewer = await ViewerManager.getById({
+ // id,
+ // });
+ // }
return app.render(req, res, "/_/slate", {
- viewer,
- creator: Serializers.user(creator),
+ viewer: null,
+ creator,
slate,
- mobile,
- mac,
+ isMobile,
+ isMac,
resources: EXTERNAL_RESOURCES,
});
});
server.get("/:username", async (req, res) => {
- let mobile = Window.isMobileBrowser(req.headers["user-agent"]);
- let mac = Window.isMac(req.headers["user-agent"]);
+ let isMobile = Window.isMobileBrowser(req.headers["user-agent"]);
+ let isMac = Window.isMac(req.headers["user-agent"]);
// TODO(jim): Temporary workaround
if (!Validations.userRoute(req.params.username)) {
return handler(req, res, req.url, {
- mobile,
+ isMobile,
resources: EXTERNAL_RESOURCES,
});
}
@@ -315,15 +326,18 @@ app.prepare().then(async () => {
);
}
- let viewer = null;
- if (id) {
- viewer = await ViewerManager.getById({
- id,
- });
- }
+ // let viewer = null;
+ // if (id) {
+ // viewer = await ViewerManager.getById({
+ // id,
+ // });
+ // }
let creator = await Data.getUserByUsername({
- username: req.params.username,
+ username: req.params.username.toLowerCase(),
+ includeFiles: true,
+ sanitize: true,
+ publicOnly: true,
});
if (!creator) {
@@ -334,39 +348,20 @@ app.prepare().then(async () => {
return res.redirect("/404");
}
- const { bucketRoot } = await Utilities.getBucketAPIFromUserToken({
- user: creator,
- });
-
- let library = creator.data.library;
-
- creator = Serializers.user(creator);
-
const slates = await Data.getSlatesByUserId({
- userId: creator.id,
+ ownerId: creator.id,
+ sanitize: true,
+ includeFiles: true,
publicOnly: true,
});
- let publicFileIds = [];
- for (let slate of slates) {
- publicFileIds.push(...slate.data.objects.map((obj) => obj.id));
- }
-
creator.slates = slates;
- if (library && library.length) {
- library[0].children = library[0].children.filter((file) => {
- return file.public || publicFileIds.includes(file.id);
- });
- }
-
- creator.library = library;
-
return app.render(req, res, "/_/profile", {
- viewer,
+ viewer: null,
creator,
- mobile,
- mac,
+ isMobile,
+ isMac,
resources: EXTERNAL_RESOURCES,
exploreSlates,
userBucketCID: bucketRoot?.path,
@@ -374,8 +369,8 @@ app.prepare().then(async () => {
});
server.get("/:username/cid::cid", async (req, res) => {
- let mobile = Window.isMobileBrowser(req.headers["user-agent"]);
- let mac = Window.isMac(req.headers["user-agent"]);
+ let isMobile = Window.isMobileBrowser(req.headers["user-agent"]);
+ let isMac = Window.isMac(req.headers["user-agent"]);
// TODO(jim): Temporary workaround
if (!Validations.userRoute(req.params.username)) {
@@ -394,15 +389,18 @@ app.prepare().then(async () => {
);
}
- let viewer = null;
- if (id) {
- viewer = await ViewerManager.getById({
- id,
- });
- }
+ // let viewer = null;
+ // if (id) {
+ // viewer = await ViewerManager.getById({
+ // id,
+ // });
+ // }
let creator = await Data.getUserByUsername({
- username: req.params.username,
+ username: req.params.username.toLowerCase(),
+ includeFiles: true,
+ sanitize: true,
+ publicOnly: true,
});
if (!creator) {
@@ -413,48 +411,33 @@ app.prepare().then(async () => {
return res.redirect("/404");
}
- let library = creator.data.library;
-
- creator = Serializers.user(creator);
-
const slates = await Data.getSlatesByUserId({
- userId: creator.id,
+ ownerId: creator.id,
+ sanitize: true,
+ includeFiles: true,
publicOnly: true,
});
- let publicFileIds = [];
- for (let slate of slates) {
- publicFileIds.push(...slate.data.objects.map((obj) => obj.id));
- }
-
creator.slates = slates;
- if (library && library.length) {
- library[0].children = library[0].children.filter((file) => {
- return file.public || publicFileIds.includes(file.id);
- });
- }
-
- creator.library = library;
-
return app.render(req, res, "/_/profile", {
- viewer,
- creator: Serializers.user(creator),
- mobile,
- mac,
+ viewer: null,
+ creator,
+ isMobile,
+ isMac,
resources: EXTERNAL_RESOURCES,
cid: req.params.cid,
});
});
server.get("/:username/:slatename", async (req, res) => {
- let mobile = Window.isMobileBrowser(req.headers["user-agent"]);
- let mac = Window.isMac(req.headers["user-agent"]);
+ let isMobile = Window.isMobileBrowser(req.headers["user-agent"]);
+ let isMac = Window.isMac(req.headers["user-agent"]);
// TODO(jim): Temporary workaround
if (!Validations.userRoute(req.params.username)) {
return handler(req, res, req.url, {
- mobile,
+ isMobile,
resources: EXTERNAL_RESOURCES,
});
}
@@ -474,6 +457,8 @@ app.prepare().then(async () => {
const slate = await Data.getSlateByName({
slatename: req.params.slatename,
username: req.params.username,
+ includeFiles: true,
+ sanitize: true,
});
if (!slate) {
@@ -484,11 +469,14 @@ app.prepare().then(async () => {
return res.redirect("/404");
}
- if (!slate.data.public && slate.data.ownerId !== id) {
+ if (!slate.isPublic && slate.ownerId !== id) {
return res.redirect("/403");
}
- const creator = await Data.getUserById({ id: slate.data.ownerId });
+ const creator = await Data.getUserById({
+ id: slate.ownerId,
+ sanitize: true,
+ });
if (!creator) {
return res.redirect("/404");
@@ -502,26 +490,26 @@ app.prepare().then(async () => {
return res.redirect("/403");
}
- let viewer = null;
- if (id) {
- viewer = await ViewerManager.getById({
- id,
- });
- }
+ // let viewer = null;
+ // if (id) {
+ // viewer = await ViewerManager.getById({
+ // id,
+ // });
+ // }
return app.render(req, res, "/_/slate", {
- viewer,
- creator: Serializers.user(creator),
+ viewer: null,
+ creator,
slate,
- mobile,
- mac,
+ isMobile,
+ isMac,
resources: EXTERNAL_RESOURCES,
});
});
server.get("/:username/:slatename/cid::cid", async (req, res) => {
- let mobile = Window.isMobileBrowser(req.headers["user-agent"]);
- let mac = Window.isMac(req.headers["user-agent"]);
+ let isMobile = Window.isMobileBrowser(req.headers["user-agent"]);
+ let isMac = Window.isMac(req.headers["user-agent"]);
// TODO(jim): Temporary workaround
if (!Validations.userRoute(req.params.username)) {
@@ -545,6 +533,8 @@ app.prepare().then(async () => {
const slate = await Data.getSlateByName({
slatename: req.params.slatename,
username: req.params.username,
+ includeFiles: true,
+ sanitize: true,
});
if (!slate) {
@@ -555,11 +545,14 @@ app.prepare().then(async () => {
return res.redirect("/404");
}
- if (!slate.data.public && slate.data.ownerId !== id) {
+ if (!slate.isPublic && slate.ownerId !== id) {
return res.redirect("/403");
}
- const creator = await Data.getUserById({ id: slate.data.ownerId });
+ const creator = await Data.getUserById({
+ id: slate.ownerId,
+ sanitize: true,
+ });
if (!creator) {
return res.redirect("/404");
@@ -573,19 +566,19 @@ app.prepare().then(async () => {
return res.redirect("/403");
}
- let viewer = null;
- if (id) {
- viewer = await ViewerManager.getById({
- id,
- });
- }
+ // let viewer = null;
+ // if (id) {
+ // viewer = await ViewerManager.getById({
+ // id,
+ // });
+ // }
return app.render(req, res, "/_/slate", {
- viewer,
- creator: Serializers.user(creator),
+ viewer: null,
+ creator,
slate,
- mobile,
- mac,
+ isMobile,
+ isMac,
resources: EXTERNAL_RESOURCES,
cid: req.params.cid,
});