integration: example subscribe and unsubscribe endpoints with ui example

This commit is contained in:
@wwwjim 2020-08-25 20:13:06 -07:00
parent fad8145360
commit 0af4431bd3
10 changed files with 182 additions and 15 deletions

View File

@ -46,9 +46,23 @@ export const sendFilecoin = async (data) => {
});
};
export const createTrustRelationship = async (data) => {
return await returnJSON(`/api/users/trust`, {
...DEFAULT_OPTIONS,
body: JSON.stringify({ data }),
});
};
export const createSubscription = async (data) => {
return await returnJSON(`/api/subscribe`, {
...DEFAULT_OPTIONS,
body: JSON.stringify({ data }),
});
};
export const search = async (data) => {
if (Strings.isEmpty(data.query)) {
return { decorator: "NO_SERVER_TRIP", data: [] };
return { decorator: "NO_SERVER_TRIP", data: { results: [] } };
}
return await returnJSON(`/api/search/${data.query}`, {

View File

@ -220,8 +220,7 @@ export default class ApplicationPage extends React.Component {
console.log("REHYDRATION CALL", response);
const updates = {
viewer: State.getInitialState(response.data),
selected: State.getSelectedState(response.data),
viewer: response.data,
};
if (options && options.resetFiles) {

View File

@ -37,6 +37,7 @@ import deleteSubscriptionById from "~/node_common/data/methods/delete-subscripti
// NOTE(jim):
// Trust postgres queries
import createTrustedRelationship from "~/node_common/data/methods/create-trusted-relationship";
import updateTrustedRelationshipById from "~/node_common/data/methods/update-trusted-relationship-by-id";
import getTrustedRelationshipsByUserId from "~/node_common/data/methods/get-trusted-relationships-by-user-id";
import getTrustedRelationshipByUserIds from "~/node_common/data/methods/get-trusted-relationship-by-ids";
import getTrustedRelationshipById from "~/node_common/data/methods/get-trusted-relationship-by-id";
@ -86,6 +87,7 @@ export {
deleteSubscriptionById,
// NOTE(jim): Trust operations
createTrustedRelationship,
updateTrustedRelationshipById,
getTrustedRelationshipsByUserId,
getTrustedRelationshipByUserIds,
getTrustedRelationshipById,

View File

@ -7,12 +7,13 @@ export default async ({ ownerUserId, targetUserId }) => {
const query = await DB.insert({
owner_user_id: ownerUserId,
target_user_id: targetUserId,
data: { verified: false },
})
.into("trusted")
.returning("*");
const index = query ? query.pop() : null;
return index;
return JSON.parse(JSON.stringify(index));
},
errorFn: async (e) => {
return {

View File

@ -1,16 +1,22 @@
import { runQuery } from "~/node_common/data/utilities";
export default async ({ subscriberUserId, slateId, userId }) => {
const whereQuery = { owner_user_id: subscriberUserId };
if (slateId) {
whereQuery.target_slate_id = slateId;
}
if (userId) {
whereQuery.target_user_id = userId;
}
return await runQuery({
label: "GET_SUBSCRIPTION_BY_ID",
queryFn: async (DB) => {
const query = await DB.select("*")
.from("subscriptions")
.where({
owner_user_id: subscriberUserId,
target_slate_id: slateId,
target_user_id: userId,
})
.where(whereQuery)
.first();
if (!query || query.error) {

View File

@ -13,7 +13,11 @@ export default async ({ query }) => {
return [];
}
return JSON.parse(JSON.stringify(r));
const sanitized = r.map((each) => {
return { ...each, type: "SLATE" };
});
return JSON.parse(JSON.stringify(sanitized));
},
errorFn: async (e) => {
return {

View File

@ -16,6 +16,9 @@ export default async ({ query }) => {
// TODO(jim): Not a fan of this. Need something more secure.
const sanitized = r.map((each) => {
return {
type: "USER",
id: each.id,
username: each.username,
data: {
name: each.data.name,
photo: each.data.photo,

View File

@ -0,0 +1,22 @@
import { runQuery } from "~/node_common/data/utilities";
export default async ({ id, data }) => {
return await runQuery({
label: "UPDATE_TRUSTED_RELATIONSHIP_BY_ID",
queryFn: async (DB) => {
const response = await DB.from("trusted")
.where("id", id)
.update({ data })
.returning("*");
const index = response ? response.pop() : null;
return JSON.parse(JSON.stringify(index));
},
errorFn: async (e) => {
return {
error: "UPDATE_TRUSTED_RELATIONSHIP_BY_ID",
source: e,
};
},
});
};

View File

@ -5,6 +5,27 @@ import * as Actions from "~/common/actions";
import { css } from "@emotion/react";
const STYLES_ITEM = css`
font-size: 12px;
font-weight: 600;
font-famliy: monaco;
white-space: pre-wrap;
overflow-wrap: break-word;
`;
const STYLES_ROW = css`
display: flex;
align-items: flex-start;
justify-content: space-between;
`;
const STYLES_COLUMN = css`
width: 33.33%;
flex-shrink: 0;
padding: 24px;
box-sizing: border-box;
`;
export const getServerSideProps = async (context) => {
return {
props: { ...context.query },
@ -14,24 +35,118 @@ export const getServerSideProps = async (context) => {
export default class IntegrationPage extends React.Component {
state = {
results: [],
viewer: this.props.viewer,
};
componentDidMount() {}
_handleChange = async (e) => {
const query = e.target.value;
const results = await Actions.search({ query });
this.setState({ results: results.data.results });
};
_handleUpdate = async (e) => {
const response = await Actions.hydrateAuthenticatedUser();
if (!response || response.error) {
alert("TODO: error fetching authenticated viewer");
return null;
}
const updates = {
viewer: response.data,
};
this.setState(updates);
};
_handleTrust = async (user) => {
const response = await Actions.createTrustRelationship({ userId: user.id });
console.log(response);
await this._handleUpdate();
};
_handleSubscribe = async (entity) => {
let response;
if (entity.type === "USER" || entity.target_user_id) {
response = await Actions.createSubscription({
userId: entity.target_user_id ? entity.target_user_id : entity.id,
});
}
if (entity.type === "SLATE" || entity.target_slate_id) {
response = await Actions.createSubscription({
slateId: entity.target_slate_id ? entity.target_slate_id : entity.id,
});
}
await this._handleUpdate();
};
render() {
console.log(this.props.viewer);
console.log({ results: this.state.results });
console.log(this.state.viewer);
return (
<div>
<input type="text" onChange={this._handleChange} />
<div css={STYLES_ROW}>
<div css={STYLES_COLUMN}>
{this.state.viewer.trusted.map((each) => {
return (
<div css={STYLES_ITEM} key={each.id}>
{JSON.stringify(each, null, 1)}{" "}
</div>
);
})}
</div>
<div css={STYLES_COLUMN}>
<button onClick={this._handleUpdate}>
Update {this.state.viewer.username}
</button>
<br />
<input
type="text"
onChange={this._handleChange}
placeholder="type anything to search"
/>
{this.state.results.map((each) => {
if (!each) {
return;
}
return (
<div css={STYLES_ITEM} key={each.id}>
{JSON.stringify(each, null, 1)}{" "}
<div>
{each.type === "USER" ? (
<button onClick={() => this._handleTrust(each)}>
Trust
</button>
) : null}
<button onClick={() => this._handleSubscribe(each)}>
Subscribe
</button>
</div>
</div>
);
})}
</div>
<div css={STYLES_COLUMN}>
{this.state.viewer.subscriptions.map((each) => {
return (
<div css={STYLES_ITEM} key={each.id}>
{JSON.stringify(each, null, 1)}{" "}
<div>
<button onClick={() => this._handleSubscribe(each)}>
Unsubscribe
</button>
</div>
</div>
);
})}
</div>
</div>
);
}

View File

@ -39,6 +39,7 @@ export default async (req, res) => {
});
if (existingResponse && existingResponse.error) {
console.log(existingResponse);
return res.status(500).json({
decorator: "SERVER_SUBSCRIBE_SUBSCRIPTION_CHECK_ERROR",
error: true,