mirror of
https://github.com/tavo-wasd-gh/conex-builder.git
synced 2025-06-07 12:13:30 -06:00
better ui, paypal order ready, subscription still missing
This commit is contained in:
parent
f2e07946d0
commit
1ff85e982a
8 changed files with 229 additions and 53 deletions
59
main.go
59
main.go
|
@ -10,10 +10,24 @@ import (
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
// "time"
|
||||||
|
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type OrderData struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
PurchaseUnits []struct {
|
||||||
|
Payments struct {
|
||||||
|
Captures []struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
} `json:"captures"`
|
||||||
|
} `json:"payments"`
|
||||||
|
} `json:"purchase_units"`
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
baseURL = "https://api-m.sandbox.paypal.com"
|
baseURL = "https://api-m.sandbox.paypal.com"
|
||||||
)
|
)
|
||||||
|
@ -27,6 +41,7 @@ func init() {
|
||||||
func main() {
|
func main() {
|
||||||
// Handlers
|
// Handlers
|
||||||
http.HandleFunc("/api/orders", CreateOrder)
|
http.HandleFunc("/api/orders", CreateOrder)
|
||||||
|
http.HandleFunc("/api/orders/", CaptureOrder)
|
||||||
http.Handle("/", http.FileServer(http.Dir("./public")))
|
http.Handle("/", http.FileServer(http.Dir("./public")))
|
||||||
|
|
||||||
// Channel to listen for signals
|
// Channel to listen for signals
|
||||||
|
@ -121,3 +136,47 @@ func CreateOrder(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CaptureOrder(w http.ResponseWriter, r *http.Request) {
|
||||||
|
path := strings.TrimPrefix(r.URL.Path, "/api/orders/")
|
||||||
|
parts := strings.Split(path, "/")
|
||||||
|
orderID := parts[0]
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
req, err := http.NewRequest("POST", baseURL+"/v2/checkout/orders/"+orderID+"/capture", nil)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Failed to create request", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
token, err := Token()
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Failed to get access token", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("Authorization", "Bearer "+token)
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Failed to send request", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// Create an instance of AutoGenerated
|
||||||
|
var result OrderData
|
||||||
|
|
||||||
|
// Decode the response into the AutoGenerated struct
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
||||||
|
http.Error(w, "Failed to decode response", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now, `result` contains the entire structured response
|
||||||
|
// You can send the whole `result` back to the client, or you can selectively send fields.
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||||
|
http.Error(w, "Failed to encode response", http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
122
public/form.js
122
public/form.js
|
@ -46,10 +46,10 @@ function togglePaymentMethod(selectedButtonId) {
|
||||||
|
|
||||||
if (selectedButtonId === 'showOneTimeButton') {
|
if (selectedButtonId === 'showOneTimeButton') {
|
||||||
document.getElementById('paypal-button-container').classList.add('active');
|
document.getElementById('paypal-button-container').classList.add('active');
|
||||||
document.getElementById('paypalOneTimeButton').classList.add('active');
|
document.getElementById('paypal-button-container-order').classList.add('active');
|
||||||
} else if (selectedButtonId === 'showSubButton') {
|
} else if (selectedButtonId === 'showSubButton') {
|
||||||
document.getElementById('paypal-button-container').classList.add('active');
|
document.getElementById('paypal-button-container').classList.add('active');
|
||||||
document.getElementById('paypalSubButton').classList.add('active');
|
document.getElementById('paypal-button-container-subscribe').classList.add('active');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,37 +57,99 @@ function isFormValid(form) {
|
||||||
return form.checkValidity();
|
return form.checkValidity();
|
||||||
}
|
}
|
||||||
|
|
||||||
paypal_onetime.Buttons({
|
window.paypal_order.Buttons({
|
||||||
style: { shape: 'pill', color: 'black', layout: 'vertical', label: 'pay' },
|
style: { shape: 'pill', color: 'black', layout: 'vertical', label: 'pay' },
|
||||||
createOrder: function(data, actions) {
|
async createOrder() {
|
||||||
return actions.order.create({
|
try {
|
||||||
intent: 'CAPTURE',
|
const response = await fetch("/api/orders", {
|
||||||
purchase_units: [{
|
method: "POST",
|
||||||
amount: {
|
headers: {
|
||||||
currency_code: 'USD',
|
"Content-Type": "application/json",
|
||||||
value: '20.00'
|
},
|
||||||
}
|
// use the "body" param to optionally pass additional order information
|
||||||
}]
|
// like product ids and quantities
|
||||||
});
|
body: JSON.stringify({
|
||||||
},
|
cart: [
|
||||||
onApprove: function(data, actions) {
|
{
|
||||||
return actions.order.capture().then(function(details) {
|
id: "YOUR_PRODUCT_ID",
|
||||||
alert('Transaction completed by ' + details.payer.name.given_name);
|
quantity: "YOUR_PRODUCT_QUANTITY",
|
||||||
});
|
},
|
||||||
}
|
],
|
||||||
}).render("#paypalOneTimeButton");
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
paypal_subscribe.Buttons({
|
const orderData = await response.json();
|
||||||
style: { shape: 'pill', color: 'black', layout: 'vertical', label: 'subscribe' },
|
|
||||||
createSubscription: function(data, actions) {
|
if (orderData.id) {
|
||||||
return actions.subscription.create({
|
return orderData.id;
|
||||||
plan_id: PlanID
|
} else {
|
||||||
});
|
const errorDetail = orderData?.details?.[0];
|
||||||
|
const errorMessage = errorDetail
|
||||||
|
? `${errorDetail.issue} ${errorDetail.description} (${orderData.debug_id})`
|
||||||
|
: JSON.stringify(orderData);
|
||||||
|
|
||||||
|
throw new Error(errorMessage);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
resultMessage(`Could not initiate PayPal Checkout...<br><br>${error}`);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onApprove: function(data, actions) {
|
async onApprove(data, actions) {
|
||||||
alert(data.subscriptionID); // You can add optional success message for the subscriber here
|
try {
|
||||||
}
|
const response = await fetch(`/api/orders/${data.orderID}/capture`, {
|
||||||
}).render('#paypalSubButton');
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const orderData = await response.json();
|
||||||
|
// Three cases to handle:
|
||||||
|
// (1) Recoverable INSTRUMENT_DECLINED -> call actions.restart()
|
||||||
|
// (2) Other non-recoverable errors -> Show a failure message
|
||||||
|
// (3) Successful transaction -> Show confirmation or thank you message
|
||||||
|
|
||||||
|
const errorDetail = orderData?.details?.[0];
|
||||||
|
|
||||||
|
if (errorDetail?.issue === "INSTRUMENT_DECLINED") {
|
||||||
|
// (1) Recoverable INSTRUMENT_DECLINED -> call actions.restart()
|
||||||
|
// recoverable state, per https://developer.paypal.com/docs/checkout/standard/customize/handle-funding-failures/
|
||||||
|
return actions.restart();
|
||||||
|
} else if (errorDetail) {
|
||||||
|
// (2) Other non-recoverable errors -> Show a failure message
|
||||||
|
throw new Error(`${errorDetail.description} (${orderData.debug_id})`);
|
||||||
|
} else if (!orderData.purchase_units) {
|
||||||
|
throw new Error(JSON.stringify(orderData));
|
||||||
|
} else {
|
||||||
|
// (3) Successful transaction -> Show confirmation or thank you message
|
||||||
|
// Or go to another URL: actions.redirect('thank_you.html');
|
||||||
|
const transaction =
|
||||||
|
orderData?.purchase_units?.[0]?.payments?.captures?.[0] ||
|
||||||
|
orderData?.purchase_units?.[0]?.payments?.authorizations?.[0];
|
||||||
|
resultMessage(
|
||||||
|
`Transaction ${transaction.status}: ${transaction.id}<br><br>See console for all available details`,
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
"Capture result",
|
||||||
|
orderData,
|
||||||
|
JSON.stringify(orderData, null, 2),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
resultMessage(
|
||||||
|
`Sorry, your transaction could not be processed...<br><br>${error}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}).render("#paypal-button-container-order");
|
||||||
|
|
||||||
|
// Example function to show a result to the user. Your site's UI library can be used instead.
|
||||||
|
function resultMessage(message) {
|
||||||
|
const container = document.querySelector("#checkout");
|
||||||
|
container.innerHTML = message;
|
||||||
|
}
|
||||||
|
|
||||||
document.getElementById('showOneTimeButton').addEventListener('click', function() {
|
document.getElementById('showOneTimeButton').addEventListener('click', function() {
|
||||||
if (isFormValid(form)) {
|
if (isFormValid(form)) {
|
||||||
|
|
|
@ -26,20 +26,23 @@
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
|
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
|
||||||
<!-- EDITORJS -->
|
<!-- EDITORJS -->
|
||||||
<script
|
<script
|
||||||
src="https://www.paypal.com/sdk/js?client-id=AcCW43LI1S6lLQgtLkF4V8UOPfmXcqXQ8xfEl41hRuMxSskR2jkWNwQN6Ab1WK7E2E52GNaoYBHqgIKd&disable-funding=venmo¤cy=USD"
|
src="https://www.paypal.com/sdk/js?client-id=AcCW43LI1S6lLQgtLkF4V8UOPfmXcqXQ8xfEl41hRuMxSskR2jkWNwQN6Ab1WK7E2E52GNaoYBHqgIKd&components=buttons&enable-funding=card&disable-funding=paylater,venmo"
|
||||||
data-namespace="paypal_onetime"
|
data-namespace="paypal_order"
|
||||||
></script>
|
|
||||||
<script
|
|
||||||
src="https://www.paypal.com/sdk/js?client-id=AUJPUXq47cceshojipubmg0wvCgdJC-bg4O4xvMQf_ic1MzlS27OVW6EGpymJtFXssAiXNOwBQDKqWiE&vault=true&intent=subscription"
|
|
||||||
data-namespace="paypal_subscribe"
|
|
||||||
></script>
|
></script>
|
||||||
|
<!-- <script -->
|
||||||
|
<!-- src="" -->
|
||||||
|
<!-- data-namespace="paypal_subscribe" -->
|
||||||
|
<!-- ></script> -->
|
||||||
</head>
|
</head>
|
||||||
<form action="submit.php" id="mainForm" method="post">
|
<form action="submit.php" id="mainForm" method="post">
|
||||||
<div class="banner" style="background-image: url(/static/banner.jpg);">
|
<div class="banner" style="background-image: url(/static/banner.jpg);">
|
||||||
<div class="desc">
|
<div class="desc">
|
||||||
<input type="text" name="title" class="input-title" placeholder="[Nombre Ejemplo]">
|
<input type="text" name="title" class="input-title" placeholder="[Nombre Ejemplo]">
|
||||||
<input type="text" name="slogan" class="input-slogan" placeholder="[Slogan llamativo o breve descripción]">
|
<input type="text" name="slogan" class="input-slogan" placeholder="[Slogan llamativo o breve descripción]">
|
||||||
<button type="button" id="openDialogButton">Solicitar por $20/año</button>
|
<button type="button" id="openDialogButton">
|
||||||
|
<img src="/static/svg/cart.svg">
|
||||||
|
<span >$20/año</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<body>
|
<body>
|
||||||
|
@ -52,7 +55,12 @@
|
||||||
<div id="dialog">
|
<div id="dialog">
|
||||||
<div>
|
<div>
|
||||||
<h2>Información de Contacto</h2>
|
<h2>Información de Contacto</h2>
|
||||||
<button id="cancelDialogButton" type="button">x</button>
|
<button id="cancelDialogButton" type="button">
|
||||||
|
<picture>
|
||||||
|
<source srcset="/static/svg/xd.svg" media="(prefers-color-scheme: dark)">
|
||||||
|
<img src="/static/svg/x.svg" style="width: 0.7em; height: 0.7em;" alt="Close" id="closeIcon">
|
||||||
|
</picture>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<p>Utilizaremos esta información para contactarle acerca de la publicación del sitio.</p>
|
<p>Utilizaremos esta información para contactarle acerca de la publicación del sitio.</p>
|
||||||
<div id="form-container">
|
<div id="form-container">
|
||||||
|
@ -66,14 +74,15 @@
|
||||||
<p><strong>Pago Automático:</strong> Requiere cuenta de PayPal para rebajo automático, si no tiene una le pedirá configurar rápidamente los datos.</p>
|
<p><strong>Pago Automático:</strong> Requiere cuenta de PayPal para rebajo automático, si no tiene una le pedirá configurar rápidamente los datos.</p>
|
||||||
</div>
|
</div>
|
||||||
<div id="warning-message"><p>Por favor digite los campos requeridos.</p></div>
|
<div id="warning-message"><p>Por favor digite los campos requeridos.</p></div>
|
||||||
<div id="method-button-container">
|
|
||||||
<button id="showOneTimeButton" type="button">Pago Único</button>
|
|
||||||
<button id="showSubButton" type="button">Pago Automático</button>
|
|
||||||
</div>
|
|
||||||
<div id="error-with-payment"></div>
|
<div id="error-with-payment"></div>
|
||||||
<div id="paypal-button-container">
|
<div id="checkout">
|
||||||
<div id="paypalOneTimeButton"></div>
|
<div id="method-button-container">
|
||||||
<div id="paypalSubButton"></div>
|
<button id="showOneTimeButton" type="button">Pago Único</button>
|
||||||
|
<button id="showSubButton" type="button">Pago Automático</button>
|
||||||
|
</div>
|
||||||
|
<div id="paypal-button-container">
|
||||||
|
<div id="paypal-button-container-order"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
--hover-border: #505050;
|
--hover-border: #505050;
|
||||||
--hyper-color: #00b4db;
|
--hyper-color: #00b4db;
|
||||||
}
|
}
|
||||||
|
#closeIcon {
|
||||||
|
content: url('/static/svg/xd.svg');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 900px) {
|
@media (max-width: 900px) {
|
||||||
|
@ -208,6 +211,8 @@ button {
|
||||||
}
|
}
|
||||||
|
|
||||||
#openDialogButton {
|
#openDialogButton {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 2em;
|
bottom: 2em;
|
||||||
right: 1em;
|
right: 1em;
|
||||||
|
@ -273,6 +278,19 @@ button {
|
||||||
font-size: 1.1em;
|
font-size: 1.1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#checkout {
|
||||||
|
}
|
||||||
|
|
||||||
|
#openDialogButton img {
|
||||||
|
width: 1.2em;
|
||||||
|
height: 1.2em;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
#openDialogButton span {
|
||||||
|
margin-left: 0.6em;
|
||||||
|
}
|
||||||
|
|
||||||
/* Custom SimpleMDE styling */
|
/* Custom SimpleMDE styling */
|
||||||
.CodeMirror {
|
.CodeMirror {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
|
@ -286,5 +304,3 @@ button {
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -71,9 +71,9 @@ var editor = new EditorJS({
|
||||||
type : 'list',
|
type : 'list',
|
||||||
data : {
|
data : {
|
||||||
items : [
|
items : [
|
||||||
'It is a block-styled editor',
|
'Resolvemos una necesidad clave de mercado',
|
||||||
'It returns clean data output in JSON',
|
'Inversión en crecimiento con presupuesto sostenible.',
|
||||||
'Designed to be extendable and pluggable with a simple API',
|
'Enfoque en satisfacción del cliente',
|
||||||
],
|
],
|
||||||
style: 'unordered'
|
style: 'unordered'
|
||||||
}
|
}
|
||||||
|
@ -82,9 +82,9 @@ var editor = new EditorJS({
|
||||||
type: 'table',
|
type: 'table',
|
||||||
data: {
|
data: {
|
||||||
content: [
|
content: [
|
||||||
['Header 1', 'Header 2', 'Header 3'],
|
['Servicios', 'Descripción', 'Costo'],
|
||||||
['Row 1, Cell 1', 'Row 1, Cell 2', 'Row 1, Cell 3'],
|
['Impresión', 'Breve descripción', '1000'],
|
||||||
['Row 2, Cell 1', 'Row 2, Cell 2', 'Row 2, Cell 3']
|
['laminado', 'Breve descripción', '2000'],
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
5
public/static/svg/cart.svg
Normal file
5
public/static/svg/cart.svg
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="#fff" d="M528.12 301.319l47.273-208C578.806 78.301 567.391 64 551.99 64H159.208l-9.166-44.81C147.758 8.021 137.93 0 126.529 0H24C10.745 0 0 10.745 0 24v16c0 13.255 10.745 24 24 24h69.883l70.248 343.435C147.325 417.1 136 435.222 136 456c0 30.928 25.072 56 56 56s56-25.072 56-56c0-15.674-6.447-29.835-16.824-40h209.647C430.447 426.165 424 440.326 424 456c0 30.928 25.072 56 56 56s56-25.072 56-56c0-22.172-12.888-41.332-31.579-50.405l5.517-24.276c3.413-15.018-8.002-29.319-23.403-29.319H218.117l-6.545-32h293.145c11.206 0 20.92-7.754 23.403-18.681z"/></svg>
|
||||||
|
<!--
|
||||||
|
Font Awesome Free 5.2.0 by @fontawesome - https://fontawesome.com
|
||||||
|
License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||||
|
-->
|
After Width: | Height: | Size: 804 B |
12
public/static/svg/x.svg
Normal file
12
public/static/svg/x.svg
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg fill="#000000" height="800px" width="800px" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
viewBox="0 0 460.775 460.775" xml:space="preserve">
|
||||||
|
<path d="M285.08,230.397L456.218,59.27c6.076-6.077,6.076-15.911,0-21.986L423.511,4.565c-2.913-2.911-6.866-4.55-10.992-4.55
|
||||||
|
c-4.127,0-8.08,1.639-10.993,4.55l-171.138,171.14L59.25,4.565c-2.913-2.911-6.866-4.55-10.993-4.55
|
||||||
|
c-4.126,0-8.08,1.639-10.992,4.55L4.558,37.284c-6.077,6.075-6.077,15.909,0,21.986l171.138,171.128L4.575,401.505
|
||||||
|
c-6.074,6.077-6.074,15.911,0,21.986l32.709,32.719c2.911,2.911,6.865,4.55,10.992,4.55c4.127,0,8.08-1.639,10.994-4.55
|
||||||
|
l171.117-171.12l171.118,171.12c2.913,2.911,6.866,4.55,10.993,4.55c4.128,0,8.081-1.639,10.992-4.55l32.709-32.719
|
||||||
|
c6.074-6.075,6.074-15.909,0-21.986L285.08,230.397z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1 KiB |
13
public/static/svg/xd.svg
Normal file
13
public/static/svg/xd.svg
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg fill="#fff" height="800px" width="800px" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
viewBox="0 0 460.775 460.775" xml:space="preserve">
|
||||||
|
<path d="M285.08,230.397L456.218,59.27c6.076-6.077,6.076-15.911,0-21.986L423.511,4.565c-2.913-2.911-6.866-4.55-10.992-4.55
|
||||||
|
c-4.127,0-8.08,1.639-10.993,4.55l-171.138,171.14L59.25,4.565c-2.913-2.911-6.866-4.55-10.993-4.55
|
||||||
|
c-4.126,0-8.08,1.639-10.992,4.55L4.558,37.284c-6.077,6.075-6.077,15.909,0,21.986l171.138,171.128L4.575,401.505
|
||||||
|
c-6.074,6.077-6.074,15.911,0,21.986l32.709,32.719c2.911,2.911,6.865,4.55,10.992,4.55c4.127,0,8.08-1.639,10.994-4.55
|
||||||
|
l171.117-171.12l171.118,171.12c2.913,2.911,6.866,4.55,10.993,4.55c4.128,0,8.081-1.639,10.992-4.55l32.709-32.719
|
||||||
|
c6.074-6.075,6.074-15.909,0-21.986L285.08,230.397z"/>
|
||||||
|
</svg>
|
||||||
|
|
After Width: | Height: | Size: 1 KiB |
Loading…
Reference in a new issue