mirror of
https://github.com/filecoin-project/slate.git
synced 2024-11-22 21:45:56 +03:00
slates: creating slates
This commit is contained in:
parent
c446bf92d4
commit
e70c55f4e7
@ -24,7 +24,7 @@ const transformAddresses = (addrsList, info) => {
|
||||
});
|
||||
};
|
||||
|
||||
const transformPeers = (peersList) => {
|
||||
const transformPeers = (peersList = []) => {
|
||||
return peersList.map((each) => {
|
||||
return {
|
||||
id: each.addrInfo.id,
|
||||
@ -73,6 +73,7 @@ export const getInitialState = (props) => {
|
||||
username,
|
||||
storageList,
|
||||
retrievalList,
|
||||
slates,
|
||||
} = props;
|
||||
|
||||
return {
|
||||
@ -114,6 +115,7 @@ export const getInitialState = (props) => {
|
||||
data_transfers: [],
|
||||
storageList,
|
||||
retrievalList,
|
||||
slates,
|
||||
peers: transformPeers(peersList),
|
||||
addresses: transformAddresses(addrsList, info),
|
||||
library,
|
||||
|
@ -11,6 +11,8 @@ export const copyText = (str) => {
|
||||
el.setAttribute("readonly", "");
|
||||
el.style.position = "absolute";
|
||||
el.style.left = "-9999px";
|
||||
el.style.visibility = "hidden";
|
||||
el.style.opacity = "0";
|
||||
document.body.appendChild(el);
|
||||
el.select();
|
||||
document.execCommand("copy");
|
||||
@ -19,6 +21,27 @@ export const copyText = (str) => {
|
||||
return true;
|
||||
};
|
||||
|
||||
export const createSlug = (text) => {
|
||||
if (isEmpty(text)) {
|
||||
return "untitled";
|
||||
}
|
||||
|
||||
const a = "æøåàáäâèéëêìíïîòóöôùúüûñçßÿœæŕśńṕẃǵǹḿǘẍźḧ·/_,:;";
|
||||
const b = "aoaaaaaeeeeiiiioooouuuuncsyoarsnpwgnmuxzh------";
|
||||
const p = new RegExp(a.split("").join("|"), "g");
|
||||
|
||||
return text
|
||||
.toString()
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, "-") // Replace spaces with -
|
||||
.replace(p, (c) => b.charAt(a.indexOf(c))) // Replace special chars
|
||||
.replace(/&/g, "-and-") // Replace & with 'and'
|
||||
.replace(/[^\w\-]+/g, "") // Remove all non-word chars
|
||||
.replace(/\-\-+/g, "-") // Replace multiple - with single -
|
||||
.replace(/^-+/, "") // Trim - from start of text
|
||||
.replace(/-+$/, ""); // Trim - from end of text
|
||||
};
|
||||
|
||||
export const hexToRGBA = (hex, alpha = 1) => {
|
||||
hex = hex.replace("#", "");
|
||||
var r = parseInt(
|
||||
|
83
components/sidebars/SidebarCreateSlate.js
Normal file
83
components/sidebars/SidebarCreateSlate.js
Normal file
@ -0,0 +1,83 @@
|
||||
import * as React from "react";
|
||||
import * as Strings from "~/common/strings";
|
||||
import * as Constants from "~/common/constants";
|
||||
import * as SVG from "~/components/system/svg";
|
||||
import * as System from "~/components/system";
|
||||
|
||||
import { css } from "@emotion/react";
|
||||
|
||||
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
|
||||
export default class SidebarCreateSlate extends React.Component {
|
||||
state = {
|
||||
name: "",
|
||||
loading: false,
|
||||
};
|
||||
|
||||
_handleSubmit = async () => {
|
||||
this.setState({ loading: true });
|
||||
|
||||
if (!Strings.isEmpty) {
|
||||
alert("TODO: Provide a name");
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await this.props.onSubmit({
|
||||
type: "CREATE_SLATE",
|
||||
name: this.state.name,
|
||||
});
|
||||
|
||||
if (response) {
|
||||
// TODO(jim): Error task.
|
||||
alert(response.decorator);
|
||||
}
|
||||
|
||||
this.setState({ loading: false });
|
||||
};
|
||||
|
||||
_handleCancel = () => {
|
||||
this.props.onCancel();
|
||||
};
|
||||
|
||||
_handleChange = (e) => {
|
||||
this.setState({ [e.target.name]: e.target.value });
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<System.P style={{ fontFamily: Constants.font.semiBold }}>
|
||||
Create Slate
|
||||
</System.P>
|
||||
|
||||
<System.Input
|
||||
containerStyle={{ marginTop: 24 }}
|
||||
label="Slate name"
|
||||
name="name"
|
||||
value={this.state.name}
|
||||
onChange={this._handleChange}
|
||||
/>
|
||||
|
||||
<System.P style={{ marginTop: 24 }}>
|
||||
This will create a new slate address at https://slate.host/@
|
||||
{this.props.viewer.username}/{Strings.createSlug(this.state.name)}
|
||||
</System.P>
|
||||
|
||||
<System.ButtonPrimaryFull
|
||||
style={{ marginTop: 48 }}
|
||||
onClick={this._handleSubmit}
|
||||
loading={this.state.loading}
|
||||
>
|
||||
Create {this.state.name}
|
||||
</System.ButtonPrimaryFull>
|
||||
|
||||
<System.ButtonSecondaryFull
|
||||
style={{ marginTop: 16 }}
|
||||
onClick={this._handleSubmit}
|
||||
>
|
||||
Cancel
|
||||
</System.ButtonSecondaryFull>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
@ -295,6 +295,19 @@ export const TableContent = ({
|
||||
</span>
|
||||
);
|
||||
});
|
||||
case "SLATE_PUBLIC_TEXT_TAG":
|
||||
return !text ? (
|
||||
<span css={STYLES_TABLE_TAG}>Private</span>
|
||||
) : (
|
||||
<span
|
||||
css={STYLES_TABLE_TAG}
|
||||
style={{ background: Constants.system.green }}
|
||||
>
|
||||
{text}
|
||||
</span>
|
||||
);
|
||||
case "TEXT_TAG":
|
||||
return <span css={STYLES_TABLE_TAG}>{text}</span>;
|
||||
|
||||
case "FILE_DATE":
|
||||
return Strings.toDate(text);
|
||||
|
@ -7,6 +7,7 @@ import getUserById from "~/node_common/data/methods/get-user-by-id";
|
||||
import createSlate from "~/node_common/data/methods/create-slate";
|
||||
import getSlateByName from "~/node_common/data/methods/get-slate-by-name";
|
||||
import getSlateById from "~/node_common/data/methods/get-slate-by-id";
|
||||
import getSlatesByUserId from "~/node_common/data/methods/get-slates-by-user-id";
|
||||
import updateSlateById from "~/node_common/data/methods/update-slate-by-id";
|
||||
|
||||
export {
|
||||
@ -20,5 +21,6 @@ export {
|
||||
createSlate,
|
||||
getSlateByName,
|
||||
getSlateById,
|
||||
getSlatesByUserId,
|
||||
updateSlateById,
|
||||
};
|
||||
|
27
node_common/data/methods/get-slates-by-user-id.js
Normal file
27
node_common/data/methods/get-slates-by-user-id.js
Normal file
@ -0,0 +1,27 @@
|
||||
import { runQuery } from "~/node_common/data/utilities";
|
||||
|
||||
export default async ({ userId }) => {
|
||||
return await runQuery({
|
||||
label: "GET_SLATES_BY_USER_ID",
|
||||
queryFn: async (DB) => {
|
||||
const hasUser = (id) =>
|
||||
DB.raw(`?? @> ?::jsonb`, ["data", JSON.stringify({ ownerId: id })]);
|
||||
|
||||
let query = await DB.select("*")
|
||||
.from("slates")
|
||||
.where(hasUser(userId));
|
||||
|
||||
if (!query || query.error) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return query;
|
||||
},
|
||||
errorFn: async (e) => {
|
||||
return {
|
||||
error: "GET_SLATES_BY_USER_ID",
|
||||
source: e,
|
||||
};
|
||||
},
|
||||
});
|
||||
};
|
@ -16,8 +16,9 @@ export const getById = async ({ id }) => {
|
||||
}
|
||||
|
||||
let data = null;
|
||||
const response = await Data.getSlatesByUserId({ userId: id });
|
||||
const slates = JSON.parse(JSON.stringify(response));
|
||||
|
||||
// NOTE(jim): Essential for getting the right Powergate data for a user.
|
||||
try {
|
||||
data = {
|
||||
id: user.id,
|
||||
@ -29,7 +30,7 @@ export const getById = async ({ id }) => {
|
||||
library: user.data.library,
|
||||
storageList: [],
|
||||
retrievalList: [],
|
||||
peersList: null,
|
||||
slates,
|
||||
messageList: null,
|
||||
status: null,
|
||||
addrsList: null,
|
||||
|
@ -67,10 +67,7 @@ export const refresh = async (user) => {
|
||||
const status = Health.status ? Health.status : null;
|
||||
const messageList = Health.messageList ? Health.messageList : null;
|
||||
|
||||
const Peers = await PG.net.peers();
|
||||
const peersList = Peers.peersList ? Peers.peersList : null;
|
||||
|
||||
return { peersList, messageList, status };
|
||||
return { messageList, status };
|
||||
};
|
||||
|
||||
// NOTE(jim): Requires Powergate & authentication
|
||||
|
70
pages/api/slates/create.js
Normal file
70
pages/api/slates/create.js
Normal file
@ -0,0 +1,70 @@
|
||||
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";
|
||||
import * as Powergate from "~/node_common/powergate";
|
||||
|
||||
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_FIND_USER_CREATE_SLATE", error: true });
|
||||
}
|
||||
|
||||
const user = await Data.getUserById({
|
||||
id,
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return res
|
||||
.status(500)
|
||||
.json({ decorator: "SERVER_FIND_USER_CREATE_SLATE", error: true });
|
||||
}
|
||||
|
||||
if (user.error) {
|
||||
return res
|
||||
.status(500)
|
||||
.json({ decorator: "SERVER_FIND_USER_CREATE_SLATE", error: true });
|
||||
}
|
||||
|
||||
const slatename = Strings.createSlug(req.body.data.name);
|
||||
|
||||
const found = await Data.getSlateByName({ slatename });
|
||||
console.log(found);
|
||||
|
||||
if (found) {
|
||||
return res
|
||||
.status(500)
|
||||
.json({ decorator: "SERVER_EXISTING_SLATE", error: true });
|
||||
}
|
||||
|
||||
const slate = await Data.createSlate({
|
||||
slatename,
|
||||
data: {
|
||||
ownerId: id,
|
||||
name: req.body.data.name,
|
||||
objects: [],
|
||||
},
|
||||
});
|
||||
|
||||
if (!slate) {
|
||||
return res
|
||||
.status(500)
|
||||
.json({ decorator: "SERVER_CREATE_SLATE", error: true });
|
||||
}
|
||||
|
||||
if (slate.error) {
|
||||
return res
|
||||
.status(500)
|
||||
.json({ decorator: "SERVER_CREATE_SLATE", error: true });
|
||||
}
|
||||
|
||||
return res.status(200).json({ decorator: "SERVER_CREATE_SLATE", slate });
|
||||
};
|
@ -24,6 +24,7 @@ import SceneLocalData from "~/scenes/SceneLocalData";
|
||||
import SceneSettingsDeveloper from "~/scenes/SceneSettingsDeveloper";
|
||||
import SceneSignIn from "~/scenes/SceneSignIn";
|
||||
|
||||
import SidebarCreateSlate from "~/components/sidebars/SidebarCreateSlate";
|
||||
import SidebarCreateWalletAddress from "~/components/sidebars/SidebarCreateWalletAddress";
|
||||
import SidebarDeleteWalletAddress from "~/components/sidebars/SidebarDeleteWalletAddress";
|
||||
import SidebarWalletSendFunds from "~/components/sidebars/SidebarWalletSendFunds";
|
||||
@ -193,8 +194,15 @@ export default class ApplicationPage extends React.Component {
|
||||
};
|
||||
|
||||
_handleSubmit = async (data) => {
|
||||
let response;
|
||||
if (data.type === "CREATE_SLATE") {
|
||||
response = await Actions.createSlate({
|
||||
name: data.name,
|
||||
});
|
||||
}
|
||||
|
||||
if (data.type === "CREATE_WALLET_ADDRESS") {
|
||||
const address = await Actions.updateViewer({
|
||||
response = await Actions.updateViewer({
|
||||
type: "CREATE_FILECOIN_ADDRESS",
|
||||
address: {
|
||||
name: data.name,
|
||||
@ -205,16 +213,20 @@ export default class ApplicationPage extends React.Component {
|
||||
}
|
||||
|
||||
if (data.type === "SEND_WALLET_ADDRESS_FILECOIN") {
|
||||
const response = await Actions.sendFilecoin({
|
||||
response = await Actions.sendFilecoin({
|
||||
source: data.source,
|
||||
target: data.target,
|
||||
amount: data.amount,
|
||||
});
|
||||
}
|
||||
|
||||
console.log({ response });
|
||||
|
||||
await this.rehydrate();
|
||||
|
||||
this._handleDismissSidebar();
|
||||
|
||||
return response;
|
||||
};
|
||||
|
||||
_handleCancel = () => {
|
||||
@ -399,6 +411,7 @@ export default class ApplicationPage extends React.Component {
|
||||
SIDEBAR_DELETE_WALLET_ADDRESS: <SidebarDeleteWalletAddress />,
|
||||
SIDEBAR_REDEEM_PAYMENT_CHANNEL: <SidebarRedeemPaymentChannel />,
|
||||
SIDEBAR_ADD_FILE_TO_BUCKET: <SidebarAddFileToBucket />,
|
||||
SIDEBAR_CREATE_SLATE: <SidebarCreateSlate />,
|
||||
};
|
||||
|
||||
scenes = {
|
||||
|
@ -51,60 +51,122 @@ export default class SceneHome extends React.Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
console.log(this.props.viewer.slates);
|
||||
// TODO(jim): Refactor later.
|
||||
const slates = {
|
||||
columns: [
|
||||
{ key: "id", id: "id", name: "ID" },
|
||||
{ key: "slatename", name: "Slate Name", width: "228px" },
|
||||
{ key: "url", name: "URL", width: "268px" },
|
||||
{
|
||||
key: "public",
|
||||
name: "Public",
|
||||
type: "SLATE_PUBLIC_TEXT_TAG",
|
||||
width: "188px",
|
||||
},
|
||||
],
|
||||
rows: this.props.viewer.slates.map((each) => {
|
||||
return {
|
||||
...each,
|
||||
url: `https://slate.host/@${this.props.viewer.username}/${
|
||||
each.slatename
|
||||
}`,
|
||||
public: false,
|
||||
};
|
||||
}),
|
||||
};
|
||||
|
||||
// TODO(jim): Refactor later.
|
||||
const slateButtons = [
|
||||
{ name: "Create slate", type: "SIDEBAR", value: "SIDEBAR_CREATE_SLATE" },
|
||||
];
|
||||
|
||||
// TODO(jim): Refactor later.
|
||||
const data = {
|
||||
columns: [
|
||||
{ key: "name", name: "Data", type: "FILE_LINK" },
|
||||
{
|
||||
key: "size",
|
||||
name: "Size",
|
||||
width: "140px",
|
||||
type: "FILE_SIZE",
|
||||
},
|
||||
{
|
||||
key: "date",
|
||||
name: "Date uploaded",
|
||||
width: "160px",
|
||||
type: "FILE_DATE",
|
||||
tooltip:
|
||||
"This date represents when the file was first uploaded to IPFS.",
|
||||
},
|
||||
{
|
||||
key: "networks",
|
||||
name: "Network",
|
||||
type: "NETWORK_TYPE",
|
||||
width: "188px",
|
||||
},
|
||||
],
|
||||
rows: this.props.viewer.library[0].children.map((each) => {
|
||||
return {
|
||||
...each,
|
||||
button: "Store on Filecoin",
|
||||
};
|
||||
}),
|
||||
};
|
||||
|
||||
// TODO(jim): Refactor later.
|
||||
const dataButtons = [
|
||||
{
|
||||
name: "View files",
|
||||
type: "NAVIGATE",
|
||||
value: this.props.viewer.library[0].folderId,
|
||||
},
|
||||
{
|
||||
name: "Upload to IPFS",
|
||||
type: "SIDEBAR",
|
||||
value: "SIDEBAR_ADD_FILE_TO_BUCKET",
|
||||
},
|
||||
];
|
||||
|
||||
// TODO(jim): Refactor later.
|
||||
const wallet = {
|
||||
columns: [
|
||||
{ key: "address", name: "Address" },
|
||||
{ key: "balance", name: "Filecoin", width: "228px" },
|
||||
{ key: "type", name: "Type", width: "188px", type: "TEXT_TAG" },
|
||||
],
|
||||
rows: this.props.viewer.addresses,
|
||||
};
|
||||
|
||||
// TODO(jim): Refactor later.
|
||||
const walletButtons = [
|
||||
{
|
||||
name: "View all",
|
||||
type: "NAVIGATE",
|
||||
value: 2,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<ScenePage>
|
||||
<GLRenderer width={1200} height={480} />
|
||||
<Section
|
||||
title="Slates"
|
||||
buttons={slateButtons}
|
||||
onAction={this.props.onAction}
|
||||
>
|
||||
<System.Table data={slates} name="slate" />
|
||||
</Section>
|
||||
|
||||
{this.props.viewer.library[0] ? (
|
||||
<Section
|
||||
onAction={this.props.onAction}
|
||||
onNavigateTo={this.props.onNavigateTo}
|
||||
title="Recent data"
|
||||
buttons={[
|
||||
{
|
||||
name: "View files",
|
||||
type: "NAVIGATE",
|
||||
value: this.props.viewer.library[0].folderId,
|
||||
},
|
||||
{
|
||||
name: "Upload to IPFS",
|
||||
type: "SIDEBAR",
|
||||
value: "SIDEBAR_ADD_FILE_TO_BUCKET",
|
||||
},
|
||||
]}
|
||||
buttons={dataButtons}
|
||||
>
|
||||
<System.Table
|
||||
data={{
|
||||
columns: [
|
||||
{ key: "name", name: "Data", type: "FILE_LINK" },
|
||||
{
|
||||
key: "size",
|
||||
name: "Size",
|
||||
width: "140px",
|
||||
type: "FILE_SIZE",
|
||||
},
|
||||
{
|
||||
key: "date",
|
||||
name: "Date uploaded",
|
||||
width: "160px",
|
||||
type: "FILE_DATE",
|
||||
tooltip:
|
||||
"This date represents when the file was first uploaded to IPFS.",
|
||||
},
|
||||
{
|
||||
key: "networks",
|
||||
name: "Network",
|
||||
type: "NETWORK_TYPE",
|
||||
},
|
||||
],
|
||||
rows: this.props.viewer.library[0].children.map((each) => {
|
||||
return {
|
||||
...each,
|
||||
button: "Store on Filecoin",
|
||||
};
|
||||
}),
|
||||
}}
|
||||
selectedRowId={this.state.data}
|
||||
onChange={this._handleChange}
|
||||
data={data}
|
||||
onAction={this.props.onAction}
|
||||
onNavigateTo={this.props.onNavigateTo}
|
||||
name="data"
|
||||
@ -117,25 +179,10 @@ export default class SceneHome extends React.Component {
|
||||
onAction={this.props.onAction}
|
||||
onNavigateTo={this.props.onNavigateTo}
|
||||
title="Wallet addresses"
|
||||
buttons={[
|
||||
{
|
||||
name: "View all",
|
||||
type: "NAVIGATE",
|
||||
value: 2,
|
||||
},
|
||||
]}
|
||||
buttons={walletButtons}
|
||||
>
|
||||
<System.Table
|
||||
data={{
|
||||
columns: [
|
||||
{ key: "address", name: "Address" },
|
||||
{ key: "balance", name: "Filecoin", width: "228px" },
|
||||
{ key: "type", name: "Type" },
|
||||
],
|
||||
rows: this.props.viewer.addresses,
|
||||
}}
|
||||
selectedRowId={this.state.transaction}
|
||||
onChange={this._handleChange}
|
||||
data={wallet}
|
||||
onAction={this.props.onAction}
|
||||
onNavigateTo={this.props.onNavigateTo}
|
||||
name="transaction"
|
||||
|
@ -9,16 +9,14 @@ const db = knex(envConfig);
|
||||
|
||||
console.log(`RUNNING: seed-database.js`);
|
||||
|
||||
/*
|
||||
const u = db.schema.table("slates", function(table) {
|
||||
table
|
||||
.integer("slatename")
|
||||
.string("slatename")
|
||||
.unique()
|
||||
.nullable();
|
||||
});
|
||||
*/
|
||||
|
||||
Promise.all([]);
|
||||
Promise.all([u]);
|
||||
|
||||
console.log(`FINISHED: seed-database.js`);
|
||||
console.log(` CTRL +C to return to terminal.`);
|
||||
|
Loading…
Reference in New Issue
Block a user