mirror of
https://github.com/filecoin-project/slate.git
synced 2024-12-20 07:32:01 +03:00
Merge pull request #398 from filecoin-project/@martinalong/search-v2
Replaced rehydrate with webhooks
This commit is contained in:
commit
71fd7f4ae7
@ -77,6 +77,7 @@ PUBSUB_SECRET=pKLO4lbzdMrhAFKwPo9bnmq03bxQrtu3
|
|||||||
RESOURCE_URI_UPLOAD=http://localhost:4242
|
RESOURCE_URI_UPLOAD=http://localhost:4242
|
||||||
RESOURCE_URI_STORAGE_UPLOAD=http://localhost:4242
|
RESOURCE_URI_STORAGE_UPLOAD=http://localhost:4242
|
||||||
RESOURCE_URI_PUBSUB=ws://localhost:6464
|
RESOURCE_URI_PUBSUB=ws://localhost:6464
|
||||||
|
RESOURCE_URI_SEARCH=http://localhost:1313
|
||||||
```
|
```
|
||||||
|
|
||||||
### Setup pubsub server
|
### Setup pubsub server
|
||||||
|
@ -13,6 +13,12 @@ const DEFAULT_OPTIONS = {
|
|||||||
credentials: "include",
|
credentials: "include",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const CORS_OPTIONS = {
|
||||||
|
method: "POST",
|
||||||
|
headers: REQUEST_HEADERS,
|
||||||
|
credentials: "omit",
|
||||||
|
};
|
||||||
|
|
||||||
const returnJSON = async (route, options) => {
|
const returnJSON = async (route, options) => {
|
||||||
const response = await fetch(route, options);
|
const response = await fetch(route, options);
|
||||||
const json = await response.json();
|
const json = await response.json();
|
||||||
@ -120,8 +126,8 @@ export const search = async (data) => {
|
|||||||
return { decorator: "NO_SERVER_TRIP", data: { results: [] } };
|
return { decorator: "NO_SERVER_TRIP", data: { results: [] } };
|
||||||
}
|
}
|
||||||
|
|
||||||
return await returnJSON(`/api/search/${data.query}`, {
|
return await returnJSON(`http://localhost:1313/${data.query}`, {
|
||||||
...DEFAULT_OPTIONS,
|
...CORS_OPTIONS,
|
||||||
body: JSON.stringify(data),
|
body: JSON.stringify(data),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -37,7 +37,7 @@ export const init = ({ resource = "", viewer, onUpdate }) => {
|
|||||||
}, 30000 + 1000);
|
}, 30000 + 1000);
|
||||||
});
|
});
|
||||||
|
|
||||||
client.addEventListener("message", function(event) {
|
client.addEventListener("message", function (event) {
|
||||||
if (!client) {
|
if (!client) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import * as Actions from "~/common/actions";
|
|||||||
import * as Store from "~/common/store";
|
import * as Store from "~/common/store";
|
||||||
import * as Constants from "~/common/constants";
|
import * as Constants from "~/common/constants";
|
||||||
import * as Credentials from "~/common/credentials";
|
import * as Credentials from "~/common/credentials";
|
||||||
|
import * as Strings from "~/common/strings";
|
||||||
|
|
||||||
import { dispatchCustomEvent } from "~/common/custom-events";
|
import { dispatchCustomEvent } from "~/common/custom-events";
|
||||||
import { encode } from "blurhash";
|
import { encode } from "blurhash";
|
||||||
@ -212,12 +213,7 @@ export const uploadToSlate = async ({ responses, slate }) => {
|
|||||||
skipped = addResponse.skipped;
|
skipped = addResponse.skipped;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let message = `${added || 0} file${added !== 1 ? "s" : ""} uploaded to slate. `;
|
let message = Strings.formatAsUploadMessage(added, skipped, true);
|
||||||
if (skipped) {
|
|
||||||
message += `${skipped || 0} duplicate / existing file${
|
|
||||||
added !== 1 ? "s were" : " was"
|
|
||||||
} skipped.`;
|
|
||||||
}
|
|
||||||
dispatchCustomEvent({
|
dispatchCustomEvent({
|
||||||
name: "create-alert",
|
name: "create-alert",
|
||||||
detail: {
|
detail: {
|
||||||
|
@ -103,6 +103,7 @@ export const error = {
|
|||||||
CREATE_PENDING_ERROR: "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:
|
PROCESS_PENDING_ERROR:
|
||||||
"We ran into an error while updating your uploaded data. Please try again later",
|
"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",
|
||||||
|
|
||||||
//Data CID Status
|
//Data CID Status
|
||||||
NO_CIDS_TO_CHECK: "There are no CIDs to check",
|
NO_CIDS_TO_CHECK: "There are no CIDs to check",
|
||||||
|
@ -87,6 +87,16 @@ export const getCIDFromIPFS = (url) => {
|
|||||||
return cid;
|
return cid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const formatAsUploadMessage = (added, skipped, slate = false) => {
|
||||||
|
let message = `${added || 0} file${added !== 1 ? "s" : ""} uploaded${slate ? " to slate" : ""}. `;
|
||||||
|
if (skipped) {
|
||||||
|
message += `${skipped || 0} duplicate / existing file${
|
||||||
|
added !== 1 ? "s were" : " was"
|
||||||
|
} skipped.`;
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
};
|
||||||
|
|
||||||
export const formatAsFilecoinConversion = (number) => {
|
export const formatAsFilecoinConversion = (number) => {
|
||||||
const filecoinNumber = new FilecoinNumber(`${number}`, "attofil");
|
const filecoinNumber = new FilecoinNumber(`${number}`, "attofil");
|
||||||
//const inAttoFil = filecoinNumber.toAttoFil();
|
//const inAttoFil = filecoinNumber.toAttoFil();
|
||||||
|
@ -68,13 +68,8 @@ const STYLES_MESSAGE = css`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_TEXT = css`
|
const STYLES_TEXT = css`
|
||||||
border-bottom: 1px solid ${Constants.system.white};
|
|
||||||
max-width: ${Constants.sizes.mobile}px;
|
max-width: ${Constants.sizes.mobile}px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
@supports ((-webkit-backdrop-filter: blur(25px)) or (backdrop-filter: blur(25px))) {
|
|
||||||
border-bottom: 1px solid ${Constants.system.brand};
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_MESSAGE_BOX = css`
|
const STYLES_MESSAGE_BOX = css`
|
||||||
|
@ -180,9 +180,10 @@ export default class ApplicationPage extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//make this a function that can handle different types of inputs and updates state accordingly (rather than ahving a bunch of different functions for each type)
|
||||||
_handleUpdateViewer = (newViewerState) => {
|
_handleUpdateViewer = (newViewerState) => {
|
||||||
|
console.log("update viewer");
|
||||||
console.log({ newViewerState });
|
console.log({ newViewerState });
|
||||||
|
|
||||||
if (this.state.viewer && newViewerState.id && newViewerState.id === this.state.viewer.id) {
|
if (this.state.viewer && newViewerState.id && newViewerState.id === this.state.viewer.id) {
|
||||||
this.setState({
|
this.setState({
|
||||||
viewer: { ...this.state.viewer, ...newViewerState, type: "VIEWER" },
|
viewer: { ...this.state.viewer, ...newViewerState, type: "VIEWER" },
|
||||||
@ -425,39 +426,11 @@ export default class ApplicationPage extends React.Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(jim): Remove this once the viewer is being broadcasted for
|
this.setState({ sidebar: null });
|
||||||
// this case.
|
|
||||||
await this.rehydrate({ resetFiles: true });
|
|
||||||
|
|
||||||
// //NOTE(martina): to update the carousel to include the new file if you're on the data view page
|
|
||||||
// dispatchCustomEvent({
|
|
||||||
// name: "remote-update-carousel",
|
|
||||||
// detail: {},
|
|
||||||
// });
|
|
||||||
|
|
||||||
//NOTE(martina): to update the slate carousel to include the new file if you're on a slate page
|
|
||||||
// const navigation = NavigationData.generate(this.state.viewer);
|
|
||||||
// const next = this.state.history[this.state.currentIndex];
|
|
||||||
// const current = NavigationData.getCurrentById(navigation, next.id);
|
|
||||||
// if (
|
|
||||||
// current.target &&
|
|
||||||
// current.target.slateId &&
|
|
||||||
// this.state.viewer.slates.map((slate) => slate.id).includes(current.target.slateId)
|
|
||||||
// ) {
|
|
||||||
// dispatchCustomEvent({
|
|
||||||
// name: "remote-update-slate-screen",
|
|
||||||
// detail: {},
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (!slate) {
|
if (!slate) {
|
||||||
const { added, skipped } = processResponse.data;
|
const { added, skipped } = processResponse.data;
|
||||||
let message = `${added || 0} file${added !== 1 ? "s" : ""} uploaded. `;
|
let message = Strings.formatAsUploadMessage(added, skipped);
|
||||||
if (skipped) {
|
|
||||||
message += `${skipped || 0} duplicate / existing file${
|
|
||||||
added !== 1 ? "s were" : " was"
|
|
||||||
} skipped.`;
|
|
||||||
}
|
|
||||||
dispatchCustomEvent({
|
dispatchCustomEvent({
|
||||||
name: "create-alert",
|
name: "create-alert",
|
||||||
detail: {
|
detail: {
|
||||||
@ -527,6 +500,7 @@ export default class ApplicationPage extends React.Component {
|
|||||||
|
|
||||||
_handleSidebarLoading = (sidebarLoading) => this.setState({ sidebarLoading });
|
_handleSidebarLoading = (sidebarLoading) => this.setState({ sidebarLoading });
|
||||||
|
|
||||||
|
//change the naem to hydrate. and use this only upon initial sign in (should be the only time you need it)
|
||||||
rehydrate = async (options) => {
|
rehydrate = async (options) => {
|
||||||
const response = await Actions.hydrateAuthenticatedUser();
|
const response = await Actions.hydrateAuthenticatedUser();
|
||||||
|
|
||||||
@ -587,10 +561,6 @@ export default class ApplicationPage extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(jim): Remove this once the viewer is being broadcasted for
|
|
||||||
// this case.
|
|
||||||
await this.rehydrate();
|
|
||||||
|
|
||||||
this._handleDismissSidebar();
|
this._handleDismissSidebar();
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
@ -666,8 +636,6 @@ export default class ApplicationPage extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(jim): Remove this once the viewer is being broadcasted for
|
|
||||||
// this case.
|
|
||||||
await this.rehydrate();
|
await this.rehydrate();
|
||||||
|
|
||||||
let wsclient = Websockets.getClient();
|
let wsclient = Websockets.getClient();
|
||||||
@ -893,7 +861,6 @@ export default class ApplicationPage extends React.Component {
|
|||||||
</WebsitePrototypeWrapper>
|
</WebsitePrototypeWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(jim): Authenticated.
|
// NOTE(jim): Authenticated.
|
||||||
const navigation = NavigationData.generate(this.state.viewer);
|
const navigation = NavigationData.generate(this.state.viewer);
|
||||||
const next = this.state.history[this.state.currentIndex];
|
const next = this.state.history[this.state.currentIndex];
|
||||||
@ -924,7 +891,6 @@ export default class ApplicationPage extends React.Component {
|
|||||||
currentIndex={this.state.currentIndex}
|
currentIndex={this.state.currentIndex}
|
||||||
history={this.state.history}
|
history={this.state.history}
|
||||||
onAction={this._handleAction}
|
onAction={this._handleAction}
|
||||||
onRehydrate={this.rehydrate}
|
|
||||||
onBack={this._handleBack}
|
onBack={this._handleBack}
|
||||||
onForward={this._handleForward}
|
onForward={this._handleForward}
|
||||||
onSignOut={this._handleSignOut}
|
onSignOut={this._handleSignOut}
|
||||||
@ -944,7 +910,6 @@ export default class ApplicationPage extends React.Component {
|
|||||||
onUpload: this._handleUploadFiles,
|
onUpload: this._handleUploadFiles,
|
||||||
onBack: this._handleBack,
|
onBack: this._handleBack,
|
||||||
onForward: this._handleForward,
|
onForward: this._handleForward,
|
||||||
onRehydrate: this.rehydrate,
|
|
||||||
sceneId: current.target.id,
|
sceneId: current.target.id,
|
||||||
mobile: this.state.mobile,
|
mobile: this.state.mobile,
|
||||||
resources: this.props.resources,
|
resources: this.props.resources,
|
||||||
@ -967,7 +932,6 @@ export default class ApplicationPage extends React.Component {
|
|||||||
onUpload: this._handleUploadFiles,
|
onUpload: this._handleUploadFiles,
|
||||||
onSidebarLoading: this._handleSidebarLoading,
|
onSidebarLoading: this._handleSidebarLoading,
|
||||||
onAction: this._handleAction,
|
onAction: this._handleAction,
|
||||||
onRehydrate: this.rehydrate,
|
|
||||||
resources: this.props.resources,
|
resources: this.props.resources,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1002,7 +966,6 @@ export default class ApplicationPage extends React.Component {
|
|||||||
? current.target
|
? current.target
|
||||||
: this.state.data //NOTE(martina): for slates that are not your own
|
: this.state.data //NOTE(martina): for slates that are not your own
|
||||||
}
|
}
|
||||||
onRehydrate={this.rehydrate}
|
|
||||||
slates={this.state.viewer.slates}
|
slates={this.state.viewer.slates}
|
||||||
onAction={this._handleAction}
|
onAction={this._handleAction}
|
||||||
mobile={this.props.mobile}
|
mobile={this.props.mobile}
|
||||||
|
@ -140,14 +140,7 @@ export default class ApplicationHeader extends React.Component {
|
|||||||
_handleCreateSearch = (e) => {
|
_handleCreateSearch = (e) => {
|
||||||
dispatchCustomEvent({
|
dispatchCustomEvent({
|
||||||
name: "create-modal",
|
name: "create-modal",
|
||||||
detail: { modal: <SearchModal onAction={this.props.onAction} /> },
|
detail: { modal: <SearchModal viewer={this.props.viewer} onAction={this.props.onAction} /> },
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
_handleRehydrate = (e) => {
|
|
||||||
this.setState({ isRefreshing: true }, async () => {
|
|
||||||
await this.props.onRehydrate();
|
|
||||||
this.setState({ isRefreshing: false });
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -193,16 +186,6 @@ export default class ApplicationHeader extends React.Component {
|
|||||||
<SVG.NavigationArrow height="24px" />
|
<SVG.NavigationArrow height="24px" />
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span css={STYLES_MOBILE_HIDDEN}>
|
|
||||||
<span
|
|
||||||
css={this.state.isRefreshing ? STYLES_ROTATION : STYLES_STATIC}
|
|
||||||
style={{ marginLeft: 24 }}
|
|
||||||
>
|
|
||||||
<span css={STYLES_ICON_ELEMENT} onClick={this._handleRehydrate}>
|
|
||||||
<SVG.Refresh height="20px" />
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<span css={STYLES_MOBILE_HIDDEN}>
|
<span css={STYLES_MOBILE_HIDDEN}>
|
||||||
<span
|
<span
|
||||||
css={STYLES_ICON_ELEMENT}
|
css={STYLES_ICON_ELEMENT}
|
||||||
|
@ -278,7 +278,6 @@ export default class CarouselSidebarSlate extends React.Component {
|
|||||||
selected: { ...this.state.selected, [slate.id]: true },
|
selected: { ...this.state.selected, [slate.id]: true },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.props.onRehydrate();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_handleDownload = () => {
|
_handleDownload = () => {
|
||||||
@ -326,7 +325,13 @@ export default class CarouselSidebarSlate extends React.Component {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.props.onRehydrate();
|
let message = Strings.formatAsUploadMessage(response.data.added, response.data.skipped);
|
||||||
|
dispatchCustomEvent({
|
||||||
|
name: "create-alert",
|
||||||
|
detail: {
|
||||||
|
alert: { message, status: !response.data.added ? null : "INFO" },
|
||||||
|
},
|
||||||
|
});
|
||||||
this.setState({ loading: false });
|
this.setState({ loading: false });
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -363,8 +368,8 @@ export default class CarouselSidebarSlate extends React.Component {
|
|||||||
this.setState({ loading: false });
|
this.setState({ loading: false });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await this.props.onRehydrate();
|
|
||||||
this.setState({ loading: false });
|
this.setState({ loading: false });
|
||||||
|
console.log("got here to end of handle delete");
|
||||||
};
|
};
|
||||||
|
|
||||||
_toggleAccordion = (tab) => {
|
_toggleAccordion = (tab) => {
|
||||||
|
@ -243,7 +243,6 @@ export default class DataView extends React.Component {
|
|||||||
if (windowBottom >= docHeight - 600) {
|
if (windowBottom >= docHeight - 600) {
|
||||||
this.setState({ viewLimit: this.state.viewLimit + 30 });
|
this.setState({ viewLimit: this.state.viewLimit + 30 });
|
||||||
}
|
}
|
||||||
console.log(e);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_handleCheckScroll = Window.debounce(this._handleScroll, 200);
|
_handleCheckScroll = Window.debounce(this._handleScroll, 200);
|
||||||
@ -300,7 +299,6 @@ export default class DataView extends React.Component {
|
|||||||
dispatchCustomEvent({ name: "state-global-carousel-loading", detail: { loading: false } });
|
dispatchCustomEvent({ name: "state-global-carousel-loading", detail: { loading: false } });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await this.props.onRehydrate();
|
|
||||||
this._handleLoading({ cids });
|
this._handleLoading({ cids });
|
||||||
this.setState({ checked: {} });
|
this.setState({ checked: {} });
|
||||||
dispatchCustomEvent({
|
dispatchCustomEvent({
|
||||||
@ -357,12 +355,7 @@ export default class DataView extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { added, skipped } = addResponse;
|
const { added, skipped } = addResponse;
|
||||||
let message = `${added || 0} file${added !== 1 ? "s" : ""} uploaded. `;
|
let message = Strings.formatAsUploadMessage(added, skipped, true);
|
||||||
if (skipped) {
|
|
||||||
message += `${skipped || 0} duplicate / existing file${
|
|
||||||
added !== 1 ? "s were" : " was"
|
|
||||||
} skipped.`;
|
|
||||||
}
|
|
||||||
dispatchCustomEvent({
|
dispatchCustomEvent({
|
||||||
name: "create-alert",
|
name: "create-alert",
|
||||||
detail: {
|
detail: {
|
||||||
@ -370,7 +363,6 @@ export default class DataView extends React.Component {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.props.onRehydrate();
|
|
||||||
System.dispatchCustomEvent({
|
System.dispatchCustomEvent({
|
||||||
name: "state-global-carousel-loading",
|
name: "state-global-carousel-loading",
|
||||||
detail: { loading: false },
|
detail: { loading: false },
|
||||||
@ -422,8 +414,6 @@ export default class DataView extends React.Component {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.props.onRehydrate();
|
|
||||||
|
|
||||||
System.dispatchCustomEvent({
|
System.dispatchCustomEvent({
|
||||||
name: "state-global-carousel-loading",
|
name: "state-global-carousel-loading",
|
||||||
detail: { loading: false },
|
detail: { loading: false },
|
||||||
|
@ -70,10 +70,7 @@ const UserEntry = ({ item }) => {
|
|||||||
return (
|
return (
|
||||||
<div css={STYLES_ENTRY}>
|
<div css={STYLES_ENTRY}>
|
||||||
<div css={STYLES_USER_ENTRY_CONTAINER}>
|
<div css={STYLES_USER_ENTRY_CONTAINER}>
|
||||||
<div
|
<div style={{ backgroundImage: `url(${item.data.photo})` }} css={STYLES_PROFILE_IMAGE} />
|
||||||
style={{ backgroundImage: `url(${item.data.photo})` }}
|
|
||||||
css={STYLES_PROFILE_IMAGE}
|
|
||||||
/>
|
|
||||||
{item.data.name ? <div css={STYLES_TITLE}>{item.data.name}</div> : null}
|
{item.data.name ? <div css={STYLES_TITLE}>{item.data.name}</div> : null}
|
||||||
<div css={STYLES_TITLE}>@{item.username}</div>
|
<div css={STYLES_TITLE}>@{item.username}</div>
|
||||||
</div>
|
</div>
|
||||||
@ -132,18 +129,14 @@ const FileEntry = ({ item }) => {
|
|||||||
<SVG.Folder height="16px" />
|
<SVG.Folder height="16px" />
|
||||||
</div>
|
</div>
|
||||||
<div css={STYLES_TITLE}>
|
<div css={STYLES_TITLE}>
|
||||||
{item.data.file.title || item.data.file.name}
|
{item.data.file.title || item.data.file.name || item.data.file.file}
|
||||||
</div>
|
</div>
|
||||||
{item.data.slate.owner && item.data.slate.owner.username ? (
|
{item.data.slate && item.data.slate.owner && item.data.slate.owner.username ? (
|
||||||
<div css={STYLES_TITLE}>@{item.data.slate.owner.username}</div>
|
<div css={STYLES_TITLE}>@{item.data.slate.owner.username}</div>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
<div css={STYLES_SLATE_IMAGES_CONTAINER}>
|
<div css={STYLES_SLATE_IMAGES_CONTAINER}>
|
||||||
<SlatePreviewRow
|
<SlatePreviewRow numItems={1} slate={{ data: { objects: [item.data.file] } }} small />
|
||||||
numItems={1}
|
|
||||||
slate={{ data: { objects: [item.data.file] } }}
|
|
||||||
small
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -154,10 +147,12 @@ export class SearchModal extends React.Component {
|
|||||||
loading: true,
|
loading: true,
|
||||||
results: [],
|
results: [],
|
||||||
inputValue: "",
|
inputValue: "",
|
||||||
|
filters: { slates: true },
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount = async () => {
|
componentDidMount = async () => {
|
||||||
await this.fillDirectory();
|
await this.fillDirectory();
|
||||||
|
// await this.fillPersonalDirectory();
|
||||||
this.setState({ loading: false });
|
this.setState({ loading: false });
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -165,19 +160,9 @@ export class SearchModal extends React.Component {
|
|||||||
const response = await Actions.getNetworkDirectory();
|
const response = await Actions.getNetworkDirectory();
|
||||||
this.miniSearch = new MiniSearch({
|
this.miniSearch = new MiniSearch({
|
||||||
fields: ["slatename", "data.name", "username", "filename"],
|
fields: ["slatename", "data.name", "username", "filename"],
|
||||||
storeFields: [
|
storeFields: ["type", "slatename", "username", "data", "id", "slates", "owner"],
|
||||||
"type",
|
|
||||||
"slatename",
|
|
||||||
"username",
|
|
||||||
"data",
|
|
||||||
"id",
|
|
||||||
"slates",
|
|
||||||
"owner",
|
|
||||||
],
|
|
||||||
extractField: (entry, fieldName) => {
|
extractField: (entry, fieldName) => {
|
||||||
return fieldName
|
return fieldName.split(".").reduce((doc, key) => doc && doc[key], entry);
|
||||||
.split(".")
|
|
||||||
.reduce((doc, key) => doc && doc[key], entry);
|
|
||||||
},
|
},
|
||||||
searchOptions: {
|
searchOptions: {
|
||||||
fuzzy: 0.15,
|
fuzzy: 0.15,
|
||||||
@ -199,16 +184,72 @@ export class SearchModal extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.users = response.data.users;
|
|
||||||
this.slates = response.data.slates;
|
|
||||||
this.miniSearch.addAll(response.data.users);
|
this.miniSearch.addAll(response.data.users);
|
||||||
this.miniSearch.addAll(response.data.slates);
|
this.miniSearch.addAll(response.data.slates);
|
||||||
this.miniSearch.addAll(files);
|
this.miniSearch.addAll(files);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fillPersonalDirectory = () => {
|
||||||
|
this.personalSearch = new MiniSearch({
|
||||||
|
fields: ["slatename", "data.name", "username", "filename"],
|
||||||
|
storeFields: ["type", "slatename", "username", "data", "id", "slates", "owner"],
|
||||||
|
extractField: (entry, fieldName) => {
|
||||||
|
return fieldName.split(".").reduce((doc, key) => doc && doc[key], entry);
|
||||||
|
},
|
||||||
|
searchOptions: {
|
||||||
|
fuzzy: 0.15,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
let files = this.props.viewer.library[0].children.map((file, i) => {
|
||||||
|
return {
|
||||||
|
type: "DATA_FILE",
|
||||||
|
id: file.id,
|
||||||
|
filename: file.name || file.file,
|
||||||
|
data: {
|
||||||
|
file: {
|
||||||
|
...file,
|
||||||
|
url: `${Constants.gateways.ipfs}/${file.cid || file.ipfs.replace("/ipfs/", "")}`,
|
||||||
|
},
|
||||||
|
index: i,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
let slates = this.props.viewer.slates.map((slate) => {
|
||||||
|
return { ...slate, type: "SLATE", owner: this.props.viewer };
|
||||||
|
});
|
||||||
|
this.personalSearch.addAll(slates);
|
||||||
|
let userIds = [];
|
||||||
|
this.personalSearch.addAll(this.props.viewer.pendingTrusted.map((trust) => trust.owner));
|
||||||
|
userIds.push(...this.props.viewer.pendingTrusted.map((trust) => trust.owner.id));
|
||||||
|
this.personalSearch.addAll(
|
||||||
|
this.props.viewer.trusted
|
||||||
|
.filter((trust) => !userIds.includes(trust.user.id))
|
||||||
|
.map((trust) => trust.user)
|
||||||
|
);
|
||||||
|
userIds.push(...this.props.viewer.trusted.map((trust) => trust.user.id));
|
||||||
|
this.personalSearch.addAll(
|
||||||
|
this.props.viewer.subscriptions
|
||||||
|
.filter((sub) => sub.target_user_id && !userIds.includes(sub.user.id))
|
||||||
|
.map((sub) => sub.user)
|
||||||
|
);
|
||||||
|
this.personalSearch.addAll(files);
|
||||||
|
};
|
||||||
|
|
||||||
_handleChange = (e) => {
|
_handleChange = (e) => {
|
||||||
this.setState({ inputValue: e.target.value });
|
this.setState({ inputValue: e.target.value });
|
||||||
|
//interpret the thing with handleInterpret (and change shownValue accordingly)
|
||||||
|
};
|
||||||
|
|
||||||
|
//converts input to search filter options
|
||||||
|
_handleInterpret = (query) => {
|
||||||
|
if (query.contains("files:")) {
|
||||||
|
} else if (query.contains("users:")) {
|
||||||
|
} else if (query.contains("slates:")) {
|
||||||
|
} else if (query.contains("tags:")) {
|
||||||
|
} else if (query.contains("#")) {
|
||||||
|
} else if (query.contains("@")) {
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_handleSearch = () => {
|
_handleSearch = () => {
|
||||||
@ -230,6 +271,63 @@ export class SearchModal extends React.Component {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// _handleSearch = async () => {
|
||||||
|
// if (this.state.loading) return;
|
||||||
|
|
||||||
|
// if (this.state.filters["my"]) {
|
||||||
|
// let miniSearch = this.personalSearch;
|
||||||
|
// let filter;
|
||||||
|
// if (this.state.filters["files"]) {
|
||||||
|
// filter = {
|
||||||
|
// filter: (result) => {
|
||||||
|
// return result.type === "FILE" || result.type === "DATA_FILE";
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
// } else if (this.state.filters["users"]) {
|
||||||
|
// filter = {
|
||||||
|
// filter: (result) => result.type === "USER",
|
||||||
|
// };
|
||||||
|
// } else if (this.state.filters["slates"]) {
|
||||||
|
// filter = {
|
||||||
|
// filter: (result) => result.type === "SLATE",
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// let searchResults;
|
||||||
|
// if (filter) {
|
||||||
|
// searchResults = miniSearch.search(this.state.inputValue, filter);
|
||||||
|
// } else {
|
||||||
|
// searchResults = miniSearch.search(this.state.inputValue);
|
||||||
|
// }
|
||||||
|
// let ids = new Set();
|
||||||
|
// for (let result of searchResults) {
|
||||||
|
// ids.add(result.id);
|
||||||
|
// }
|
||||||
|
// let autofill = miniSearch.autoSuggest(this.state.inputValue);
|
||||||
|
// for (let i = 0; i < autofill.length; i++) {
|
||||||
|
// let result;
|
||||||
|
// if (Object.keys(this.state.filter).length) {
|
||||||
|
// result = miniSearch.search(autofill[i].suggestion, this.state.filter);
|
||||||
|
// } else {
|
||||||
|
// result = miniSearch.search(autofill[i].suggestion);
|
||||||
|
// }
|
||||||
|
// if (result && result.length) {
|
||||||
|
// result = result[0];
|
||||||
|
// if (!ids.has(result.id)) {
|
||||||
|
// ids.add(result.id);
|
||||||
|
// searchResults.push(result);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// this.setState({ results: searchResults });
|
||||||
|
// } else {
|
||||||
|
// const results = await Actions.search({
|
||||||
|
// query: this.state.inputValue,
|
||||||
|
// filter: this.state.filters,
|
||||||
|
// });
|
||||||
|
// this.setState({ results: results.data.results });
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
_handleSelect = async (value) => {
|
_handleSelect = async (value) => {
|
||||||
if (value.type === "SLATE") {
|
if (value.type === "SLATE") {
|
||||||
this.props.onAction({
|
this.props.onAction({
|
||||||
@ -245,6 +343,16 @@ export class SearchModal extends React.Component {
|
|||||||
data: value.data,
|
data: value.data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (value.type === "DATA_FILE") {
|
||||||
|
await this.props.onAction({
|
||||||
|
type: "NAVIGATE",
|
||||||
|
value: "data",
|
||||||
|
});
|
||||||
|
dispatchCustomEvent({
|
||||||
|
name: "slate-global-open-carousel",
|
||||||
|
detail: { index: value.data.data.index },
|
||||||
|
});
|
||||||
|
}
|
||||||
if (value.type === "FILE") {
|
if (value.type === "FILE") {
|
||||||
await this.props.onAction({
|
await this.props.onAction({
|
||||||
type: "NAVIGATE",
|
type: "NAVIGATE",
|
||||||
@ -281,10 +389,10 @@ export class SearchModal extends React.Component {
|
|||||||
},
|
},
|
||||||
component: <SlateEntry item={item} />,
|
component: <SlateEntry item={item} />,
|
||||||
});
|
});
|
||||||
} else if (item.type === "FILE") {
|
} else if (item.type === "FILE" || item.type === "DATA_FILE") {
|
||||||
results.push({
|
results.push({
|
||||||
value: {
|
value: {
|
||||||
type: "FILE",
|
type: item.type,
|
||||||
data: item,
|
data: item,
|
||||||
},
|
},
|
||||||
component: <FileEntry item={item} />,
|
component: <FileEntry item={item} />,
|
||||||
@ -301,7 +409,7 @@ export class SearchModal extends React.Component {
|
|||||||
onSelect={this._handleSelect}
|
onSelect={this._handleSelect}
|
||||||
onChange={this._handleChange}
|
onChange={this._handleChange}
|
||||||
onSearch={this._handleSearch}
|
onSearch={this._handleSearch}
|
||||||
inputValue={this.state.inputValue}
|
inputValue={this.state.shownValue}
|
||||||
style={STYLES_SEARCH_DROPDOWN}
|
style={STYLES_SEARCH_DROPDOWN}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -89,12 +89,7 @@ export default class SidebarAddFileToSlate extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { added, skipped } = addResponse;
|
const { added, skipped } = addResponse;
|
||||||
let message = `${added || 0} file${added !== 1 ? "s" : ""} uploaded. `;
|
let message = Strings.formatAsUploadMessage(added, skipped, true);
|
||||||
if (skipped) {
|
|
||||||
message += `${skipped || 0} duplicate / existing file${
|
|
||||||
added !== 1 ? "s were" : " was"
|
|
||||||
} skipped.`;
|
|
||||||
}
|
|
||||||
dispatchCustomEvent({
|
dispatchCustomEvent({
|
||||||
name: "create-alert",
|
name: "create-alert",
|
||||||
detail: {
|
detail: {
|
||||||
@ -102,7 +97,6 @@ export default class SidebarAddFileToSlate extends React.Component {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
await this.props.onRehydrate();
|
|
||||||
this.props.onCancel();
|
this.props.onCancel();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -117,12 +117,7 @@ export default class SidebarCreateSlate extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { added, skipped } = addResponse;
|
const { added, skipped } = addResponse;
|
||||||
let message = `${added || 0} file${added !== 1 ? "s" : ""} uploaded. `;
|
let message = Strings.formatAsUploadMessage(added, skipped, true);
|
||||||
if (skipped) {
|
|
||||||
message += `${skipped || 0} duplicate / existing file${
|
|
||||||
added !== 1 ? "s were" : " was"
|
|
||||||
} skipped.`;
|
|
||||||
}
|
|
||||||
if (message) {
|
if (message) {
|
||||||
dispatchCustomEvent({
|
dispatchCustomEvent({
|
||||||
name: "create-alert",
|
name: "create-alert",
|
||||||
@ -131,8 +126,6 @@ export default class SidebarCreateSlate extends React.Component {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.props.onRehydrate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ loading: false });
|
this.setState({ loading: false });
|
||||||
|
@ -65,15 +65,13 @@ export default class SidebarSingleSlateSettings extends React.Component {
|
|||||||
body: this.state.body,
|
body: this.state.body,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
console.log(response);
|
|
||||||
|
|
||||||
if (!response) {
|
if (!response) {
|
||||||
dispatchCustomEvent({
|
dispatchCustomEvent({
|
||||||
name: "create-alert",
|
name: "create-alert",
|
||||||
detail: {
|
detail: {
|
||||||
alert: {
|
alert: {
|
||||||
message:
|
message: "We're having trouble connecting right now. Please try again later",
|
||||||
"We're having trouble connecting right now. Please try again later",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -87,8 +85,7 @@ export default class SidebarSingleSlateSettings extends React.Component {
|
|||||||
});
|
});
|
||||||
return this.setState({ loading: false });
|
return this.setState({ loading: false });
|
||||||
}
|
}
|
||||||
|
this.props.onCancel();
|
||||||
await this.props.onSubmit({});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_handleCancel = () => {
|
_handleCancel = () => {
|
||||||
@ -103,9 +100,7 @@ export default class SidebarSingleSlateSettings extends React.Component {
|
|||||||
this.setState({ loading: true });
|
this.setState({ loading: true });
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!window.confirm(
|
!window.confirm("Are you sure you want to delete this Slate? This action is irreversible.")
|
||||||
"Are you sure you want to delete this Slate? This action is irreversible."
|
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
return this.setState({ loading: false });
|
return this.setState({ loading: false });
|
||||||
}
|
}
|
||||||
@ -119,8 +114,7 @@ export default class SidebarSingleSlateSettings extends React.Component {
|
|||||||
name: "create-alert",
|
name: "create-alert",
|
||||||
detail: {
|
detail: {
|
||||||
alert: {
|
alert: {
|
||||||
message:
|
message: "We're having trouble connecting right now. Please try again later",
|
||||||
"We're having trouble connecting right now. Please try again later",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -139,8 +133,6 @@ export default class SidebarSingleSlateSettings extends React.Component {
|
|||||||
type: "NAVIGATE",
|
type: "NAVIGATE",
|
||||||
value: "V1_NAVIGATION_SLATES",
|
value: "V1_NAVIGATION_SLATES",
|
||||||
});
|
});
|
||||||
|
|
||||||
return await this.props.onRehydrate();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -182,19 +174,14 @@ export default class SidebarSingleSlateSettings extends React.Component {
|
|||||||
marginTop: 12,
|
marginTop: 12,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Changing the slatename will change your public slate URL. Your slate
|
Changing the slatename will change your public slate URL. Your slate URL is:{" "}
|
||||||
URL is:{" "}
|
|
||||||
</System.P>
|
</System.P>
|
||||||
<System.P
|
<System.P
|
||||||
style={{
|
style={{
|
||||||
marginTop: 12,
|
marginTop: 12,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<a
|
<a href={url} target="_blank" style={{ color: Constants.system.brand }}>
|
||||||
href={url}
|
|
||||||
target="_blank"
|
|
||||||
style={{ color: Constants.system.brand }}
|
|
||||||
>
|
|
||||||
https://slate.host{url}
|
https://slate.host{url}
|
||||||
</a>
|
</a>
|
||||||
</System.P>
|
</System.P>
|
||||||
@ -236,11 +223,7 @@ export default class SidebarSingleSlateSettings extends React.Component {
|
|||||||
</System.P>
|
</System.P>
|
||||||
|
|
||||||
<div css={STYLES_IMAGE_BOX} style={{ marginTop: 24 }}>
|
<div css={STYLES_IMAGE_BOX} style={{ marginTop: 24 }}>
|
||||||
<img
|
<img src={preview} alt="" style={{ maxWidth: "368px", maxHeight: "368px" }} />
|
||||||
src={preview}
|
|
||||||
alt=""
|
|
||||||
style={{ maxWidth: "368px", maxHeight: "368px" }}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -252,20 +235,12 @@ export default class SidebarSingleSlateSettings extends React.Component {
|
|||||||
? "Public. Anyone can search for and view this slate."
|
? "Public. Anyone can search for and view this slate."
|
||||||
: "Private. Only you can view this slate."}
|
: "Private. Only you can view this slate."}
|
||||||
</System.P>
|
</System.P>
|
||||||
<System.Toggle
|
<System.Toggle name="public" onChange={this._handleChange} active={this.state.public} />
|
||||||
name="public"
|
|
||||||
onChange={this._handleChange}
|
|
||||||
active={this.state.public}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ marginTop: 40 }}>
|
<div style={{ marginTop: 40 }}>
|
||||||
<System.ButtonPrimary
|
<System.ButtonPrimary full onClick={this._handleSubmit} loading={this.state.loading}>
|
||||||
full
|
|
||||||
onClick={this._handleSubmit}
|
|
||||||
loading={this.state.loading}
|
|
||||||
>
|
|
||||||
Save changes
|
Save changes
|
||||||
</System.ButtonPrimary>
|
</System.ButtonPrimary>
|
||||||
|
|
||||||
@ -284,11 +259,7 @@ export default class SidebarSingleSlateSettings extends React.Component {
|
|||||||
|
|
||||||
{!this.state.loading ? (
|
{!this.state.loading ? (
|
||||||
<div style={{ marginTop: 48 }}>
|
<div style={{ marginTop: 48 }}>
|
||||||
<System.ButtonWarning
|
<System.ButtonWarning full onClick={this._handleDelete} style={{ overflow: "hidden" }}>
|
||||||
full
|
|
||||||
onClick={this._handleDelete}
|
|
||||||
style={{ overflow: "hidden" }}
|
|
||||||
>
|
|
||||||
Delete{" "}
|
Delete{" "}
|
||||||
{this.props.current.data && this.props.current.data.name
|
{this.props.current.data && this.props.current.data.name
|
||||||
? this.props.current.data.name
|
? this.props.current.data.name
|
||||||
|
@ -302,7 +302,6 @@ export class GlobalCarousel extends React.Component {
|
|||||||
detail: { alert: { decorator: response.decorator } },
|
detail: { alert: { decorator: response.decorator } },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.props.onRehydrate();
|
|
||||||
this.setState({ loading: false, saving: false });
|
this.setState({ loading: false, saving: false });
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -347,7 +346,7 @@ export class GlobalCarousel extends React.Component {
|
|||||||
this.state.index < this.props.viewer.library[0].children.length
|
this.state.index < this.props.viewer.library[0].children.length
|
||||||
) {
|
) {
|
||||||
data = this.props.viewer.library[0].children[this.state.index];
|
data = this.props.viewer.library[0].children[this.state.index];
|
||||||
data.url = `${Constants.gateways.ipfs}/${data.cid || Strings.getCIDFromIPFS(data.ipfs)}`;
|
data.url = `${Constants.gateways.ipfs}/${data.cid || data.ipfs.replace("/ipfs/", "")}`;
|
||||||
}
|
}
|
||||||
if (!data) {
|
if (!data) {
|
||||||
this._handleClose();
|
this._handleClose();
|
||||||
@ -398,7 +397,6 @@ export class GlobalCarousel extends React.Component {
|
|||||||
saving={this.state.saving}
|
saving={this.state.saving}
|
||||||
loading={this.state.loading}
|
loading={this.state.loading}
|
||||||
slates={this.props.slates}
|
slates={this.props.slates}
|
||||||
onRehydrate={this.props.onRehydrate}
|
|
||||||
onAction={this.props.onAction}
|
onAction={this.props.onAction}
|
||||||
data={data}
|
data={data}
|
||||||
cid={data.cid}
|
cid={data.cid}
|
||||||
@ -411,7 +409,6 @@ export class GlobalCarousel extends React.Component {
|
|||||||
loading={this.state.loading}
|
loading={this.state.loading}
|
||||||
slates={this.props.slates}
|
slates={this.props.slates}
|
||||||
onClose={this._handleClose}
|
onClose={this._handleClose}
|
||||||
onRehydrate={this.props.onRehydrate}
|
|
||||||
onAction={this.props.onAction}
|
onAction={this.props.onAction}
|
||||||
data={data}
|
data={data}
|
||||||
external={this.props.external}
|
external={this.props.external}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import * as Data from "~/node_common/data";
|
import * as Data from "~/node_common/data";
|
||||||
import * as LibraryManager from "~/node_common/managers/library";
|
|
||||||
|
|
||||||
import { runQuery } from "~/node_common/data/utilities";
|
import { runQuery } from "~/node_common/data/utilities";
|
||||||
|
|
||||||
@ -7,32 +6,9 @@ export default async ({ owner_user_id }) => {
|
|||||||
return await runQuery({
|
return await runQuery({
|
||||||
label: "REMOVE_PENDING_DATA_FOR_USER",
|
label: "REMOVE_PENDING_DATA_FOR_USER",
|
||||||
queryFn: async (DB) => {
|
queryFn: async (DB) => {
|
||||||
const user = await Data.getUserById({
|
const pending = await DB.from("pending").where({ owner_user_id }).returning("*").del();
|
||||||
id: owner_user_id,
|
|
||||||
});
|
|
||||||
const pending = await DB.from("pending")
|
|
||||||
.where({ owner_user_id })
|
|
||||||
.returning("*")
|
|
||||||
.del();
|
|
||||||
let cids = [];
|
|
||||||
let noRepeats = [];
|
|
||||||
for (let entry of pending) {
|
|
||||||
if (cids.includes(entry.data.ipfs)) continue;
|
|
||||||
cids.push(entry.data.ipfs);
|
|
||||||
noRepeats.push(entry.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
const { updatedUserDataFields, added, skipped } = LibraryManager.addData({
|
return pending;
|
||||||
user,
|
|
||||||
files: noRepeats,
|
|
||||||
});
|
|
||||||
|
|
||||||
await Data.updateUserById({
|
|
||||||
id: user.id,
|
|
||||||
data: updatedUserDataFields,
|
|
||||||
});
|
|
||||||
|
|
||||||
return { added, skipped };
|
|
||||||
},
|
},
|
||||||
errorFn: async (e) => {
|
errorFn: async (e) => {
|
||||||
return {
|
return {
|
||||||
|
@ -41,3 +41,4 @@ export const TEXTILE_SLACK_WEBHOOK_KEY = process.env.TEXTILE_SLACK_WEBHOOK_KEY;
|
|||||||
export const RESOURCE_URI_UPLOAD = process.env.RESOURCE_URI_UPLOAD;
|
export const RESOURCE_URI_UPLOAD = process.env.RESOURCE_URI_UPLOAD;
|
||||||
export const RESOURCE_URI_STORAGE_UPLOAD = process.env.RESOURCE_URI_STORAGE_UPLOAD;
|
export const RESOURCE_URI_STORAGE_UPLOAD = process.env.RESOURCE_URI_STORAGE_UPLOAD;
|
||||||
export const RESOURCE_URI_PUBSUB = process.env.RESOURCE_URI_PUBSUB;
|
export const RESOURCE_URI_PUBSUB = process.env.RESOURCE_URI_PUBSUB;
|
||||||
|
export const RESOURCE_URI_SEARCH = process.env.RESOURCE_URI_SEARCH;
|
@ -21,9 +21,37 @@ const delay = async (waitMs) => {
|
|||||||
|
|
||||||
Websocket.create();
|
Websocket.create();
|
||||||
|
|
||||||
|
//NOTE(martina): type = "UPDATE" will be processed by slate and lens. type = "SEARCH" will only be processed by lens
|
||||||
|
const websocketSend = async (type, data) => {
|
||||||
|
if (Strings.isEmpty(Environment.PUBSUB_SECRET)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ws = Websocket.get();
|
||||||
|
const encryptedData = await Utilities.encryptWithSecret(
|
||||||
|
JSON.stringify(data),
|
||||||
|
Environment.PUBSUB_SECRET
|
||||||
|
);
|
||||||
|
|
||||||
|
// NOTE(jim): Only allow this to be passed around encrypted.
|
||||||
|
ws.send(
|
||||||
|
JSON.stringify({
|
||||||
|
type,
|
||||||
|
iv: encryptedData.iv,
|
||||||
|
data: encryptedData.hex,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const hydratePartialViewer = async (user) => {
|
export const hydratePartialViewer = async (user) => {
|
||||||
const data = {
|
const data = {
|
||||||
...Serializers.user(user),
|
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",
|
type: "PARTIAL_VIEWER",
|
||||||
library: user.data.library,
|
library: user.data.library,
|
||||||
onboarding: user.data.onboarding || {},
|
onboarding: user.data.onboarding || {},
|
||||||
@ -40,24 +68,237 @@ export const hydratePartialViewer = async (user) => {
|
|||||||
: null,
|
: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (Strings.isEmpty(Environment.PUBSUB_SECRET)) {
|
websocketSend("UPDATE", data);
|
||||||
return;
|
};
|
||||||
|
|
||||||
|
export const hydratePartialOnboarding = async (onboarding, userId) => {
|
||||||
|
const data = {
|
||||||
|
id: userId,
|
||||||
|
onboarding,
|
||||||
|
};
|
||||||
|
websocketSend("UPDATE", data);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const hydratePartialSubscriptions = async (updated, userId) => {
|
||||||
|
const data = {
|
||||||
|
id: userId,
|
||||||
|
};
|
||||||
|
const user = await Data.getUserById({ id: userId });
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ws = Websocket.get();
|
if (user.error) {
|
||||||
const encryptedData = await Utilities.encryptWithSecret(
|
return null;
|
||||||
JSON.stringify(data),
|
}
|
||||||
Environment.PUBSUB_SECRET
|
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: {},
|
||||||
|
});
|
||||||
|
data.subscriptions = r1.serializedSubscriptions;
|
||||||
|
mostRecent = r1;
|
||||||
|
}
|
||||||
|
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 (updated.trusted) {
|
||||||
|
console.log("update 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 (updated.pendingTrusted) {
|
||||||
|
console.log("update pending trusted");
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
websocketSend("UPDATE", data);
|
||||||
|
};
|
||||||
|
|
||||||
// NOTE(jim): Only allow this to be passed around encrypted.
|
export const hydratePartialKeys = async (keys, userId) => {
|
||||||
ws.send(
|
const data = {
|
||||||
JSON.stringify({
|
id: userId,
|
||||||
type: "UPDATE",
|
keys,
|
||||||
iv: encryptedData.iv,
|
};
|
||||||
data: encryptedData.hex,
|
websocketSend("UPDATE", data);
|
||||||
})
|
};
|
||||||
);
|
|
||||||
|
export const hydratePartialLibrary = async (library, userId) => {
|
||||||
|
const data = {
|
||||||
|
id: userId,
|
||||||
|
library,
|
||||||
|
};
|
||||||
|
websocketSend("UPDATE", data);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const hydratePartialSlates = async (slates, userId) => {
|
||||||
|
console.log("hydrate 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
|
||||||
|
// websocketSend("UPDATE", data);
|
||||||
|
// };
|
||||||
|
|
||||||
|
export const hydrate = async (id) => {
|
||||||
|
const user = await Data.getUserById({
|
||||||
|
id,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.error) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(jim): You can serialize this last because you will have all the information
|
||||||
|
// from subscriptions, trusted, and pendingTrusted most likely.
|
||||||
|
const activity = await Data.getActivityForUserId({ userId: id });
|
||||||
|
const slates = await Data.getSlatesByUserId({ userId: id });
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
bytes += each.size;
|
||||||
|
});
|
||||||
|
|
||||||
|
let data = {
|
||||||
|
...Serializers.user(user),
|
||||||
|
type: "VIEWER",
|
||||||
|
library: user.data.library,
|
||||||
|
onboarding: user.data.onboarding || {},
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
stats: {
|
||||||
|
bytes,
|
||||||
|
maximumBytes: Constants.TEXTILE_ACCOUNT_BYTE_LIMIT,
|
||||||
|
imageBytes,
|
||||||
|
videoBytes,
|
||||||
|
audioBytes,
|
||||||
|
epubBytes,
|
||||||
|
pdfBytes,
|
||||||
|
},
|
||||||
|
keys,
|
||||||
|
activity,
|
||||||
|
slates,
|
||||||
|
subscriptions: r1.serializedSubscriptions,
|
||||||
|
subscribers: r2.serializedSubscribers,
|
||||||
|
trusted: r3.serializedTrusted,
|
||||||
|
pendingTrusted: r4.serializedPendingTrusted,
|
||||||
|
};
|
||||||
|
websocketSend("UPDATE", data);
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO(jim): Work on better serialization when adoption starts occuring.
|
// TODO(jim): Work on better serialization when adoption starts occuring.
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-rate-limit": "^5.1.3",
|
"express-rate-limit": "^5.1.3",
|
||||||
|
"fs": "0.0.1-security",
|
||||||
"fs-extra": "^9.0.1",
|
"fs-extra": "^9.0.1",
|
||||||
"heic2any": "0.0.3",
|
"heic2any": "0.0.3",
|
||||||
"isomorphic-fetch": "^3.0.0",
|
"isomorphic-fetch": "^3.0.0",
|
||||||
|
@ -46,7 +46,12 @@ export default class IntegrationPage extends React.Component {
|
|||||||
|
|
||||||
_handleChange = async (e) => {
|
_handleChange = async (e) => {
|
||||||
const query = e.target.value;
|
const query = e.target.value;
|
||||||
const results = await Actions.search({ query });
|
const results = await Actions.search({
|
||||||
|
query,
|
||||||
|
filter: {
|
||||||
|
slates: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
this.setState({ results: results.data.results });
|
this.setState({ results: results.data.results });
|
||||||
};
|
};
|
||||||
@ -59,8 +64,7 @@ export default class IntegrationPage extends React.Component {
|
|||||||
name: "create-alert",
|
name: "create-alert",
|
||||||
detail: {
|
detail: {
|
||||||
alert: {
|
alert: {
|
||||||
message:
|
message: "We're having trouble connecting right now. Please try again later",
|
||||||
"We're having trouble connecting right now. Please try again later",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -135,15 +139,11 @@ export default class IntegrationPage extends React.Component {
|
|||||||
{JSON.stringify(each, null, 1)}{" "}
|
{JSON.stringify(each, null, 1)}{" "}
|
||||||
<div>
|
<div>
|
||||||
{!each.data.verified ? (
|
{!each.data.verified ? (
|
||||||
<button onClick={() => this._handleAccept(each)}>
|
<button onClick={() => this._handleAccept(each)}>Accept</button>
|
||||||
Accept
|
|
||||||
</button>
|
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{each.data.verified ? (
|
{each.data.verified ? (
|
||||||
<button onClick={() => this._handleDelete(each)}>
|
<button onClick={() => this._handleDelete(each)}>Delete</button>
|
||||||
Delete
|
|
||||||
</button>
|
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -162,9 +162,7 @@ export default class IntegrationPage extends React.Component {
|
|||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{each.data.verified ? (
|
{each.data.verified ? (
|
||||||
<button onClick={() => this._handleDelete(each)}>
|
<button onClick={() => this._handleDelete(each)}>Delete</button>
|
||||||
Delete
|
|
||||||
</button>
|
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -172,15 +170,9 @@ export default class IntegrationPage extends React.Component {
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<div css={STYLES_COLUMN}>
|
<div css={STYLES_COLUMN}>
|
||||||
<button onClick={this._handleUpdate}>
|
<button onClick={this._handleUpdate}>Update {this.state.viewer.username}</button>
|
||||||
Update {this.state.viewer.username}
|
|
||||||
</button>
|
|
||||||
<br />
|
<br />
|
||||||
<input
|
<input type="text" onChange={this._handleChange} placeholder="type anything to search" />
|
||||||
type="text"
|
|
||||||
onChange={this._handleChange}
|
|
||||||
placeholder="type anything to search"
|
|
||||||
/>
|
|
||||||
|
|
||||||
{this.state.results.map((each) => {
|
{this.state.results.map((each) => {
|
||||||
if (!each) {
|
if (!each) {
|
||||||
@ -192,13 +184,9 @@ export default class IntegrationPage extends React.Component {
|
|||||||
{JSON.stringify(each, null, 1)}{" "}
|
{JSON.stringify(each, null, 1)}{" "}
|
||||||
<div>
|
<div>
|
||||||
{each.type === "USER" ? (
|
{each.type === "USER" ? (
|
||||||
<button onClick={() => this._handleTrust(each)}>
|
<button onClick={() => this._handleTrust(each)}>Trust</button>
|
||||||
Trust
|
|
||||||
</button>
|
|
||||||
) : null}
|
) : null}
|
||||||
<button onClick={() => this._handleSubscribe(each)}>
|
<button onClick={() => this._handleSubscribe(each)}>Subscribe</button>
|
||||||
Subscribe
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -210,9 +198,7 @@ export default class IntegrationPage extends React.Component {
|
|||||||
<div css={STYLES_ITEM} key={each.id}>
|
<div css={STYLES_ITEM} key={each.id}>
|
||||||
{JSON.stringify(each, null, 1)}{" "}
|
{JSON.stringify(each, null, 1)}{" "}
|
||||||
<div>
|
<div>
|
||||||
<button onClick={() => this._handleSubscribe(each)}>
|
<button onClick={() => this._handleSubscribe(each)}>Unsubscribe</button>
|
||||||
Unsubscribe
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -2,6 +2,7 @@ import * as Upload from "~/node_common/upload";
|
|||||||
import * as Utilities from "~/node_common/utilities";
|
import * as Utilities from "~/node_common/utilities";
|
||||||
import * as Data from "~/node_common/data";
|
import * as Data from "~/node_common/data";
|
||||||
import * as LibraryManager from "~/node_common/managers/library";
|
import * as LibraryManager from "~/node_common/managers/library";
|
||||||
|
import * as ViewerManager from "~/node_common/managers/viewer";
|
||||||
|
|
||||||
import { Buckets } from "@textile/hub";
|
import { Buckets } from "@textile/hub";
|
||||||
|
|
||||||
@ -13,17 +14,10 @@ export default async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!user || user.error) {
|
if (!user || user.error) {
|
||||||
return res
|
return res.status(403).send({ decorator: "SERVER_ADD_TO_SLATE_USER_NOT_FOUND", error: true });
|
||||||
.status(403)
|
|
||||||
.send({ decorator: "SERVER_ADD_TO_SLATE_USER_NOT_FOUND", error: true });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let {
|
let { buckets, bucketKey, bucketRoot, bucketName } = await Utilities.getBucketAPIFromUserToken({
|
||||||
buckets,
|
|
||||||
bucketKey,
|
|
||||||
bucketRoot,
|
|
||||||
bucketName,
|
|
||||||
} = await Utilities.getBucketAPIFromUserToken({
|
|
||||||
user,
|
user,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -41,9 +35,7 @@ export default async (req, res) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let userCIDs = user.data.library[0].children.map((file) =>
|
let userCIDs = user.data.library[0].children.map((file) => file.ipfs.replace("/ipfs/", ""));
|
||||||
file.ipfs.replace("/ipfs/", "")
|
|
||||||
);
|
|
||||||
let newFiles = [];
|
let newFiles = [];
|
||||||
for (let item of req.body.data.items) {
|
for (let item of req.body.data.items) {
|
||||||
let cid = item.cid;
|
let cid = item.cid;
|
||||||
@ -71,7 +63,7 @@ export default async (req, res) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { updatedUserDataFields } = LibraryManager.addData({
|
const { updatedUserDataFields, added, skipped } = LibraryManager.addData({
|
||||||
user,
|
user,
|
||||||
files: newFiles,
|
files: newFiles,
|
||||||
});
|
});
|
||||||
@ -79,9 +71,12 @@ export default async (req, res) => {
|
|||||||
id: user.id,
|
id: user.id,
|
||||||
data: updatedUserDataFields,
|
data: updatedUserDataFields,
|
||||||
});
|
});
|
||||||
|
if (updatedUserDataFields && updatedUserDataFields.library) {
|
||||||
|
ViewerManager.hydratePartialLibrary(updatedUserDataFields.library, id);
|
||||||
|
}
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
decorator: "SERVER_ADD_EXISTING_CID_TO_DATA",
|
decorator: "SERVER_ADD_EXISTING_CID_TO_DATA",
|
||||||
data: true,
|
data: { added, skipped: skipped + req.body.data.items.length - newFiles.length },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -1,32 +1,68 @@
|
|||||||
import * as Upload from "~/node_common/upload";
|
import * as Upload from "~/node_common/upload";
|
||||||
import * as Utilities from "~/node_common/utilities";
|
import * as Utilities from "~/node_common/utilities";
|
||||||
import * as Data from "~/node_common/data";
|
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) => {
|
export default async (req, res) => {
|
||||||
const id = Utilities.getIdFromCookie(req);
|
const id = Utilities.getIdFromCookie(req);
|
||||||
|
|
||||||
if (!id) {
|
if (!id) {
|
||||||
return res
|
return res.status(500).send({ decorator: "PROCESS_PENDING_ERROR", error: true });
|
||||||
.status(500)
|
|
||||||
.send({ decorator: "PROCESS_PENDING_ERROR", error: true });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await Data.deletePendingDataByUserId({ owner_user_id: id });
|
const user = await Data.getUserById({
|
||||||
|
id,
|
||||||
|
});
|
||||||
|
|
||||||
if (!response) {
|
if (!user) {
|
||||||
return res
|
return res.status(404).send({
|
||||||
.status(404)
|
decorator: "PROCESS_PENDING_USER_NOT_FOUND",
|
||||||
.send({ decorator: "PROCESS_PENDING_ERROR", error: true });
|
error: true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.error) {
|
if (user.error) {
|
||||||
return res
|
return res.status(500).send({
|
||||||
.status(500)
|
decorator: "PROCESS_PENDING_USER_NOT_FOUND",
|
||||||
.send({ decorator: response.decorator, error: response.error });
|
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.ipfs)) continue;
|
||||||
|
cids.push(entry.data.ipfs);
|
||||||
|
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({
|
return res.status(200).send({
|
||||||
decorator: "PROCESS_PENDING_DATA",
|
decorator: "PROCESS_PENDING_DATA",
|
||||||
data: response,
|
data: { added, skipped: skipped + pending.length - noRepeats.length },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,7 @@ import * as Data from "~/node_common/data";
|
|||||||
import * as Utilities from "~/node_common/utilities";
|
import * as Utilities from "~/node_common/utilities";
|
||||||
import * as Strings from "~/common/strings";
|
import * as Strings from "~/common/strings";
|
||||||
import * as Social from "~/node_common/social";
|
import * as Social from "~/node_common/social";
|
||||||
|
import * as ViewerManager from "~/node_common/managers/viewer";
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
if (!req.body.data || !req.body.data.cids || !req.body.data.cids.length) {
|
if (!req.body.data || !req.body.data.cids || !req.body.data.cids.length) {
|
||||||
@ -99,7 +100,8 @@ export default async (req, res) => {
|
|||||||
|
|
||||||
// NOTE(jim):
|
// NOTE(jim):
|
||||||
// Goes through all of your slates and removes all data references.
|
// Goes through all of your slates and removes all data references.
|
||||||
const slates = await Data.getSlatesByUserId({ userId: id });
|
let refreshSlates = false;
|
||||||
|
let slates = await Data.getSlatesByUserId({ userId: id });
|
||||||
for (let i = 0; i < slates.length; i++) {
|
for (let i = 0; i < slates.length; i++) {
|
||||||
let slate = slates[i];
|
let slate = slates[i];
|
||||||
|
|
||||||
@ -108,6 +110,7 @@ export default async (req, res) => {
|
|||||||
for (let cid of req.body.data.cids) {
|
for (let cid of req.body.data.cids) {
|
||||||
if (o.url.includes(cid)) {
|
if (o.url.includes(cid)) {
|
||||||
removal = true;
|
removal = true;
|
||||||
|
refreshSlates = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -115,7 +118,7 @@ export default async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (removal) {
|
if (removal) {
|
||||||
let layouts = await Data.updateSlateById({
|
await Data.updateSlateById({
|
||||||
id: slate.id,
|
id: slate.id,
|
||||||
updated_at: new Date(),
|
updated_at: new Date(),
|
||||||
data: {
|
data: {
|
||||||
@ -126,6 +129,11 @@ export default async (req, res) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (refreshSlates) {
|
||||||
|
slates = await Data.getSlatesByUserId({ userId: id });
|
||||||
|
ViewerManager.hydratePartialSlates(slates, id);
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE(martina):
|
// NOTE(martina):
|
||||||
// Removes the reposted file from other people's slates
|
// Removes the reposted file from other people's slates
|
||||||
// for (let cid of req.body.data.cids) {
|
// for (let cid of req.body.data.cids) {
|
||||||
@ -134,7 +142,7 @@ export default async (req, res) => {
|
|||||||
|
|
||||||
// NOTE(jim):
|
// NOTE(jim):
|
||||||
// Removes the file reference from your library
|
// Removes the file reference from your library
|
||||||
const response = await Data.updateUserById({
|
const unsafeResponse = await Data.updateUserById({
|
||||||
id: user.id,
|
id: user.id,
|
||||||
data: {
|
data: {
|
||||||
...user.data,
|
...user.data,
|
||||||
@ -154,6 +162,10 @@ export default async (req, res) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (unsafeResponse) {
|
||||||
|
ViewerManager.hydratePartialViewer(unsafeResponse);
|
||||||
|
}
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
decorator: "SERVER_REMOVE_DATA",
|
decorator: "SERVER_REMOVE_DATA",
|
||||||
success: true,
|
success: true,
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
import * as Environment from "~/node_common/environment";
|
import * as Environment from "~/node_common/environment";
|
||||||
import * as Data from "~/node_common/data";
|
import * as Data from "~/node_common/data";
|
||||||
import * as Utilities from "~/node_common/utilities";
|
import * as Utilities from "~/node_common/utilities";
|
||||||
|
import * as ViewerManager from "~/node_common/managers/viewer";
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const id = Utilities.getIdFromCookie(req);
|
const id = Utilities.getIdFromCookie(req);
|
||||||
if (!id) {
|
if (!id) {
|
||||||
return res
|
return res.status(500).send({ decorator: "SERVER_DELETE_API_KEY_AUTH", error: true });
|
||||||
.status(500)
|
|
||||||
.send({ decorator: "SERVER_DELETE_API_KEY_AUTH", error: true });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = await Data.getUserById({
|
const user = await Data.getUserById({
|
||||||
@ -30,7 +29,7 @@ export default async (req, res) => {
|
|||||||
|
|
||||||
const key = await Data.getAPIKey({ id: req.body.data.id });
|
const key = await Data.getAPIKey({ id: req.body.data.id });
|
||||||
|
|
||||||
if (key.owner_id !== user.id) {
|
if (!key || key.owner_id !== user.id) {
|
||||||
return res.status(403).send({
|
return res.status(403).send({
|
||||||
decorator: "SERVER_DELETE_API_KEY_NOT_FOUND",
|
decorator: "SERVER_DELETE_API_KEY_NOT_FOUND",
|
||||||
error: true,
|
error: true,
|
||||||
@ -67,5 +66,8 @@ export default async (req, res) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let keys = await Data.getAPIKeysByUserId({ userId: user.id });
|
||||||
|
ViewerManager.hydratePartialKeys(keys, user.id);
|
||||||
|
|
||||||
return res.status(200).send({ decorator: "SERVER_DELETE_API_KEY" });
|
return res.status(200).send({ decorator: "SERVER_DELETE_API_KEY" });
|
||||||
};
|
};
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
import * as Environment from "~/node_common/environment";
|
import * as Environment from "~/node_common/environment";
|
||||||
import * as Data from "~/node_common/data";
|
import * as Data from "~/node_common/data";
|
||||||
import * as Utilities from "~/node_common/utilities";
|
import * as Utilities from "~/node_common/utilities";
|
||||||
|
import * as ViewerManager from "~/node_common/managers/viewer";
|
||||||
|
|
||||||
import { v4 as uuid } from "uuid";
|
import { v4 as uuid } from "uuid";
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const id = Utilities.getIdFromCookie(req);
|
const id = Utilities.getIdFromCookie(req);
|
||||||
if (!id) {
|
if (!id) {
|
||||||
return res
|
return res.status(500).send({ decorator: "SERVER_GENERATE_API_KEY_AUTH", error: true });
|
||||||
.status(500)
|
|
||||||
.send({ decorator: "SERVER_GENERATE_API_KEY_AUTH", error: true });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = await Data.getUserById({
|
const user = await Data.getUserById({
|
||||||
@ -30,7 +29,7 @@ export default async (req, res) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const keys = await Data.getAPIKeysByUserId({ userId: user.id });
|
let keys = await Data.getAPIKeysByUserId({ userId: user.id });
|
||||||
|
|
||||||
if (keys.length > 9) {
|
if (keys.length > 9) {
|
||||||
return res.status(404).send({
|
return res.status(404).send({
|
||||||
@ -58,5 +57,8 @@ export default async (req, res) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
keys = await Data.getAPIKeysByUserId({ userId: user.id });
|
||||||
|
ViewerManager.hydratePartialKeys(keys, user.id);
|
||||||
|
|
||||||
return res.status(200).send({ decorator: "SERVER_GENERATE_API_KEY", key });
|
return res.status(200).send({ decorator: "SERVER_GENERATE_API_KEY", key });
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,7 @@ import * as Constants from "~/node_common/constants";
|
|||||||
import * as Utilities from "~/node_common/utilities";
|
import * as Utilities from "~/node_common/utilities";
|
||||||
import * as Data from "~/node_common/data";
|
import * as Data from "~/node_common/data";
|
||||||
import * as Strings from "~/common/strings";
|
import * as Strings from "~/common/strings";
|
||||||
|
import * as ViewerManager from "~/node_common/managers/viewer";
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const id = Utilities.getIdFromCookie(req);
|
const id = Utilities.getIdFromCookie(req);
|
||||||
@ -120,6 +121,11 @@ export default async (req, res) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const slates = await Data.getSlatesByUserId({ userId: id });
|
||||||
|
if (slates) {
|
||||||
|
ViewerManager.hydratePartialSlates(slates, id);
|
||||||
|
}
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
decorator: "SERVER_SLATE_ADD_TO_SLATE",
|
decorator: "SERVER_SLATE_ADD_TO_SLATE",
|
||||||
added: addlObjects.length,
|
added: addlObjects.length,
|
||||||
|
@ -2,6 +2,7 @@ import * as Utilities from "~/node_common/utilities";
|
|||||||
import * as Data from "~/node_common/data";
|
import * as Data from "~/node_common/data";
|
||||||
import * as Strings from "~/common/strings";
|
import * as Strings from "~/common/strings";
|
||||||
import * as Social from "~/node_common/social";
|
import * as Social from "~/node_common/social";
|
||||||
|
import * as ViewerManager from "~/node_common/managers/viewer";
|
||||||
|
|
||||||
const SLATE_LIMIT = 50;
|
const SLATE_LIMIT = 50;
|
||||||
|
|
||||||
@ -40,7 +41,7 @@ export default async (req, res) => {
|
|||||||
return res.status(500).send({ decorator: "SERVER_EXISTING_SLATE", error: true });
|
return res.status(500).send({ decorator: "SERVER_EXISTING_SLATE", error: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
const slates = await Data.getSlatesByUserId({ userId: id });
|
let slates = await Data.getSlatesByUserId({ userId: id });
|
||||||
if (slates.length >= SLATE_LIMIT) {
|
if (slates.length >= SLATE_LIMIT) {
|
||||||
return res.status(500).send({ decorator: "SERVER_SLATE_LIMIT", error: true });
|
return res.status(500).send({ decorator: "SERVER_SLATE_LIMIT", error: true });
|
||||||
}
|
}
|
||||||
@ -64,6 +65,11 @@ export default async (req, res) => {
|
|||||||
return res.status(500).send({ decorator: "SERVER_CREATE_SLATE", error: true });
|
return res.status(500).send({ decorator: "SERVER_CREATE_SLATE", error: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slates = await Data.getSlatesByUserId({ userId: id });
|
||||||
|
if (slates) {
|
||||||
|
ViewerManager.hydratePartialSlates(slates, id);
|
||||||
|
}
|
||||||
|
|
||||||
const userProfileURL = `https://slate.host/${user.username}`;
|
const userProfileURL = `https://slate.host/${user.username}`;
|
||||||
const userURL = `<${userProfileURL}|${user.username}>`;
|
const userURL = `<${userProfileURL}|${user.username}>`;
|
||||||
Social.sendSlackMessage(
|
Social.sendSlackMessage(
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import * as Utilities from "~/node_common/utilities";
|
import * as Utilities from "~/node_common/utilities";
|
||||||
import * as Data from "~/node_common/data";
|
import * as Data from "~/node_common/data";
|
||||||
import * as Strings from "~/common/strings";
|
import * as Strings from "~/common/strings";
|
||||||
|
import * as ViewerManager from "~/node_common/managers/viewer";
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const id = Utilities.getIdFromCookie(req);
|
const id = Utilities.getIdFromCookie(req);
|
||||||
@ -46,5 +47,10 @@ export default async (req, res) => {
|
|||||||
return res.status(500).send({ decorator: "SERVER_DELETE_SLATE", error: true });
|
return res.status(500).send({ decorator: "SERVER_DELETE_SLATE", error: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let slates = await Data.getSlatesByUserId({ userId: id });
|
||||||
|
if (slates) {
|
||||||
|
ViewerManager.hydratePartialSlates(slates, id);
|
||||||
|
}
|
||||||
|
|
||||||
return res.status(200).send({ decorator: "SERVER_DELETE_SLATE", error: false });
|
return res.status(200).send({ decorator: "SERVER_DELETE_SLATE", error: false });
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,7 @@ import * as Constants from "~/node_common/constants";
|
|||||||
import * as Utilities from "~/node_common/utilities";
|
import * as Utilities from "~/node_common/utilities";
|
||||||
import * as Data from "~/node_common/data";
|
import * as Data from "~/node_common/data";
|
||||||
import * as Strings from "~/common/strings";
|
import * as Strings from "~/common/strings";
|
||||||
|
import * as ViewerManager from "~/node_common/managers/viewer";
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const id = Utilities.getIdFromCookie(req);
|
const id = Utilities.getIdFromCookie(req);
|
||||||
@ -79,6 +80,11 @@ export default async (req, res) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let slates = await Data.getSlatesByUserId({ userId: id });
|
||||||
|
if (slates) {
|
||||||
|
ViewerManager.hydratePartialSlates(slates, id);
|
||||||
|
}
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
decorator: "SERVER_SLATE_REMOVE_FROM_SLATE",
|
decorator: "SERVER_SLATE_REMOVE_FROM_SLATE",
|
||||||
slate,
|
slate,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import * as Utilities from "~/node_common/utilities";
|
import * as Utilities from "~/node_common/utilities";
|
||||||
import * as Data from "~/node_common/data";
|
import * as Data from "~/node_common/data";
|
||||||
import * as Strings from "~/common/strings";
|
import * as Strings from "~/common/strings";
|
||||||
|
import * as ViewerManager from "~/node_common/managers/viewer";
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const id = Utilities.getIdFromCookie(req);
|
const id = Utilities.getIdFromCookie(req);
|
||||||
@ -10,9 +11,7 @@ export default async (req, res) => {
|
|||||||
|
|
||||||
if (!layoutOnly) {
|
if (!layoutOnly) {
|
||||||
if (!id) {
|
if (!id) {
|
||||||
return res
|
return res.status(500).send({ decorator: "SERVER_FIND_USER_UPDATE_SLATE", error: true });
|
||||||
.status(500)
|
|
||||||
.send({ decorator: "SERVER_FIND_USER_UPDATE_SLATE", error: true });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
user = await Data.getUserById({
|
user = await Data.getUserById({
|
||||||
@ -37,15 +36,11 @@ export default async (req, res) => {
|
|||||||
const response = await Data.getSlateById({ id: req.body.data.id });
|
const response = await Data.getSlateById({ id: req.body.data.id });
|
||||||
|
|
||||||
if (!response) {
|
if (!response) {
|
||||||
return res
|
return res.status(404).send({ decorator: "SERVER_UPDATE_SLATE_NOT_FOUND", error: true });
|
||||||
.status(404)
|
|
||||||
.send({ decorator: "SERVER_UPDATE_SLATE_NOT_FOUND", error: true });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
return res
|
return res.status(500).send({ decorator: "SERVER_UPDATE_SLATE_NOT_FOUND", error: true });
|
||||||
.status(500)
|
|
||||||
.send({ decorator: "SERVER_UPDATE_SLATE_NOT_FOUND", error: true });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!req.body.data) {
|
if (!req.body.data) {
|
||||||
@ -87,8 +82,7 @@ export default async (req, res) => {
|
|||||||
slatename: req.body.data.data.name
|
slatename: req.body.data.data.name
|
||||||
? Strings.createSlug(req.body.data.data.name)
|
? Strings.createSlug(req.body.data.data.name)
|
||||||
: response.slatename,
|
: response.slatename,
|
||||||
updated_at:
|
updated_at: layoutOnly || req.body.data.autoSave ? response.updated_at : new Date(),
|
||||||
layoutOnly || req.body.data.autoSave ? response.updated_at : new Date(),
|
|
||||||
data: {
|
data: {
|
||||||
...response.data,
|
...response.data,
|
||||||
...req.body.data.data,
|
...req.body.data.data,
|
||||||
@ -97,15 +91,16 @@ export default async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!slate) {
|
if (!slate) {
|
||||||
return res
|
return res.status(404).send({ decorator: "SERVER_UPDATE_SLATE", error: true });
|
||||||
.status(404)
|
|
||||||
.send({ decorator: "SERVER_UPDATE_SLATE", error: true });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slate.error) {
|
if (slate.error) {
|
||||||
return res
|
return res.status(500).send({ decorator: "SERVER_UPDATE_SLATE", error: true });
|
||||||
.status(500)
|
}
|
||||||
.send({ decorator: "SERVER_UPDATE_SLATE", error: true });
|
|
||||||
|
let slates = await Data.getSlatesByUserId({ userId: id });
|
||||||
|
if (slates) {
|
||||||
|
ViewerManager.hydratePartialSlates(slates, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status(200).send({ decorator: "SERVER_UPDATE_SLATE", slate });
|
return res.status(200).send({ decorator: "SERVER_UPDATE_SLATE", slate });
|
||||||
|
@ -2,6 +2,7 @@ import * as Data from "~/node_common/data";
|
|||||||
import * as Utilities from "~/node_common/utilities";
|
import * as Utilities from "~/node_common/utilities";
|
||||||
import * as Serializers from "~/node_common/serializers";
|
import * as Serializers from "~/node_common/serializers";
|
||||||
import * as Validations from "~/common/validations";
|
import * as Validations from "~/common/validations";
|
||||||
|
import * as ViewerManager from "~/node_common/managers/viewer";
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const id = Utilities.getIdFromCookie(req);
|
const id = Utilities.getIdFromCookie(req);
|
||||||
@ -102,6 +103,8 @@ export default async (req, res) => {
|
|||||||
return res.status(500).send({ decorator: "SERVER_UNSUBSCRIBE_ERROR", error: true });
|
return res.status(500).send({ decorator: "SERVER_UNSUBSCRIBE_ERROR", error: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ViewerManager.hydratePartialSubscriptions({ subscriptions: true }, user.id);
|
||||||
|
|
||||||
return res.status(200).send({ decorator: "SERVER_UNSUBSCRIBE", data: unsubscribeResponse });
|
return res.status(200).send({ decorator: "SERVER_UNSUBSCRIBE", data: unsubscribeResponse });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,6 +122,8 @@ export default async (req, res) => {
|
|||||||
return res.status(500).send({ decorator: "SERVER_SUBSCRIBE_ERROR", error: true });
|
return res.status(500).send({ decorator: "SERVER_SUBSCRIBE_ERROR", error: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ViewerManager.hydratePartialSubscriptions({ subscriptions: true }, user.id);
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
decorator: "SERVER_SUBSCRIBE",
|
decorator: "SERVER_SUBSCRIBE",
|
||||||
data: {
|
data: {
|
||||||
|
@ -3,6 +3,7 @@ import * as Data from "~/node_common/data";
|
|||||||
import * as Utilities from "~/node_common/utilities";
|
import * as Utilities from "~/node_common/utilities";
|
||||||
import * as Serializers from "~/node_common/serializers";
|
import * as Serializers from "~/node_common/serializers";
|
||||||
import * as Validations from "~/common/validations";
|
import * as Validations from "~/common/validations";
|
||||||
|
import * as ViewerManager from "~/node_common/managers/viewer";
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const id = Utilities.getIdFromCookie(req);
|
const id = Utilities.getIdFromCookie(req);
|
||||||
@ -48,6 +49,8 @@ export default async (req, res) => {
|
|||||||
data: { ...user.data, onboarding },
|
data: { ...user.data, onboarding },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ViewerManager.hydratePartialOnboarding(onboarding, user.id);
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
decorator: "SERVER_ONBOARDING_UPDATE",
|
decorator: "SERVER_ONBOARDING_UPDATE",
|
||||||
data: updateResponse,
|
data: updateResponse,
|
||||||
|
@ -2,6 +2,7 @@ import * as Environment from "~/node_common/environment";
|
|||||||
import * as Data from "~/node_common/data";
|
import * as Data from "~/node_common/data";
|
||||||
import * as Utilities from "~/node_common/utilities";
|
import * as Utilities from "~/node_common/utilities";
|
||||||
import * as Validations from "~/common/validations";
|
import * as Validations from "~/common/validations";
|
||||||
|
import * as ViewerManager from "~/node_common/managers/viewer";
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const id = Utilities.getIdFromCookie(req);
|
const id = Utilities.getIdFromCookie(req);
|
||||||
@ -38,5 +39,7 @@ export default async (req, res) => {
|
|||||||
id: req.body.data.id,
|
id: req.body.data.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ViewerManager.hydratePartialSubscriptions({ trusted: true, pendingTrusted: true }, id);
|
||||||
|
|
||||||
return res.status(200).send({ decorator: "SERVER_TRUST_UPDATE", data: response });
|
return res.status(200).send({ decorator: "SERVER_TRUST_UPDATE", data: response });
|
||||||
};
|
};
|
||||||
|
@ -3,6 +3,7 @@ import * as Data from "~/node_common/data";
|
|||||||
import * as Utilities from "~/node_common/utilities";
|
import * as Utilities from "~/node_common/utilities";
|
||||||
import * as Serializers from "~/node_common/serializers";
|
import * as Serializers from "~/node_common/serializers";
|
||||||
import * as Validations from "~/common/validations";
|
import * as Validations from "~/common/validations";
|
||||||
|
import * as ViewerManager from "~/node_common/managers/viewer";
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const id = Utilities.getIdFromCookie(req);
|
const id = Utilities.getIdFromCookie(req);
|
||||||
@ -84,6 +85,8 @@ export default async (req, res) => {
|
|||||||
data: { ...existingResponse.data, verified: true },
|
data: { ...existingResponse.data, verified: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ViewerManager.hydratePartialSubscriptions({ trusted: true, pendingTrusted: true }, id);
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
decorator: "SERVER_TRUST_UPDATE",
|
decorator: "SERVER_TRUST_UPDATE",
|
||||||
data: {
|
data: {
|
||||||
|
@ -3,6 +3,7 @@ import * as Data from "~/node_common/data";
|
|||||||
import * as Utilities from "~/node_common/utilities";
|
import * as Utilities from "~/node_common/utilities";
|
||||||
import * as Serializers from "~/node_common/serializers";
|
import * as Serializers from "~/node_common/serializers";
|
||||||
import * as Validations from "~/common/validations";
|
import * as Validations from "~/common/validations";
|
||||||
|
import * as ViewerManager from "~/node_common/managers/viewer";
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const id = Utilities.getIdFromCookie(req);
|
const id = Utilities.getIdFromCookie(req);
|
||||||
@ -105,6 +106,8 @@ export default async (req, res) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ViewerManager.hydratePartialSubscriptions({ trusted: true, pendingTrusted: true }, id);
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
decorator: "SERVER_DELETE_TRUSTED_RELATIONSHIP",
|
decorator: "SERVER_DELETE_TRUSTED_RELATIONSHIP",
|
||||||
data: deleteRelationshipResponse,
|
data: deleteRelationshipResponse,
|
||||||
@ -127,6 +130,8 @@ export default async (req, res) => {
|
|||||||
return res.status(500).send({ decorator: "SERVER_TRUSTED_RELATIONSHIP_ERROR", error: true });
|
return res.status(500).send({ decorator: "SERVER_TRUSTED_RELATIONSHIP_ERROR", error: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ViewerManager.hydratePartialSubscriptions({ trusted: true, pendingTrusted: true }, id);
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
decorator: "SERVER_TRUSTED_RELATIONSHIP",
|
decorator: "SERVER_TRUSTED_RELATIONSHIP",
|
||||||
data: {
|
data: {
|
||||||
|
@ -138,7 +138,6 @@ export default class SceneDirectory extends React.Component {
|
|||||||
|
|
||||||
state = {
|
state = {
|
||||||
copyValue: "",
|
copyValue: "",
|
||||||
loading: false,
|
|
||||||
tab: 0,
|
tab: 0,
|
||||||
contextMenu: null,
|
contextMenu: null,
|
||||||
};
|
};
|
||||||
@ -168,28 +167,25 @@ export default class SceneDirectory extends React.Component {
|
|||||||
_handleDelete = async (e, id) => {
|
_handleDelete = async (e, id) => {
|
||||||
this._handleHide();
|
this._handleHide();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
const response = await Actions.deleteTrustRelationship({
|
await Actions.deleteTrustRelationship({
|
||||||
id: id,
|
id: id,
|
||||||
});
|
});
|
||||||
await this.props.onRehydrate();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_handleAccept = async (e, id) => {
|
_handleAccept = async (e, id) => {
|
||||||
this._handleHide();
|
this._handleHide();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
const response = await Actions.updateTrustRelationship({
|
await Actions.updateTrustRelationship({
|
||||||
userId: id,
|
userId: id,
|
||||||
});
|
});
|
||||||
await this.props.onRehydrate();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_handleFollow = async (e, id) => {
|
_handleFollow = async (e, id) => {
|
||||||
this._handleHide();
|
this._handleHide();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
const response = await Actions.createSubscription({
|
await Actions.createSubscription({
|
||||||
userId: id,
|
userId: id,
|
||||||
});
|
});
|
||||||
await this.props.onRehydrate();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -50,7 +50,6 @@ export default class SceneFilesFolder extends React.Component {
|
|||||||
onAction={this.props.onAction}
|
onAction={this.props.onAction}
|
||||||
viewer={this.props.viewer}
|
viewer={this.props.viewer}
|
||||||
items={this.props.viewer.library[0].children}
|
items={this.props.viewer.library[0].children}
|
||||||
onRehydrate={this.props.onRehydrate}
|
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<EmptyState>
|
<EmptyState>
|
||||||
|
@ -58,7 +58,6 @@ export default class SceneHome extends React.Component {
|
|||||||
viewer={this.props.viewer}
|
viewer={this.props.viewer}
|
||||||
items={this.props.viewer.library[0].children}
|
items={this.props.viewer.library[0].children}
|
||||||
onAction={this.props.onAction}
|
onAction={this.props.onAction}
|
||||||
onRehydrate={this.props.onRehydrate}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
@ -5,10 +5,7 @@ import * as Constants from "~/common/constants";
|
|||||||
import * as SVG from "~/common/svg";
|
import * as SVG from "~/common/svg";
|
||||||
|
|
||||||
import { css } from "@emotion/react";
|
import { css } from "@emotion/react";
|
||||||
import {
|
import { ButtonPrimary, ButtonSecondary } from "~/components/system/components/Buttons";
|
||||||
ButtonPrimary,
|
|
||||||
ButtonSecondary,
|
|
||||||
} from "~/components/system/components/Buttons";
|
|
||||||
import { dispatchCustomEvent } from "~/common/custom-events";
|
import { dispatchCustomEvent } from "~/common/custom-events";
|
||||||
|
|
||||||
import ScenePage from "~/components/core/ScenePage";
|
import ScenePage from "~/components/core/ScenePage";
|
||||||
@ -28,165 +25,87 @@ const STATUS_BUTTON_MAP = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default class SceneProfile extends React.Component {
|
export default class SceneProfile extends React.Component {
|
||||||
state = {
|
_handleTrust = async (trustStatus, trustId) => {
|
||||||
loading: false,
|
if (trustStatus === "untrusted" || trustStatus === "sent") {
|
||||||
trustStatus: "untrusted",
|
await Actions.createTrustRelationship({
|
||||||
followStatus: false,
|
userId: this.props.data.id,
|
||||||
followLoading: false,
|
});
|
||||||
trustLoading: false,
|
} else if (trustStatus === "received") {
|
||||||
};
|
await Actions.updateTrustRelationship({
|
||||||
|
userId: this.props.data.id,
|
||||||
componentDidMount = () => {
|
});
|
||||||
this.setStatus(this.props.viewer);
|
} else {
|
||||||
};
|
await Actions.deleteTrustRelationship({
|
||||||
|
id: trustId,
|
||||||
componentDidUpdate(prevProps) {
|
});
|
||||||
if (prevProps.data.username !== this.props.data.username) {
|
|
||||||
this.setStatus(this.props.viewer);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
setStatus = (viewer) => {
|
|
||||||
let newState = {
|
|
||||||
trustStatus: "untrusted",
|
|
||||||
followStatus: false,
|
|
||||||
followLoading: false,
|
|
||||||
trustLoading: false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_handleFollow = async () => {
|
||||||
|
await Actions.createSubscription({
|
||||||
|
userId: this.props.data.id,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let trustId, followStatus, relation;
|
||||||
|
let trustStatus = "untrusted";
|
||||||
|
let viewer = this.props.viewer;
|
||||||
let trust = viewer.trusted.filter((entry) => {
|
let trust = viewer.trusted.filter((entry) => {
|
||||||
return entry.target_user_id === this.props.data.id;
|
return entry.target_user_id === this.props.data.id;
|
||||||
});
|
});
|
||||||
if (trust.length) {
|
if (trust.length) {
|
||||||
let relation = trust[0];
|
relation = trust[0];
|
||||||
newState.trustId = relation.id;
|
trustId = relation.id;
|
||||||
if (relation.data.verified) {
|
if (relation.data.verified) {
|
||||||
newState.trustStatus = "trusted";
|
trustStatus = "trusted";
|
||||||
} else {
|
} else {
|
||||||
newState.trustStatus = "sent";
|
trustStatus = "sent";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let pendingTrust = viewer.pendingTrusted.filter((entry) => {
|
let pendingTrust = viewer.pendingTrusted.filter((entry) => {
|
||||||
return entry.owner_user_id === this.props.data.id;
|
return entry.owner_user_id === this.props.data.id;
|
||||||
});
|
});
|
||||||
if (pendingTrust.length) {
|
if (pendingTrust.length) {
|
||||||
let relation = pendingTrust[0];
|
relation = pendingTrust[0];
|
||||||
newState.trustId = relation.id;
|
trustId = relation.id;
|
||||||
if (pendingTrust[0].data.verified) {
|
if (pendingTrust[0].data.verified) {
|
||||||
newState.trustStatus = "trusted";
|
trustStatus = "trusted";
|
||||||
} else {
|
} else {
|
||||||
newState.trustStatus = "received";
|
trustStatus = "received";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (
|
followStatus = !!viewer.subscriptions.filter((entry) => {
|
||||||
viewer.subscriptions.filter((entry) => {
|
|
||||||
return entry.target_user_id === this.props.data.id;
|
return entry.target_user_id === this.props.data.id;
|
||||||
}).length
|
}).length;
|
||||||
) {
|
|
||||||
newState.followStatus = true;
|
|
||||||
}
|
|
||||||
this.setState(newState);
|
|
||||||
};
|
|
||||||
|
|
||||||
_handleUpdate = async (e) => {
|
|
||||||
let response = await this.props.onRehydrate();
|
|
||||||
if (!response) {
|
|
||||||
dispatchCustomEvent({
|
|
||||||
name: "create-alert",
|
|
||||||
detail: {
|
|
||||||
alert: {
|
|
||||||
message:
|
|
||||||
"We're having trouble connecting right now. Please try again later",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.error) {
|
|
||||||
dispatchCustomEvent({
|
|
||||||
name: "create-alert",
|
|
||||||
detail: { alert: { decorator: response.decorator } },
|
|
||||||
});
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let viewer = response.data;
|
|
||||||
|
|
||||||
this.setStatus(viewer);
|
|
||||||
};
|
|
||||||
|
|
||||||
_handleTrust = () => {
|
|
||||||
this.setState({ trustLoading: true }, async () => {
|
|
||||||
let response;
|
|
||||||
if (
|
|
||||||
this.state.trustStatus === "untrusted" ||
|
|
||||||
this.state.trustStatus === "sent"
|
|
||||||
) {
|
|
||||||
response = await Actions.createTrustRelationship({
|
|
||||||
userId: this.props.data.id,
|
|
||||||
});
|
|
||||||
console.log(response);
|
|
||||||
} else if (this.state.trustStatus === "received") {
|
|
||||||
response = await Actions.updateTrustRelationship({
|
|
||||||
userId: this.props.data.id,
|
|
||||||
});
|
|
||||||
console.log(response);
|
|
||||||
} else {
|
|
||||||
response = await Actions.deleteTrustRelationship({
|
|
||||||
id: this.state.trustId,
|
|
||||||
});
|
|
||||||
console.log(response);
|
|
||||||
}
|
|
||||||
await this._handleUpdate();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
_handleFollow = () => {
|
|
||||||
this.setState({ followLoading: true }, async () => {
|
|
||||||
let response = await Actions.createSubscription({
|
|
||||||
userId: this.props.data.id,
|
|
||||||
});
|
|
||||||
console.log(response);
|
|
||||||
await this._handleUpdate();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
let buttons = (
|
let buttons = (
|
||||||
<div css={STYLES_BUTTONS}>
|
<div css={STYLES_BUTTONS}>
|
||||||
{this.state.followStatus ? (
|
{followStatus ? (
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
loading={this.state.followLoading}
|
|
||||||
style={{ margin: "0px 8px", minWidth: 152 }}
|
style={{ margin: "0px 8px", minWidth: 152 }}
|
||||||
onClick={this._handleFollow}
|
onClick={this._handleFollow}
|
||||||
>
|
>
|
||||||
Unfollow
|
Unfollow
|
||||||
</ButtonSecondary>
|
</ButtonSecondary>
|
||||||
) : (
|
) : (
|
||||||
<ButtonPrimary
|
<ButtonPrimary style={{ margin: "0px 8px", minWidth: 152 }} onClick={this._handleFollow}>
|
||||||
loading={this.state.followLoading}
|
|
||||||
style={{ margin: "0px 8px", minWidth: 152 }}
|
|
||||||
onClick={this._handleFollow}
|
|
||||||
>
|
|
||||||
Follow
|
Follow
|
||||||
</ButtonPrimary>
|
</ButtonPrimary>
|
||||||
)}
|
)}
|
||||||
{this.state.trustStatus === "untrusted" ||
|
{trustStatus === "untrusted" || trustStatus === "received" ? (
|
||||||
this.state.trustStatus === "received" ? (
|
|
||||||
<ButtonPrimary
|
<ButtonPrimary
|
||||||
loading={this.state.trustLoading}
|
|
||||||
style={{ margin: "0px 8px", minWidth: 152 }}
|
style={{ margin: "0px 8px", minWidth: 152 }}
|
||||||
onClick={this._handleTrust}
|
onClick={() => this._handleTrust(trustStatus, trustId)}
|
||||||
>
|
>
|
||||||
{STATUS_BUTTON_MAP[this.state.trustStatus]}
|
{STATUS_BUTTON_MAP[trustStatus]}
|
||||||
</ButtonPrimary>
|
</ButtonPrimary>
|
||||||
) : (
|
) : (
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
loading={this.state.trustLoading}
|
|
||||||
style={{ margin: "0px 8px", minWidth: 152 }}
|
style={{ margin: "0px 8px", minWidth: 152 }}
|
||||||
onClick={this._handleTrust}
|
onClick={() => this._handleTrust(trustStatus, trustId)}
|
||||||
>
|
>
|
||||||
{STATUS_BUTTON_MAP[this.state.trustStatus]}
|
{STATUS_BUTTON_MAP[trustStatus]}
|
||||||
</ButtonSecondary>
|
</ButtonSecondary>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -198,11 +117,7 @@ export default class SceneProfile extends React.Component {
|
|||||||
onAction={this.props.onAction}
|
onAction={this.props.onAction}
|
||||||
creator={this.props.data}
|
creator={this.props.data}
|
||||||
sceneId={this.props.sceneId}
|
sceneId={this.props.sceneId}
|
||||||
buttons={
|
buttons={this.props.viewer.username === this.props.data.username ? null : buttons}
|
||||||
this.props.viewer.username === this.props.data.username
|
|
||||||
? null
|
|
||||||
: buttons
|
|
||||||
}
|
|
||||||
isOwner={this.props.viewer.username === this.props.data.username}
|
isOwner={this.props.viewer.username === this.props.data.username}
|
||||||
/>
|
/>
|
||||||
</ScenePage>
|
</ScenePage>
|
||||||
|
@ -118,8 +118,6 @@ export default class SceneSettings extends React.Component {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.props.onRehydrate();
|
|
||||||
|
|
||||||
this.setState({ loading: false });
|
this.setState({ loading: false });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -211,8 +211,6 @@ export default class SceneSettingsDeveloper extends React.Component {
|
|||||||
return this.setState({ loading: false });
|
return this.setState({ loading: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.props.onRehydrate();
|
|
||||||
|
|
||||||
this.setState({ loading: false });
|
this.setState({ loading: false });
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -244,6 +242,7 @@ export default class SceneSettingsDeveloper extends React.Component {
|
|||||||
});
|
});
|
||||||
return this.setState({ loading: false });
|
return this.setState({ loading: false });
|
||||||
}
|
}
|
||||||
|
this.setState({ loading: false });
|
||||||
};
|
};
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
|
@ -57,7 +57,6 @@ export default class SceneSlate extends React.Component {
|
|||||||
saving: "IDLE",
|
saving: "IDLE",
|
||||||
isOwner: this.props.current.data.ownerId === this.props.viewer.id,
|
isOwner: this.props.current.data.ownerId === this.props.viewer.id,
|
||||||
editing: false,
|
editing: false,
|
||||||
followLoading: false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOTE(jim):
|
// NOTE(jim):
|
||||||
@ -108,13 +107,9 @@ export default class SceneSlate extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_handleFollow = () => {
|
_handleFollow = () => {
|
||||||
this.setState({ followLoading: true }, async () => {
|
Actions.createSubscription({
|
||||||
let response = await Actions.createSubscription({
|
|
||||||
slateId: this.props.current.id,
|
slateId: this.props.current.id,
|
||||||
});
|
});
|
||||||
await this.props.onRehydrate();
|
|
||||||
this.setState({ followLoading: false });
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_handleSaveLayout = async (layouts, autoSave) => {
|
_handleSaveLayout = async (layouts, autoSave) => {
|
||||||
@ -165,10 +160,6 @@ export default class SceneSlate extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.state.isOwner) {
|
|
||||||
await this.props.onRehydrate();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
saving: "SAVED",
|
saving: "SAVED",
|
||||||
});
|
});
|
||||||
@ -224,7 +215,6 @@ export default class SceneSlate extends React.Component {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await this.props.onRehydrate();
|
|
||||||
dispatchCustomEvent({
|
dispatchCustomEvent({
|
||||||
name: "create-alert",
|
name: "create-alert",
|
||||||
detail: {
|
detail: {
|
||||||
@ -277,8 +267,6 @@ export default class SceneSlate extends React.Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.props.onRehydrate();
|
|
||||||
|
|
||||||
System.dispatchCustomEvent({
|
System.dispatchCustomEvent({
|
||||||
name: "state-global-carousel-loading",
|
name: "state-global-carousel-loading",
|
||||||
detail: { loading: false },
|
detail: { loading: false },
|
||||||
@ -323,8 +311,14 @@ export default class SceneSlate extends React.Component {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let message = Strings.formatAsUploadMessage(response.data.added, response.data.skipped);
|
||||||
|
dispatchCustomEvent({
|
||||||
|
name: "create-alert",
|
||||||
|
detail: {
|
||||||
|
alert: { message, status: !response.data.added ? null : "INFO" },
|
||||||
|
},
|
||||||
|
});
|
||||||
this.setState({ loading: false, saving: "SAVED" });
|
this.setState({ loading: false, saving: "SAVED" });
|
||||||
this.props.onRehydrate();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_handleShowSettings = () => {
|
_handleShowSettings = () => {
|
||||||
@ -336,7 +330,6 @@ export default class SceneSlate extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
console.log(this.props);
|
|
||||||
const { user, data } = this.props.current;
|
const { user, data } = this.props.current;
|
||||||
const { body = "", preview } = data;
|
const { body = "", preview } = data;
|
||||||
let objects = this.props.current.data.objects;
|
let objects = this.props.current.data.objects;
|
||||||
@ -375,19 +368,11 @@ export default class SceneSlate extends React.Component {
|
|||||||
) : (
|
) : (
|
||||||
<div onClick={this._handleFollow}>
|
<div onClick={this._handleFollow}>
|
||||||
{following ? (
|
{following ? (
|
||||||
<ButtonSecondary
|
<ButtonSecondary transparent style={{ minWidth: 120, paddingLeft: 0 }}>
|
||||||
transparent
|
|
||||||
style={{ minWidth: 120, paddingLeft: 0 }}
|
|
||||||
loading={this.state.followLoading}
|
|
||||||
>
|
|
||||||
Unfollow
|
Unfollow
|
||||||
</ButtonSecondary>
|
</ButtonSecondary>
|
||||||
) : (
|
) : (
|
||||||
<ButtonPrimary
|
<ButtonPrimary transparent style={{ minWidth: 120, paddingLeft: 0 }}>
|
||||||
transparent
|
|
||||||
style={{ minWidth: 120, paddingLeft: 0 }}
|
|
||||||
loading={this.state.followLoading}
|
|
||||||
>
|
|
||||||
Follow
|
Follow
|
||||||
</ButtonPrimary>
|
</ButtonPrimary>
|
||||||
)}
|
)}
|
||||||
|
@ -35,13 +35,12 @@ export default class SceneSlates extends React.Component {
|
|||||||
type: "SIDEBAR",
|
type: "SIDEBAR",
|
||||||
value: "SIDEBAR_CREATE_SLATE",
|
value: "SIDEBAR_CREATE_SLATE",
|
||||||
});
|
});
|
||||||
this.props.onRehydrate();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_handleSearch = () => {
|
_handleSearch = () => {
|
||||||
dispatchCustomEvent({
|
dispatchCustomEvent({
|
||||||
name: "create-modal",
|
name: "create-modal",
|
||||||
detail: { modal: <SearchModal onAction={this.props.onAction} /> },
|
detail: { modal: <SearchModal viewer={this.props.viewer} onAction={this.props.onAction} /> },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -72,10 +71,7 @@ export default class SceneSlates extends React.Component {
|
|||||||
title="Slates"
|
title="Slates"
|
||||||
actions={
|
actions={
|
||||||
this.state.tab === 0 ? (
|
this.state.tab === 0 ? (
|
||||||
<CircleButtonGray
|
<CircleButtonGray onClick={this._handleAdd} style={{ marginLeft: 12 }}>
|
||||||
onClick={this._handleAdd}
|
|
||||||
style={{ marginLeft: 12 }}
|
|
||||||
>
|
|
||||||
<SVG.Plus height="16px" />
|
<SVG.Plus height="16px" />
|
||||||
</CircleButtonGray>
|
</CircleButtonGray>
|
||||||
) : null
|
) : null
|
||||||
@ -106,13 +102,9 @@ export default class SceneSlates extends React.Component {
|
|||||||
<SVG.Video height="24px" style={{ margin: "0 16px" }} />
|
<SVG.Video height="24px" style={{ margin: "0 16px" }} />
|
||||||
</div>
|
</div>
|
||||||
<div style={{ marginTop: 24 }}>
|
<div style={{ marginTop: 24 }}>
|
||||||
Use slates to create mood boards, share files, and organize
|
Use slates to create mood boards, share files, and organize research.
|
||||||
research.
|
|
||||||
</div>
|
</div>
|
||||||
<ButtonSecondary
|
<ButtonSecondary onClick={this._handleAdd} style={{ marginTop: 32 }}>
|
||||||
onClick={this._handleAdd}
|
|
||||||
style={{ marginTop: 32 }}
|
|
||||||
>
|
|
||||||
Create slate
|
Create slate
|
||||||
</ButtonSecondary>
|
</ButtonSecondary>
|
||||||
</EmptyState>
|
</EmptyState>
|
||||||
@ -146,10 +138,7 @@ export default class SceneSlates extends React.Component {
|
|||||||
) : (
|
) : (
|
||||||
<EmptyState>
|
<EmptyState>
|
||||||
You can follow any public slates on the network.
|
You can follow any public slates on the network.
|
||||||
<ButtonSecondary
|
<ButtonSecondary onClick={this._handleSearch} style={{ marginTop: 32 }}>
|
||||||
onClick={this._handleSearch}
|
|
||||||
style={{ marginTop: 32 }}
|
|
||||||
>
|
|
||||||
Browse slates
|
Browse slates
|
||||||
</ButtonSecondary>
|
</ButtonSecondary>
|
||||||
</EmptyState>
|
</EmptyState>
|
||||||
|
@ -45,7 +45,6 @@ export default class SceneTara extends React.Component {
|
|||||||
onAction={this.props.onAction}
|
onAction={this.props.onAction}
|
||||||
viewer={this.props.viewer}
|
viewer={this.props.viewer}
|
||||||
items={this.props.viewer.library[0].children}
|
items={this.props.viewer.library[0].children}
|
||||||
onRehydrate={this.props.onRehydrate}
|
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<EmptyState>
|
<EmptyState>
|
||||||
|
Loading…
Reference in New Issue
Block a user