mirror of
https://github.com/filecoin-project/slate.git
synced 2024-12-24 01:23:08 +03:00
slates: supports deleting slates
This commit is contained in:
parent
a23b8b9926
commit
e79f611fda
@ -8,6 +8,19 @@ const REQUEST_HEADERS = {
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
|
||||
const DEFAULT_OPTIONS = {
|
||||
method: "POST",
|
||||
headers: REQUEST_HEADERS,
|
||||
credentials: "include",
|
||||
};
|
||||
|
||||
const returnJSON = async (route, options) => {
|
||||
const response = await fetch(route, options);
|
||||
const json = await response.json();
|
||||
|
||||
return json;
|
||||
};
|
||||
|
||||
export const sendFilecoin = async (data) => {
|
||||
if (Strings.isEmpty(data.source)) {
|
||||
return null;
|
||||
@ -21,158 +34,96 @@ export const sendFilecoin = async (data) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
const options = {
|
||||
method: "POST",
|
||||
headers: REQUEST_HEADERS,
|
||||
credentials: "include",
|
||||
return await returnJSON(`/api/addresses/send`, {
|
||||
...DEFAULT_OPTIONS,
|
||||
body: JSON.stringify({ data }),
|
||||
};
|
||||
|
||||
const response = await fetch(`/api/addresses/send`, options);
|
||||
const json = await response.json();
|
||||
|
||||
return json;
|
||||
});
|
||||
};
|
||||
|
||||
export const updateViewer = async (data) => {
|
||||
const options = {
|
||||
method: "POST",
|
||||
headers: REQUEST_HEADERS,
|
||||
credentials: "include",
|
||||
return await returnJSON(`/api/users/update`, {
|
||||
...DEFAULT_OPTIONS,
|
||||
body: JSON.stringify(data),
|
||||
};
|
||||
|
||||
const response = await fetch(`/api/users/update`, options);
|
||||
const json = await response.json();
|
||||
|
||||
return json;
|
||||
});
|
||||
};
|
||||
|
||||
export const signIn = async (data) => {
|
||||
const options = {
|
||||
method: "POST",
|
||||
headers: REQUEST_HEADERS,
|
||||
credentials: "include",
|
||||
return await returnJSON(`/api/sign-in`, {
|
||||
...DEFAULT_OPTIONS,
|
||||
body: JSON.stringify({ data }),
|
||||
};
|
||||
|
||||
const response = await fetch(`/api/sign-in`, options);
|
||||
const json = await response.json();
|
||||
|
||||
return json;
|
||||
});
|
||||
};
|
||||
|
||||
export const hydrateAuthenticatedUser = async () => {
|
||||
const options = {
|
||||
method: "POST",
|
||||
headers: REQUEST_HEADERS,
|
||||
credentials: "include",
|
||||
};
|
||||
|
||||
const response = await fetch(`/api/hydrate`, options);
|
||||
const json = await response.json();
|
||||
|
||||
return json;
|
||||
return await returnJSON(`/api/hydrate`, {
|
||||
...DEFAULT_OPTIONS,
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteViewer = async () => {
|
||||
const options = {
|
||||
method: "DELETE",
|
||||
headers: REQUEST_HEADERS,
|
||||
credentials: "include",
|
||||
};
|
||||
|
||||
const response = await fetch(`/api/users/delete`, options);
|
||||
const json = await response.json();
|
||||
return json;
|
||||
return await returnJSON(`/api/users/delete`, {
|
||||
...DEFAULT_OPTIONS,
|
||||
});
|
||||
};
|
||||
|
||||
export const createUser = async (data) => {
|
||||
const options = {
|
||||
method: "POST",
|
||||
headers: REQUEST_HEADERS,
|
||||
credentials: "include",
|
||||
return await returnJSON(`/api/users/create`, {
|
||||
...DEFAULT_OPTIONS,
|
||||
body: JSON.stringify({ data }),
|
||||
};
|
||||
|
||||
const response = await fetch(`/api/users/create`, options);
|
||||
const json = await response.json();
|
||||
return json;
|
||||
});
|
||||
};
|
||||
|
||||
export const checkCIDStatus = async (data) => {
|
||||
const options = {
|
||||
method: "POST",
|
||||
headers: REQUEST_HEADERS,
|
||||
credentials: "include",
|
||||
return await returnJSON(`/api/data/cid-status`, {
|
||||
...DEFAULT_OPTIONS,
|
||||
body: JSON.stringify({ data }),
|
||||
};
|
||||
|
||||
const response = await fetch(`/api/data/cid-status`, options);
|
||||
const json = await response.json();
|
||||
return json;
|
||||
});
|
||||
};
|
||||
|
||||
export const health = async (data) => {
|
||||
const options = {
|
||||
method: "POST",
|
||||
headers: REQUEST_HEADERS,
|
||||
credentials: "include",
|
||||
return await returnJSON(`/api/_`, {
|
||||
...DEFAULT_OPTIONS,
|
||||
body: JSON.stringify({ data: { success: true } }),
|
||||
};
|
||||
|
||||
const response = await fetch(`/api/_`, options);
|
||||
const json = await response.json();
|
||||
return json;
|
||||
});
|
||||
};
|
||||
|
||||
export const createSlate = async (data) => {
|
||||
const options = {
|
||||
method: "POST",
|
||||
headers: REQUEST_HEADERS,
|
||||
credentials: "include",
|
||||
return await returnJSON(`/api/slates/create`, {
|
||||
...DEFAULT_OPTIONS,
|
||||
body: JSON.stringify({ data }),
|
||||
};
|
||||
|
||||
const response = await fetch(`/api/slates/create`, options);
|
||||
const json = await response.json();
|
||||
return json;
|
||||
});
|
||||
};
|
||||
|
||||
export const updateSlate = async (data) => {
|
||||
const options = {
|
||||
method: "POST",
|
||||
headers: REQUEST_HEADERS,
|
||||
credentials: "include",
|
||||
return await returnJSON(`/api/slates/update`, {
|
||||
...DEFAULT_OPTIONS,
|
||||
body: JSON.stringify({ data }),
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const response = await fetch(`/api/slates/update`, options);
|
||||
const json = await response.json();
|
||||
return json;
|
||||
export const deleteSlate = async (data) => {
|
||||
return await returnJSON(`/api/slates/delete`, {
|
||||
...DEFAULT_OPTIONS,
|
||||
body: JSON.stringify({ data }),
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteSlateItem = async (data) => {
|
||||
return await returnJSON(`/api/slates/remove-item`, {
|
||||
...DEFAULT_OPTIONS,
|
||||
body: JSON.stringify({ data }),
|
||||
});
|
||||
};
|
||||
|
||||
export const generateAPIKey = async () => {
|
||||
const options = {
|
||||
method: "POST",
|
||||
headers: REQUEST_HEADERS,
|
||||
credentials: "include",
|
||||
};
|
||||
|
||||
const response = await fetch(`/api/keys/generate`, options);
|
||||
const json = await response.json();
|
||||
return json;
|
||||
return await returnJSON(`/api/keys/generate`, {
|
||||
...DEFAULT_OPTIONS,
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteAPIKey = async (data) => {
|
||||
const options = {
|
||||
method: "POST",
|
||||
headers: REQUEST_HEADERS,
|
||||
credentials: "include",
|
||||
return await returnJSON(`/api/keys/delete`, {
|
||||
...DEFAULT_OPTIONS,
|
||||
body: JSON.stringify({ data }),
|
||||
};
|
||||
|
||||
const response = await fetch(`/api/keys/delete`, options);
|
||||
const json = await response.json();
|
||||
return json;
|
||||
});
|
||||
};
|
||||
|
@ -104,7 +104,7 @@ const Item = ({
|
||||
return (
|
||||
<span
|
||||
css={STYLES_NAVIGATION_ITEM}
|
||||
style={{ padding: `0 0 0 ${level * 16}px` }}
|
||||
style={{ padding: `0 24px 0 ${level * 16}px` }}
|
||||
>
|
||||
<span css={STYLES_EXPANDER} onClick={onToggleShow ? onToggleShow : null}>
|
||||
<span
|
||||
|
@ -10,6 +10,7 @@ import getSlateById from "~/node_common/data/methods/get-slate-by-id";
|
||||
import getSlatesByUserId from "~/node_common/data/methods/get-slates-by-user-id";
|
||||
import updateSlateById from "~/node_common/data/methods/update-slate-by-id";
|
||||
import deleteSlatesForUserId from "~/node_common/data/methods/delete-slates-for-user-id";
|
||||
import deleteSlateById from "~/node_common/data/methods/delete-slate-by-id";
|
||||
|
||||
import createAPIKeyForUserId from "~/node_common/data/methods/create-api-key-for-user-id";
|
||||
import deleteAPIKeyById from "~/node_common/data/methods/delete-api-key-by-id";
|
||||
@ -32,6 +33,7 @@ export {
|
||||
getSlatesByUserId,
|
||||
updateSlateById,
|
||||
deleteSlatesForUserId,
|
||||
deleteSlateById,
|
||||
// NOTE(jim): API key operations,
|
||||
createAPIKeyForUserId,
|
||||
deleteAPIKeyById,
|
||||
|
20
node_common/data/methods/delete-slate-by-id.js
Normal file
20
node_common/data/methods/delete-slate-by-id.js
Normal file
@ -0,0 +1,20 @@
|
||||
import { runQuery } from "~/node_common/data/utilities";
|
||||
|
||||
export default async ({ id }) => {
|
||||
return await runQuery({
|
||||
label: "DELETE_SLATE_BY_ID",
|
||||
queryFn: async (DB) => {
|
||||
const data = await DB.from("slates")
|
||||
.where({ id })
|
||||
.del();
|
||||
|
||||
return 1 === data;
|
||||
},
|
||||
errorFn: async (e) => {
|
||||
return {
|
||||
error: "DELETE_SLATE_BY_ID",
|
||||
source: e,
|
||||
};
|
||||
},
|
||||
});
|
||||
};
|
@ -4,8 +4,12 @@ export default async ({ userId }) => {
|
||||
return await runQuery({
|
||||
label: "DELETE_SLATES_FOR_USER_ID",
|
||||
queryFn: async (DB) => {
|
||||
const hasUser = (id) => DB.raw(`?? @> ?::jsonb`, ["data", JSON.stringify({ ownerId: id })]);
|
||||
const data = await DB.select("*").from("slates").where(hasUser(userId)).del();
|
||||
const hasUser = (id) =>
|
||||
DB.raw(`?? @> ?::jsonb`, ["data", JSON.stringify({ ownerId: id })]);
|
||||
const data = await DB.select("*")
|
||||
.from("slates")
|
||||
.where(hasUser(userId))
|
||||
.del();
|
||||
|
||||
return 1 === data;
|
||||
},
|
||||
|
69
pages/api/slates/delete.js
Normal file
69
pages/api/slates/delete.js
Normal file
@ -0,0 +1,69 @@
|
||||
import * as MW from "~/node_common/middleware";
|
||||
import * as Utilities from "~/node_common/utilities";
|
||||
import * as Data from "~/node_common/data";
|
||||
import * as Strings from "~/common/strings";
|
||||
|
||||
const initCORS = MW.init(MW.CORS);
|
||||
const initAuth = MW.init(MW.RequireCookieAuthentication);
|
||||
|
||||
export default async (req, res) => {
|
||||
initCORS(req, res);
|
||||
initAuth(req, res);
|
||||
|
||||
const id = Utilities.getIdFromCookie(req);
|
||||
if (!id) {
|
||||
return res
|
||||
.status(500)
|
||||
.json({ decorator: "SERVER_DELETE_SLATE", error: true });
|
||||
}
|
||||
|
||||
const user = await Data.getUserById({
|
||||
id,
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
decorator: "SERVER_DELETE_SLATE_USER_NOT_FOUND",
|
||||
error: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (user.error) {
|
||||
return res.status(500).json({
|
||||
decorator: "SERVER_DELETE_SLATE_USER_NOT_FOUND",
|
||||
error: true,
|
||||
});
|
||||
}
|
||||
|
||||
const slate = await Data.getSlateById({ id: req.body.data.id });
|
||||
|
||||
if (!slate) {
|
||||
return res
|
||||
.status(404)
|
||||
.json({ decorator: "SERVER_DELETE_SLATE_SLATE_NOT_FOUND", error: true });
|
||||
}
|
||||
|
||||
if (slate.error) {
|
||||
return res
|
||||
.status(500)
|
||||
.json({ decorator: "SERVER_DELETE_SLATE_SLATE_NOT_FOUND", error: true });
|
||||
}
|
||||
|
||||
const deleteResponse = await Data.deleteSlateById({ id: slate.id });
|
||||
|
||||
if (!deleteResponse) {
|
||||
return res
|
||||
.status(404)
|
||||
.json({ decorator: "SERVER_DELETE_SLATE", error: true });
|
||||
}
|
||||
|
||||
if (deleteResponse.error) {
|
||||
return res
|
||||
.status(500)
|
||||
.json({ decorator: "SERVER_DELETE_SLATE", error: true });
|
||||
}
|
||||
|
||||
return res
|
||||
.status(200)
|
||||
.json({ decorator: "SERVER_DELETE_SLATE", error: false });
|
||||
};
|
@ -72,6 +72,35 @@ export default class SceneSlate extends React.Component {
|
||||
this.setState({ loading: false });
|
||||
};
|
||||
|
||||
_handleDelete = async (e) => {
|
||||
this.setState({ loading: true });
|
||||
|
||||
if (
|
||||
!window.confirm(
|
||||
"Are you sure you want to delete this Slate? This action is irreversible."
|
||||
)
|
||||
) {
|
||||
return this.setState({ loading: false });
|
||||
}
|
||||
|
||||
const response = await Actions.deleteSlate({
|
||||
id: this.props.current.slateId,
|
||||
});
|
||||
|
||||
if (!response) {
|
||||
alert("TODO: Server Error");
|
||||
return this.setState({ loading: false });
|
||||
}
|
||||
|
||||
if (response.error) {
|
||||
alert(`TODO: ${response.decorator}`);
|
||||
return this.setState({ loading: false });
|
||||
}
|
||||
|
||||
await this.props.onAction({ type: "NAVIGATE", value: 3, data: {} });
|
||||
return await this.props.onRehydrate();
|
||||
};
|
||||
|
||||
_handleChange = (e) => {
|
||||
if (e && e.persist) {
|
||||
e.persist();
|
||||
@ -176,6 +205,21 @@ export default class SceneSlate extends React.Component {
|
||||
Save changes
|
||||
</System.ButtonPrimary>
|
||||
</div>
|
||||
|
||||
<System.DescriptionGroup
|
||||
style={{ marginTop: 48 }}
|
||||
label="Delete this slate"
|
||||
description="This action is irreversible."
|
||||
/>
|
||||
|
||||
<div style={{ marginTop: 32 }}>
|
||||
<System.ButtonSecondary
|
||||
onClick={this._handleDelete}
|
||||
loading={this.state.loading}
|
||||
>
|
||||
Delete {this.state.slatename}
|
||||
</System.ButtonSecondary>
|
||||
</div>
|
||||
</ScenePage>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user