implement just for you pages with phoenix-react
This commit is contained in:
parent
bb09b926d9
commit
7b82a95e01
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"presets": [
|
||||
"@babel/preset-env"
|
||||
"@babel/preset-env",
|
||||
"@babel/preset-react"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* This file is for your main application css. */
|
||||
@import "./phoenix.css";
|
||||
/* @import "./phoenix.css"; */
|
||||
|
||||
/* LiveView specific classes for your customizations */
|
||||
.phx-no-feedback.invalid-feedback,
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// We need to import the CSS so that webpack will load it.
|
||||
// The MiniCssExtractPlugin is used to separate it out into
|
||||
// its own CSS file.
|
||||
// import "../css/app.css"
|
||||
import "react-phoenix"
|
||||
import "../css/app.css"
|
||||
// const _css = require("../css/app.css");
|
||||
|
||||
// webpack automatically bundles all modules in your
|
||||
|
@ -17,10 +18,11 @@ import "phoenix_html"
|
|||
import {Socket} from "phoenix"
|
||||
import topbar from "topbar"
|
||||
import {LiveSocket} from "phoenix_live_view"
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
import SplashPage from './pages/SplashPage';
|
||||
import { GlobalStyle } from '@intended/intended-ui';
|
||||
import JustPage from './pages/JustPage'
|
||||
import ForPage from './pages/ForPage'
|
||||
import YouPage from './pages/YouPage'
|
||||
|
||||
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
|
||||
let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}})
|
||||
|
@ -39,10 +41,34 @@ liveSocket.connect()
|
|||
// >> liveSocket.disableLatencySim()
|
||||
window.liveSocket = liveSocket
|
||||
|
||||
ReactDOM.render(<div>
|
||||
<GlobalStyle />
|
||||
<SplashPage />
|
||||
</div>
|
||||
,
|
||||
document.getElementById("root")
|
||||
);
|
||||
window.Components = {
|
||||
SplashPage, JustPage, ForPage, YouPage
|
||||
}
|
||||
|
||||
// const root_el = document.getElementById("root");
|
||||
// const page = root_el.getAttribute("page")
|
||||
// let result;
|
||||
|
||||
// switch(page) {
|
||||
// case "splash":
|
||||
// result = <SplashPage />
|
||||
// break;
|
||||
// case "just":
|
||||
// result = <JustPage />
|
||||
// break;
|
||||
// case "for":
|
||||
// case "you":
|
||||
// case "identify":
|
||||
// case "revealed":
|
||||
// default:
|
||||
// null
|
||||
// break;
|
||||
// }
|
||||
|
||||
// ReactDOM.render(<React.StrictMode>
|
||||
// <GlobalStyle />
|
||||
// { result }
|
||||
// </React.StrictMode>
|
||||
// ,
|
||||
// root_el
|
||||
// );
|
|
@ -0,0 +1,61 @@
|
|||
import React, { useState } from "react";
|
||||
|
||||
import { ProgressIndicator, Header2, Button, IconArrow, Label, Input, Select, CenteredContainer, SpaceBetweenContainer, Spacer, TextAlignWrapper, GlobalStyle } from "@intended/intended-ui";
|
||||
|
||||
const ForPage = () => {
|
||||
const [recipientInput, setRecipientInput] = useState("");
|
||||
const [serviceSelect, setServiceSelect] = useState("");
|
||||
|
||||
const handleRecipientInputChange = (
|
||||
e: React.ChangeEvent<HTMLInputElement>
|
||||
) => {
|
||||
setRecipientInput(e.target.value);
|
||||
};
|
||||
|
||||
const handleServiceChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
setServiceSelect(e.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<React.StrictMode>
|
||||
<GlobalStyle />
|
||||
<CenteredContainer fullscreen>
|
||||
<CenteredContainer>
|
||||
<ProgressIndicator currentProgress={2} />
|
||||
<Header2>Tell Someone</Header2>
|
||||
<SpaceBetweenContainer>
|
||||
<Label htmlFor="recipientInput">Who gets to know the secret?</Label>
|
||||
<Label htmlFor="recipientInput">Required*</Label>
|
||||
</SpaceBetweenContainer>
|
||||
<Input
|
||||
variant="primary"
|
||||
id="recipientInput"
|
||||
value={recipientInput}
|
||||
onChange={handleRecipientInputChange}
|
||||
placeholder="Username or Email"
|
||||
/>
|
||||
<Spacer space="2.5rem" />
|
||||
<TextAlignWrapper align="left">
|
||||
<Label htmlFor="serviceSelector">
|
||||
What type of account is the above username or email associated with?
|
||||
</Label>
|
||||
</TextAlignWrapper>
|
||||
<Select
|
||||
id="serviceSelector"
|
||||
onChange={handleServiceChange}
|
||||
value={serviceSelect}
|
||||
/>
|
||||
<Spacer space="3rem" />
|
||||
<SpaceBetweenContainer>
|
||||
<Button variant="secondary" onClick={() => window.location.href = "/just"}>
|
||||
<IconArrow arrowDirection="left" />
|
||||
</Button>
|
||||
<Button onClick={() => window.location.href = "/just/for/you"}>Generate Secret Code</Button>
|
||||
</SpaceBetweenContainer>
|
||||
</CenteredContainer>
|
||||
</CenteredContainer>
|
||||
</React.StrictMode>
|
||||
);
|
||||
};
|
||||
|
||||
export default ForPage;
|
|
@ -0,0 +1,57 @@
|
|||
import React, { useState } from "react";
|
||||
|
||||
import { ProgressIndicator, Header2, Button, IconArrow, Label, FileInput, TextArea, CenteredContainer, Spacer, TextAlignWrapper, GlobalStyle } from '@intended/intended-ui';
|
||||
|
||||
const JustPage = () => {
|
||||
const [secretInput, setSecretInput] = useState("");
|
||||
const [fileInput, setFileInput] = useState<File | null>(null);
|
||||
const [fileName, setFileName] = useState("");
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||
setSecretInput(e.target.value);
|
||||
};
|
||||
|
||||
const handleFile = (file: File) => {
|
||||
setFileInput(file);
|
||||
|
||||
setFileName(file.name);
|
||||
};
|
||||
|
||||
return (
|
||||
<React.StrictMode>
|
||||
<GlobalStyle />
|
||||
<CenteredContainer fullscreen>
|
||||
<CenteredContainer>
|
||||
<ProgressIndicator currentProgress={1} />
|
||||
<Header2>Create a secret</Header2>
|
||||
<TextAlignWrapper align="left">
|
||||
<Label htmlFor="secretInput">Enter your secret here</Label>
|
||||
</TextAlignWrapper>
|
||||
<TextArea
|
||||
id="secretInput"
|
||||
value={secretInput}
|
||||
onChange={handleChange}
|
||||
placeholder="Tell me your secrets"
|
||||
/>
|
||||
<Spacer space="2rem" />
|
||||
<TextAlignWrapper align="center">
|
||||
<Label htmlFor="fileInput">OR</Label>
|
||||
</TextAlignWrapper>
|
||||
<Spacer space="1.6rem" />
|
||||
<FileInput id="fileInput" value={fileName} handleFile={handleFile} />
|
||||
{ fileInput ? "" : ""}
|
||||
<Spacer space="4rem" />
|
||||
<div
|
||||
style={{ display: "flex", justifyContent: "flex-end", width: "100%" }}
|
||||
>
|
||||
<Button variant="secondary" onClick={() => window.location.href = "/just/for"}>
|
||||
<IconArrow arrowDirection="right" />
|
||||
</Button>
|
||||
</div>
|
||||
</CenteredContainer>
|
||||
</CenteredContainer>
|
||||
</React.StrictMode>
|
||||
);
|
||||
};
|
||||
|
||||
export default JustPage;
|
|
@ -1,9 +1,11 @@
|
|||
import React from "react";
|
||||
|
||||
import { CenteredContainer, SplashIconHeader, Header1, Header3, Spacer, Button } from '@intended/intended-ui';
|
||||
import { CenteredContainer, SplashIconHeader, Header1, Header3, Spacer, Button, GlobalStyle } from '@intended/intended-ui';
|
||||
|
||||
const SplashPage = () => {
|
||||
return (
|
||||
<React.StrictMode>
|
||||
<GlobalStyle />
|
||||
<CenteredContainer fullscreen>
|
||||
<CenteredContainer wide>
|
||||
<SplashIconHeader />
|
||||
|
@ -13,11 +15,12 @@ const SplashPage = () => {
|
|||
and secretly.
|
||||
</Header3>
|
||||
<Spacer />
|
||||
<Button variant="secondary" boldFont onClick={() => {}}>
|
||||
<Button variant="secondary" boldFont onClick={() => window.location.href = "/just"}>
|
||||
START SHARING
|
||||
</Button>
|
||||
</CenteredContainer>
|
||||
</CenteredContainer>
|
||||
</React.StrictMode>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
import React from "react";
|
||||
|
||||
import { ProgressIndicator, Header2, Button, IconArrow, InputButtonWithIcon, Label, Input, CenteredContainer, SpaceBetweenContainer, Spacer, TextAlignWrapper, GlobalStyle } from "@intended/intended-ui";
|
||||
|
||||
const YouPage = () => {
|
||||
return (
|
||||
<React.StrictMode>
|
||||
<GlobalStyle />
|
||||
<CenteredContainer fullscreen>
|
||||
<CenteredContainer>
|
||||
<ProgressIndicator currentProgress={3} />
|
||||
<Header2>Share the secret</Header2>
|
||||
<SpaceBetweenContainer>
|
||||
<Label htmlFor="shareLink">Secret message url</Label>
|
||||
<Label htmlFor="shareLink">
|
||||
Share this link with the intended recepient
|
||||
</Label>
|
||||
</SpaceBetweenContainer>
|
||||
<InputButtonWithIcon
|
||||
id="shareLink"
|
||||
onClick={() => {}}
|
||||
value="https://intended.link/for/you/MWUzZjg4YmEtZmNmNy00M..."
|
||||
variant="copy"
|
||||
/>
|
||||
<Spacer space="2rem" />
|
||||
<TextAlignWrapper align="left">
|
||||
<Label htmlFor="encodedSecret">
|
||||
This is what your message looks like on our server. Pretty secure
|
||||
looking eh?:
|
||||
</Label>
|
||||
</TextAlignWrapper>
|
||||
<Input
|
||||
variant="disabled-light"
|
||||
id="encodedSecret"
|
||||
value="\4RÏÇmÄyÆFÕ¬Ð$CÑÓÃyÛ"
|
||||
/>
|
||||
<Spacer space="3rem" />
|
||||
<SpaceBetweenContainer>
|
||||
<Button variant="secondary" onClick={() => window.location.href = "/just/for"}>
|
||||
<IconArrow arrowDirection="left" />
|
||||
</Button>
|
||||
<Button onClick={() => {}}>Generate Secret Code</Button>
|
||||
</SpaceBetweenContainer>
|
||||
</CenteredContainer>
|
||||
</CenteredContainer>
|
||||
</React.StrictMode>
|
||||
);
|
||||
};
|
||||
|
||||
export default YouPage;
|
File diff suppressed because it is too large
Load Diff
|
@ -7,17 +7,19 @@
|
|||
"watch": "webpack --mode development --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@intended/intended-ui": "0.1.16",
|
||||
"@intended/intended-ui": "0.1.19",
|
||||
"phoenix": "file:../deps/phoenix",
|
||||
"phoenix_html": "file:../deps/phoenix_html",
|
||||
"phoenix_live_view": "file:../deps/phoenix_live_view",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-phoenix": "file:../deps/react_phoenix",
|
||||
"topbar": "^0.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.0.0",
|
||||
"@babel/preset-env": "^7.0.0",
|
||||
"@babel/preset-react": "^7.16.0",
|
||||
"@types/phoenix": "^1.5.3",
|
||||
"@types/react": "^17.0.37",
|
||||
"@types/react-dom": "^17.0.11",
|
||||
|
|
|
@ -50,7 +50,11 @@ module.exports = (env, options) => {
|
|||
]
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".ts", ".tsx", ".js", ".jsx"]
|
||||
extensions: [".ts", ".tsx", ".js", ".jsx"],
|
||||
alias: {
|
||||
react: path.resolve(__dirname, './node_modules/react'),
|
||||
'react-dom': path.resolve(__dirname, './node_modules/react-dom')
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new MiniCssExtractPlugin({ filename: '../css/app.css' }),
|
||||
|
|
|
@ -37,6 +37,8 @@ defmodule EntenduWeb do
|
|||
import Phoenix.Controller,
|
||||
only: [get_flash: 1, get_flash: 2, view_module: 1, view_template: 1]
|
||||
|
||||
import ReactPhoenix.ClientSide
|
||||
|
||||
# Include shared imports and aliases for views
|
||||
unquote(view_helpers())
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<main role="main" class="container">
|
||||
<main role="main">
|
||||
<p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p>
|
||||
<p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
|
||||
<%= @inner_content %>
|
||||
|
|
|
@ -9,24 +9,7 @@
|
|||
<link phx-track-static rel="stylesheet" href="<%= Routes.static_path(@conn, "/css/app.css") %>"/>
|
||||
<script defer phx-track-static type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root">
|
||||
<header>
|
||||
<section class="container">
|
||||
<nav role="navigation">
|
||||
<ul>
|
||||
<li><a href="https://hexdocs.pm/phoenix/overview.html">Get Started</a></li>
|
||||
<%= if function_exported?(Routes, :live_dashboard_path, 2) do %>
|
||||
<li><%= link "LiveDashboard", to: Routes.live_dashboard_path(@conn, :home) %></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</nav>
|
||||
<a href="https://phoenixframework.org/" class="phx-logo">
|
||||
<img src="<%= Routes.static_path(@conn, "/images/phoenix.png") %>" alt="Phoenix Framework Logo"/>
|
||||
</a>
|
||||
</section>
|
||||
</header>
|
||||
<body style="background: #060b2e;">
|
||||
<%= @inner_content %>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,6 +1 @@
|
|||
<section class="phx-hero">
|
||||
<h2>Create a secret!</h2>
|
||||
<p>There will be a form here</p>
|
||||
<p>And a file input here</p>
|
||||
<p>Then a next button</p>
|
||||
</section>
|
||||
<%= react_component("Components.ForPage") %>
|
||||
|
|
|
@ -1,10 +1 @@
|
|||
<section class="phx-hero">
|
||||
<h2>Create a secret!</h2>
|
||||
<p>There will be a form here</p>
|
||||
<p>And a file input here</p>
|
||||
<p>Then a next button</p>
|
||||
<form phx-submit="just">
|
||||
<textarea></textarea>
|
||||
<button>Submit</button>
|
||||
</form>
|
||||
</section>
|
||||
<%= react_component("Components.JustPage") %>
|
||||
|
|
|
@ -1,6 +1 @@
|
|||
<section class="phx-hero">
|
||||
<h2>Create a secret!</h2>
|
||||
<p>There will be a form here</p>
|
||||
<p>And a file input here</p>
|
||||
<p>Then a next button</p>
|
||||
</section>
|
||||
<%= react_component("Components.YouPage") %>
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
<section class="phx-hero">
|
||||
<h1>Überauth + Phoenix Example</h1>
|
||||
<p>
|
||||
This is an application to show an example of how to wire up
|
||||
<a href="https://github.com/ueberauth/ueberauth">Überauth</a> with
|
||||
<a href="https://github.com/phoenixframework/phoenix">Phoenix</a>.
|
||||
</p>
|
||||
<section>
|
||||
|
||||
<%= react_component("Components.SplashPage") %>
|
||||
|
||||
<%= if @current_user do %>
|
||||
<h2>Welcome, <%= @current_user.name %>!</h2>
|
||||
<div>
|
||||
|
@ -13,7 +10,7 @@
|
|||
<%= link "Logout", to: Routes.auth_path(@conn, :delete), method: "delete", class: "button" %>
|
||||
<br>
|
||||
<% else %>
|
||||
<ul style="list-style: none">
|
||||
<ul style="display: none;">
|
||||
<li>
|
||||
<a class="button" href="<%= Routes.auth_path(@conn, :request, "github") %>">
|
||||
<i class="fa fa-github"></i>
|
||||
|
|
3
mix.exs
3
mix.exs
|
@ -49,7 +49,8 @@ defmodule Entendu.MixProject do
|
|||
{:plug_cowboy, "~> 2.0"},
|
||||
{:libcluster, "~> 3.2"},
|
||||
{:ueberauth, "~> 0.7.0"},
|
||||
{:ueberauth_github, "~> 0.8.1"}
|
||||
{:ueberauth_github, "~> 0.8.1"},
|
||||
{:react_phoenix, "~> 1.3"}
|
||||
]
|
||||
end
|
||||
|
||||
|
|
1
mix.lock
1
mix.lock
|
@ -33,6 +33,7 @@
|
|||
"plug_crypto": {:hex, :plug_crypto, "1.2.2", "05654514ac717ff3a1843204b424477d9e60c143406aa94daf2274fdd280794d", [:mix], [], "hexpm", "87631c7ad914a5a445f0a3809f99b079113ae4ed4b867348dd9eec288cecb6db"},
|
||||
"postgrex": {:hex, :postgrex, "0.15.10", "2809dee1b1d76f7cbabe570b2a9285c2e7b41be60cf792f5f2804a54b838a067", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "1560ca427542f6b213f8e281633ae1a3b31cdbcd84ebd7f50628765b8f6132be"},
|
||||
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
|
||||
"react_phoenix": {:hex, :react_phoenix, "1.3.0", "78aa68fda37437085e96a1cadfa25817f224db9250423397e6039c0ebfe1a5c3", [:mix], [{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.11 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}], "hexpm", "86f7e8500f3f6376766609120fbabc6f119adbc9b2569f076a71aae8e15a32f8"},
|
||||
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
|
||||
"telemetry": {:hex, :telemetry, "0.4.3", "a06428a514bdbc63293cd9a6263aad00ddeb66f608163bdec7c8995784080818", [:rebar3], [], "hexpm", "eb72b8365ffda5bed68a620d1da88525e326cb82a75ee61354fc24b844768041"},
|
||||
"telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"},
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"lockfileVersion": 1
|
||||
}
|
Loading…
Reference in New Issue