Browse Source

Creación de proyecto

politica
Celestino Rey 1 year ago
parent
commit
db8aeeed26
2343 changed files with 437163 additions and 0 deletions
  1. +15
    -0
      RecetasPy/K8S/Makefile
  2. +1
    -0
      RecetasPy/K8S/entra.sh
  3. +14
    -0
      RecetasPy/K8S/pv-local-recetaspy.yaml
  4. +56
    -0
      RecetasPy/K8S/recetaspy-deployment.yaml
  5. +14
    -0
      RecetasPy/K8S/recetaspy-prod-persistentvolumeclaim.yaml
  6. +1
    -0
      RecetasPy/K8S/verImg.sh
  7. +106
    -0
      RecetasPy/chatgpt/app.py
  8. BIN
      RecetasPy/chatgpt/instance/recipes.db
  9. +30
    -0
      RecetasPy/chatgpt/models.py
  10. +38
    -0
      RecetasPy/chatgpt/static/styles.css
  11. +32
    -0
      RecetasPy/chatgpt/templates/base.html
  12. +12
    -0
      RecetasPy/chatgpt/templates/index.html
  13. +14
    -0
      RecetasPy/chatgpt/templates/login.html
  14. +48
    -0
      RecetasPy/chatgpt/templates/new_recipe.html
  15. +20
    -0
      RecetasPy/chatgpt/templates/recipe.html
  16. +18
    -0
      RecetasPy/chatgpt/templates/register.html
  17. +20
    -0
      RecetasPy/servicios/Dockerfile
  18. +8
    -0
      RecetasPy/servicios/Makefile
  19. +3
    -0
      RecetasPy/servicios/creaImagen.sh
  20. +3
    -0
      RecetasPy/servicios/entrypoint.sh
  21. BIN
      RecetasPy/servicios/instance/recipes.db
  22. BIN
      RecetasPy/servicios/instance/reymotapy.db
  23. BIN
      RecetasPy/servicios/instance/uploads/logo.png
  24. BIN
      RecetasPy/servicios/instance/uploads/nebraska.jpg
  25. +1
    -0
      RecetasPy/servicios/lanza.sh
  26. +55
    -0
      RecetasPy/servicios/recetaspy/__init__.py
  27. +82
    -0
      RecetasPy/servicios/recetaspy/auth.py
  28. +33
    -0
      RecetasPy/servicios/recetaspy/models.py
  29. +87
    -0
      RecetasPy/servicios/recetaspy/paginas.py
  30. +12
    -0
      RecetasPy/servicios/recetaspy/static/css/portal.css
  31. +21
    -0
      RecetasPy/servicios/recetaspy/static/images/app-logo.svg
  32. BIN
      RecetasPy/servicios/recetaspy/static/images/background/background-1.jpg
  33. BIN
      RecetasPy/servicios/recetaspy/static/images/background/background-2.jpg
  34. BIN
      RecetasPy/servicios/recetaspy/static/images/background/background-3.jpg
  35. BIN
      RecetasPy/servicios/recetaspy/static/images/background/background-palmeras.jpg
  36. BIN
      RecetasPy/servicios/recetaspy/static/images/doc-thumb-1.jpg
  37. BIN
      RecetasPy/servicios/recetaspy/static/images/doc-thumb-2.jpg
  38. +21
    -0
      RecetasPy/servicios/recetaspy/static/images/portal-logo.svg
  39. BIN
      RecetasPy/servicios/recetaspy/static/images/profiles/profile-1.png
  40. BIN
      RecetasPy/servicios/recetaspy/static/images/profiles/profile-2.png
  41. BIN
      RecetasPy/servicios/recetaspy/static/images/profiles/profile-3.png
  42. BIN
      RecetasPy/servicios/recetaspy/static/images/profiles/profile-4.png
  43. BIN
      RecetasPy/servicios/recetaspy/static/images/profiles/profile-5.png
  44. BIN
      RecetasPy/servicios/recetaspy/static/images/profiles/profile-6.png
  45. +18
    -0
      RecetasPy/servicios/recetaspy/static/images/reymota-logo.svg
  46. BIN
      RecetasPy/servicios/recetaspy/static/images/user.png
  47. BIN
      RecetasPy/servicios/recetaspy/static/images/users/user-1.jpg
  48. BIN
      RecetasPy/servicios/recetaspy/static/images/users/user-2.jpg
  49. BIN
      RecetasPy/servicios/recetaspy/static/images/users/user-3.jpg
  50. BIN
      RecetasPy/servicios/recetaspy/static/images/users/user-4.jpg
  51. BIN
      RecetasPy/servicios/recetaspy/static/images/users/user-5.jpg
  52. BIN
      RecetasPy/servicios/recetaspy/static/images/users/user-6.jpg
  53. BIN
      RecetasPy/servicios/recetaspy/static/images/users/user-7.jpg
  54. BIN
      RecetasPy/servicios/recetaspy/static/images/users/user-8.jpg
  55. BIN
      RecetasPy/servicios/recetaspy/static/images/users/user-9.jpg
  56. +96
    -0
      RecetasPy/servicios/recetaspy/static/js/app.js
  57. +366
    -0
      RecetasPy/servicios/recetaspy/static/js/charts-demo.js
  58. +224
    -0
      RecetasPy/servicios/recetaspy/static/js/index-charts.js
  59. +4085
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-grid.css
  60. +1
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-grid.css.map
  61. +6
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-grid.min.css
  62. +1
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-grid.min.css.map
  63. +4084
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-grid.rtl.css
  64. +1
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-grid.rtl.css.map
  65. +6
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-grid.rtl.min.css
  66. +1
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-grid.rtl.min.css.map
  67. +593
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-reboot.css
  68. +1
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-reboot.css.map
  69. +6
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-reboot.min.css
  70. +1
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-reboot.min.css.map
  71. +590
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-reboot.rtl.css
  72. +1
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-reboot.rtl.css.map
  73. +6
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-reboot.rtl.min.css
  74. +1
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-reboot.rtl.min.css.map
  75. +5399
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-utilities.css
  76. +1
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-utilities.css.map
  77. +6
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-utilities.min.css
  78. +1
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-utilities.min.css.map
  79. +5390
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-utilities.rtl.css
  80. +1
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-utilities.rtl.css.map
  81. +6
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-utilities.rtl.min.css
  82. +1
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-utilities.rtl.min.css.map
  83. +12071
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap.css
  84. +1
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap.css.map
  85. +6
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap.min.css
  86. +1
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap.min.css.map
  87. +12035
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap.rtl.css
  88. +1
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap.rtl.css.map
  89. +6
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap.rtl.min.css
  90. +1
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap.rtl.min.css.map
  91. +6306
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/js/bootstrap.bundle.js
  92. +1
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/js/bootstrap.bundle.js.map
  93. +7
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/js/bootstrap.bundle.min.js
  94. +1
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/js/bootstrap.bundle.min.js.map
  95. +4439
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/js/bootstrap.esm.js
  96. +1
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/js/bootstrap.esm.js.map
  97. +7
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/js/bootstrap.esm.min.js
  98. +1
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/js/bootstrap.esm.min.js.map
  99. +4486
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/js/bootstrap.js
  100. +1
    -0
      RecetasPy/servicios/recetaspy/static/plugins/bootstrap/js/bootstrap.js.map

+ 15
- 0
RecetasPy/K8S/Makefile View File

@ -0,0 +1,15 @@
export IMG_VERSION = 6.4
imagen:
cd ../servicios; make
install:
envsubst < lyrics-deployment.yaml |kubectl create -f -
storage:
kubectl create -f pv-local-recetaspy.yaml
kubectl create -f recetaspy-prod-persistentvolumeclaim.yaml
clean:
envsubst < lyrics-deployment.yaml |kubectl delete -f -

+ 1
- 0
RecetasPy/K8S/entra.sh View File

@ -0,0 +1 @@
kubectl exec -ti deployment.apps/lyrics -- /bin/bash

+ 14
- 0
RecetasPy/K8S/pv-local-recetaspy.yaml View File

@ -0,0 +1,14 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: recetaspy-app-folder
labels:
app: recetaspy
spec:
capacity:
storage: 100Mi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/Externo/recetaspy"

+ 56
- 0
RecetasPy/K8S/recetaspy-deployment.yaml View File

@ -0,0 +1,56 @@
apiVersion: v1
kind: Service
metadata:
name: recetaspy
spec:
type: NodePort
ports:
- name: http
port: 5000
nodePort: 30340
targetPort: recetaspy
selector:
app: recetaspy
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: recetaspy
labels:
app: recetaspy
spec:
replicas: 1
selector:
matchLabels:
app: recetaspy
strategy:
type: Recreate
template:
metadata:
labels:
app: recetaspy
spec:
containers:
- args:
- gunicorn
- --bind
- 0.0.0.0:5000
- recetaspy:create_app()
image: creylopez/recetaspy:$IMG_VERSION
name: recetaspy
env:
- name: SALUDO_DEMO
value: "Hola, mundo"
ports:
- containerPort: 5000
name: recetaspy
resources: {}
volumeMounts:
- mountPath: /recetaspy/instance
name: recetaspy-prod
restartPolicy: Always
volumes:
- name: recetaspy-prod
persistentVolumeClaim:
claimName: recetaspy-prod
status: {}

+ 14
- 0
RecetasPy/K8S/recetaspy-prod-persistentvolumeclaim.yaml View File

@ -0,0 +1,14 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
creationTimestamp: null
labels:
io.kompose.service: recetaspy-prod
name: recetaspy-prod
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Mi
status: {}

+ 1
- 0
RecetasPy/K8S/verImg.sh View File

@ -0,0 +1 @@
docker run -it creylopez/lyrics:5.3 bash

+ 106
- 0
RecetasPy/chatgpt/app.py View File

@ -0,0 +1,106 @@
from flask import Flask, render_template, request, redirect, url_for, flash
from flask_sqlalchemy import SQLAlchemy
from models import db, User, Recipe, Ingredient, Instruction
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///recipes.db'
app.config['SECRET_KEY'] = 'your_secret_key'
db.init_app(app)
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
@app.route('/')
def index():
recipes = Recipe.query.all()
return render_template('index.html', recipes=recipes)
@app.route('/recipe/<int:recipe_id>')
def recipe(recipe_id):
recipe = Recipe.query.get_or_404(recipe_id)
return render_template('recipe.html', recipe=recipe)
@app.route('/new_recipe', methods=['GET', 'POST'])
@login_required
def new_recipe():
if request.method == 'POST':
title = request.form['title']
description = request.form['description']
ingredients = request.form.getlist('ingredient')
quantities = request.form.getlist('quantity')
steps = request.form.getlist('step')
step_descriptions = request.form.getlist('step_description')
recipe = Recipe(title=title, description=description, author=current_user)
for ingredient, quantity in zip(ingredients, quantities):
recipe.ingredients.append(Ingredient(name=ingredient, quantity=quantity))
for step, description in zip(steps, step_descriptions):
recipe.instructions.append(Instruction(step=step, description=description))
db.session.add(recipe)
db.session.commit()
flash('Recipe created successfully!', 'success')
return redirect(url_for('index'))
return render_template('new_recipe.html')
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
email = request.form['email']
password = request.form['password']
user = User.query.filter_by(email=email).first()
if user and check_password_hash(user.password, password):
login_user(user)
flash('Logged in successfully.')
return redirect(url_for('index'))
else:
flash('Invalid email or password.')
return render_template('login.html')
@app.route('/logout')
@login_required
def logout():
logout_user()
flash('Logged out successfully.')
return redirect(url_for('index'))
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
username = request.form['username']
email = request.form['email']
password = request.form['password']
confirm_password = request.form['confirm_password']
if password != confirm_password:
flash('Passwords do not match.')
return redirect(url_for('register'))
hashed_password = generate_password_hash(password, method='pbkdf2:sha256')
new_user = User(username=username, email=email, password=hashed_password)
try:
db.session.add(new_user)
db.session.commit()
flash('Registration successful.')
return redirect(url_for('login'))
except:
flash('Email address already exists.')
return redirect(url_for('register'))
return render_template('register.html')
if __name__ == '__main__':
with app.app_context():
db.create_all()
app.run(debug=True)

BIN
RecetasPy/chatgpt/instance/recipes.db View File


+ 30
- 0
RecetasPy/chatgpt/models.py View File

@ -0,0 +1,30 @@
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(150), unique=True, nullable=False)
email = db.Column(db.String(150), unique=True, nullable=False)
password = db.Column(db.String(150), nullable=False)
recipes = db.relationship('Recipe', backref='author', lazy=True)
class Recipe(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(150), nullable=False)
description = db.Column(db.Text, nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
ingredients = db.relationship('Ingredient', backref='recipe', lazy=True)
instructions = db.relationship('Instruction', backref='recipe', lazy=True)
class Ingredient(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
quantity = db.Column(db.String(50), nullable=False)
recipe_id = db.Column(db.Integer, db.ForeignKey('recipe.id'), nullable=False)
class Instruction(db.Model):
id = db.Column(db.Integer, primary_key=True)
step = db.Column(db.Integer, nullable=False)
description = db.Column(db.Text, nullable=False)
recipe_id = db.Column(db.Integer, db.ForeignKey('recipe.id'), nullable=False)

+ 38
- 0
RecetasPy/chatgpt/static/styles.css View File

@ -0,0 +1,38 @@
body {
font-family: Arial, sans-serif;
padding: 20px;
}
nav {
margin-bottom: 20px;
}
nav a {
margin-right: 10px;
}
.flashes {
list-style-type: none;
padding: 0;
}
.flashes li {
margin-bottom: 10px;
padding: 10px;
border-radius: 5px;
}
.flashes .success {
background-color: #d4edda;
color: #155724;
}
.flashes .error {
background-color: #f8d7da;
color: #721c24;
}
.content {
max-width: 800px;
margin: auto;
}

+ 32
- 0
RecetasPy/chatgpt/templates/base.html View File

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}Recipe App{% endblock %}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
</head>
<body>
<nav>
<a href="{{ url_for('index') }}">Home</a>
{% if current_user.is_authenticated %}
<a href="{{ url_for('new_recipe') }}">New Recipe</a>
<a href="{{ url_for('logout') }}">Logout</a>
{% else %}
<a href="{{ url_for('login') }}">Login</a>
<a href="{{ url_for('register') }}">Register</a>
{% endif %}
</nav>
<div class="content">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<ul class="flashes">
{% for category, message in messages %}
<li class="{{ category }}">{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</div>
</body>
</html>

+ 12
- 0
RecetasPy/chatgpt/templates/index.html View File

@ -0,0 +1,12 @@
{% extends 'base.html' %}
{% block title %}Home{% endblock %}
{% block content %}
<h1>Recipes</h1>
<ul>
{% for recipe in recipes %}
<li><a href="{{ url_for('recipe', recipe_id=recipe.id) }}">{{ recipe.title }}</a></li>
{% endfor %}
</ul>
{% endblock %}

+ 14
- 0
RecetasPy/chatgpt/templates/login.html View File

@ -0,0 +1,14 @@
{% extends 'base.html' %}
{% block title %}Login{% endblock %}
{% block content %}
<h1>Login</h1>
<form action="{{ url_for('login') }}" method="post">
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
<button type="submit">Login</button>
</form>
{% endblock %}

+ 48
- 0
RecetasPy/chatgpt/templates/new_recipe.html View File

@ -0,0 +1,48 @@
{% extends 'base.html' %}
{% block title %}New Recipe{% endblock %}
{% block content %}
<h1>New Recipe</h1>
<form action="{{ url_for('new_recipe') }}" method="post">
<label for="title">Title:</label>
<input type="text" id="title" name="title" required>
<label for="description">Description:</label>
<textarea id="description" name="description" required></textarea>
<h2>Ingredients</h2>
<div id="ingredients">
<div class="ingredient">
<input type="text" name="ingredient" placeholder="Ingredient" required>
<input type="text" name="quantity" placeholder="Quantity" required>
</div>
</div>
<button type="button" onclick="addIngredient()">Add Ingredient</button>
<h2>Instructions</h2>
<div id="instructions">
<div class="instruction">
<input type="text" name="step" placeholder="Step Number" required>
<textarea name="step_description" placeholder="Step Description" required></textarea>
</div>
</div>
<button type="button" onclick="addInstruction()">Add Instruction</button>
<button type="submit">Create Recipe</button>
</form>
<script>
function addIngredient() {
var ingredientsDiv = document.getElementById('ingredients');
var newIngredientDiv = document.createElement('div');
newIngredientDiv.className = 'ingredient';
newIngredientDiv.innerHTML = '<input type="text" name="ingredient" placeholder="Ingredient" required> <input type="text" name="quantity" placeholder="Quantity" required>';
ingredientsDiv.appendChild(newIngredientDiv);
}
function addInstruction() {
var instructionsDiv = document.getElementById('instructions');
var newInstructionDiv = document.createElement('div');
newInstructionDiv.className = 'instruction';
newInstructionDiv.innerHTML = '<input type="text" name="step" placeholder="Step Number" required> <textarea name="step_description" placeholder="Step Description" required></textarea>';
instructionsDiv.appendChild(newInstructionDiv);
}
</script>
{% endblock %}

+ 20
- 0
RecetasPy/chatgpt/templates/recipe.html View File

@ -0,0 +1,20 @@
{% extends 'base.html' %}
{% block title %}Recipe: {{ recipe.title }}{% endblock %}
{% block content %}
<h1>{{ recipe.title }}</h1>
<p>{{ recipe.description }}</p>
<h2>Ingredients</h2>
<ul>
{% for ingredient in recipe.ingredients %}
<li>{{ ingredient.quantity }} {{ ingredient.name }}</li>
{% endfor %}
</ul>
<h2>Instructions</h2>
<ol>
{% for instruction in recipe.instructions %}
<li>{{ instruction.description }}</li>
{% endfor %}
</ol>
{% endblock %}

+ 18
- 0
RecetasPy/chatgpt/templates/register.html View File

@ -0,0 +1,18 @@
{% extends 'base.html' %}
{% block title %}Register{% endblock %}
{% block content %}
<h1>Register</h1>
<form action="{{ url_for('register') }}" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
<label for="confirm_password">Confirm Password:</label>
<input type="password" id="confirm_password" name="confirm_password" required>
<button type="submit">Register</button>
</form>
{% endblock %}

+ 20
- 0
RecetasPy/servicios/Dockerfile View File

@ -0,0 +1,20 @@
# syntax=docker/dockerfile:1
FROM python:3.8-slim-buster
WORKDIR /reymotapy
# set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
# install system dependencies
RUN apt-get update && apt-get install -y sqlite3
COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt
COPY . .
# run entrypoint.sh
ENTRYPOINT ["/reymotapy/entrypoint.sh"]

+ 8
- 0
RecetasPy/servicios/Makefile View File

@ -0,0 +1,8 @@
install:
echo "Creando imagen con version ${IMG_VERSION}"
docker build --no-cache -t creylopez/lyrics:${IMG_VERSION} .
docker push creylopez/lyrics:${IMG_VERSION}

+ 3
- 0
RecetasPy/servicios/creaImagen.sh View File

@ -0,0 +1,3 @@
docker build --no-cache -t creylopez/reymotapy:2.0 .
docker push creylopez/reymotapy:2.0

+ 3
- 0
RecetasPy/servicios/entrypoint.sh View File

@ -0,0 +1,3 @@
#!/bin/bash
exec "$@"

BIN
RecetasPy/servicios/instance/recipes.db View File


BIN
RecetasPy/servicios/instance/reymotapy.db View File


BIN
RecetasPy/servicios/instance/uploads/logo.png View File

Before After
Width: 894  |  Height: 894  |  Size: 468 KiB

BIN
RecetasPy/servicios/instance/uploads/nebraska.jpg View File

Before After
Width: 320  |  Height: 320  |  Size: 34 KiB

+ 1
- 0
RecetasPy/servicios/lanza.sh View File

@ -0,0 +1 @@
python3 -m flask --app recetaspy run

+ 55
- 0
RecetasPy/servicios/recetaspy/__init__.py View File

@ -0,0 +1,55 @@
import os
from flask import Flask, url_for
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
# init SQLAlchemy so we can use it later in our models
db = SQLAlchemy()
from recetaspy import paginas, auth
def create_app():
app = Flask(__name__)
app.config.from_prefixed_env()
app.config['SECRET_KEY'] = 'secret-key-goes-here'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///recipes.db'
app.config['UPLOAD_FOLDER'] = os.path.join(app.instance_path, 'uploads')
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16 MB máximo
# Asegúrate de que el directorio de carga existe
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
from .models import db
db.init_app(app)
login_manager = LoginManager()
login_manager.login_view = 'auth.login'
login_manager.init_app(app)
from .models import User
@login_manager.user_loader
def load_user(user_id):
# since the user_id is just the primary key of our user table, use it in the query for the user
return User.query.get(int(user_id))
from . import models
with app.app_context():
db.create_all()
app.register_blueprint(paginas.bp)
app.register_blueprint(auth.bp)
print(f"Current Environment: {os.getenv('ENVIRONMENT')}")
print(f"Using Database: {app.config.get('DATABASE')}")
print(f"Directorio de uploads: {app.config.get('UPLOAD_FOLDER')}")
print(f"instance: {app.instance_path}")
print(f"Saludo: {os.getenv('SALUDO_DEMO')}")
return app

+ 82
- 0
RecetasPy/servicios/recetaspy/auth.py View File

@ -0,0 +1,82 @@
from flask import Blueprint, render_template, redirect, url_for, request, flash, current_app
from werkzeug.security import generate_password_hash, check_password_hash
from werkzeug.utils import secure_filename
from flask_login import login_user, logout_user, login_required
from .models import User
import os
from . import db
bp = Blueprint('auth', __name__)
@bp.route('/login')
def login():
return render_template('login.html')
@bp.route('/login', methods=['POST'])
def login_post():
email = request.form['email']
password = request.form['password']
remember = True if request.form.get('remember') else False
user = User.query.filter_by(email=email).first()
# check if the user actually exists
# take the user-supplied password, hash it, and compare it to the hashed password in the database
if not user or not check_password_hash(user.password, password):
flash('Por favor, comprueba los datos de registro y vuelve a intentarlo.')
return redirect(url_for('auth.login')) # if the user doesn't exist or password is wrong, reload the page
# if the above check passes, then we know the user has the right credentials
login_user(user, remember=remember)
return redirect(url_for('paginas.index'))
@bp.route('/signup')
def signup():
return render_template('signup.html')
@bp.route('/signup', methods=['POST'])
def signup_post():
username = request.form['username']
email = request.form['email']
password = request.form['password']
confirm_password = request.form['confirm_password']
photo = request.files['fotoperfil']
if password != confirm_password:
flash('Passwords do not match.')
return redirect(url_for('auth.signup'))
user = User.query.filter_by(email=email).first() # if this returns a user, then the user already exists in database
if user: # if a user is found, we want to redirect back to signup page so user can try again
flash('Ese usuario ya existe')
return redirect(url_for('auth.signup'))
if photo:
photo_filename = secure_filename(photo.filename)
photo.save(os.path.join(current_app.config['UPLOAD_FOLDER'], photo_filename))
else:
photo_filename = ""
# create a new user with the form data. Hash the password so the plaintext version isn't saved.
new_user = User(email=email, username=username, password=generate_password_hash(password, method='pbkdf2:sha256'), photo=photo_filename)
# add the new user to the database
# try:
db.session.add(new_user)
db.session.commit()
flash('Registration successful.')
return redirect(url_for('auth.login'))
# except:
# flash('Email address already exists.')
# return redirect(url_for('auth.signup'))
@bp.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('paginas.index'))

+ 33
- 0
RecetasPy/servicios/recetaspy/models.py View File

@ -0,0 +1,33 @@
from flask_sqlalchemy import SQLAlchemy
from flask_login import UserMixin
from . import db
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(150), unique=True, nullable=False)
email = db.Column(db.String(150), unique=True, nullable=False)
password = db.Column(db.String(150), nullable=False)
recipes = db.relationship('Recipe', backref='author', lazy=True)
photo = db.Column(db.String(150), nullable=False)
class Recipe(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(150), nullable=False)
description = db.Column(db.Text, nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
ingredients = db.relationship('Ingredient', backref='recipe', lazy=True)
instructions = db.relationship('Instruction', backref='recipe', lazy=True)
class Ingredient(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
quantity = db.Column(db.String(50), nullable=False)
recipe_id = db.Column(db.Integer, db.ForeignKey('recipe.id'), nullable=False)
class Instruction(db.Model):
id = db.Column(db.Integer, primary_key=True)
step = db.Column(db.Integer, nullable=False)
description = db.Column(db.Text, nullable=False)
recipe_id = db.Column(db.Integer, db.ForeignKey('recipe.id'), nullable=False)

+ 87
- 0
RecetasPy/servicios/recetaspy/paginas.py View File

@ -0,0 +1,87 @@
from flask import Blueprint, render_template, request, redirect, url_for, current_app, send_from_directory,flash
from werkzeug.utils import secure_filename
from flask_login import login_user, logout_user, login_required, current_user
import os
from .models import db, Recipe, Ingredient, Instruction
bp = Blueprint("paginas", __name__)
@bp.route('/')
def index():
recipes = Recipe.query.all()
return render_template('index.html', recipes=recipes)
@bp.route('/recipe/<int:recipe_id>')
def recipe(recipe_id):
recipe = Recipe.query.get_or_404(recipe_id)
return render_template('recipe.html', recipe=recipe)
@bp.route('/new_recipe', methods=['GET', 'POST'])
@login_required
def new_recipe():
if request.method == 'POST':
title = request.form['title']
description = request.form['description']
ingredients = request.form.getlist('ingredient')
quantities = request.form.getlist('quantity')
steps = request.form.getlist('step')
step_descriptions = request.form.getlist('step_description')
recipe = Recipe(title=title, description=description, author=current_user)
for ingredient, quantity in zip(ingredients, quantities):
recipe.ingredients.append(Ingredient(name=ingredient, quantity=quantity))
for step, description in zip(steps, step_descriptions):
recipe.instructions.append(Instruction(step=step, description=description))
db.session.add(recipe)
db.session.commit()
flash('Recipe created successfully!', 'success')
return redirect(url_for('index'))
return render_template('new_recipe.html')
@bp.route('/account')
@login_required
def account():
return render_template('account.html')
@bp.route('/settings')
@login_required
def settings():
return render_template('settings.html')
@bp.route('/reset-password')
def resetpassword():
return render_template('reset-password.html')
@bp.route('/404')
def cuatrocerocuatro():
return render_template('404.html')
@bp.route('/charts')
@login_required
def charts():
return render_template('charts.html')
@bp.route('/help')
def help():
return render_template('help.html')
@bp.route('/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(current_app.config['UPLOAD_FOLDER'], filename)
@bp.route('/notifications')
def notifications():
return render_template('notifications.html')
@bp.route('/docs')
def docs():
return render_template('docs.html')
@bp.route('/orders')
def orders():
return render_template('orders.html')

+ 12
- 0
RecetasPy/servicios/recetaspy/static/css/portal.css
File diff suppressed because it is too large
View File


+ 21
- 0
RecetasPy/servicios/recetaspy/static/images/app-logo.svg View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="215px" height="215px" viewBox="0 0 215 215" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 52.6 (67491) - http://www.bohemiancoding.com/sketch -->
<title>portal-logo</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M51.165,8.742 C54.505,12.619 56.876,17.365 57.892,22.588 C60.148,17.225 65.452,13.46 71.636,13.46 C79.867,13.46 86.541,20.134 86.541,28.365 C86.541,36.597 79.867,43.269 71.636,43.269 C63.404,43.269 56.728,36.597 56.728,28.365 C56.728,12.7 44.03,0 28.365,0 C12.7,0 0,12.7 0,28.365 C0,44.031 12.7,56.731 28.365,56.731 C36.419,56.731 43.695,53.393 48.858,48.003 C45.501,44.117 43.128,39.383 42.108,34.14 C39.852,39.504 34.548,43.269 28.365,43.269 C20.133,43.269 13.46,36.597 13.46,28.365 C13.46,20.134 20.133,13.46 28.365,13.46 C36.966,13.46 43.27,20.577 43.27,28.365 C43.27,44.031 55.97,56.731 71.636,56.731 C87.3,56.731 100,44.031 100,28.365 C100,12.7 87.3,0 71.636,0 C63.589,0 56.327,3.358 51.165,8.742 Z" id="path-1"></path>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="portal-logo">
<circle id="Oval" fill="#51B37F" fill-rule="nonzero" cx="107.5" cy="107.5" r="107.5"></circle>
<g id="logo" transform="translate(58.000000, 79.000000)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="Clip-2"></g>
<polygon id="Fill-1" fill="#FFFFFE" mask="url(#mask-2)" points="-5 61.73 105 61.73 105 -5 -5 -5"></polygon>
</g>
</g>
</g>
</svg>

BIN
RecetasPy/servicios/recetaspy/static/images/background/background-1.jpg View File

Before After
Width: 1000  |  Height: 1139  |  Size: 150 KiB

BIN
RecetasPy/servicios/recetaspy/static/images/background/background-2.jpg View File

Before After
Width: 1200  |  Height: 781  |  Size: 232 KiB

BIN
RecetasPy/servicios/recetaspy/static/images/background/background-3.jpg View File

Before After
Width: 1200  |  Height: 789  |  Size: 256 KiB

BIN
RecetasPy/servicios/recetaspy/static/images/background/background-palmeras.jpg View File

Before After
Width: 1000  |  Height: 1139  |  Size: 360 KiB

BIN
RecetasPy/servicios/recetaspy/static/images/doc-thumb-1.jpg View File

Before After
Width: 600  |  Height: 432  |  Size: 75 KiB

BIN
RecetasPy/servicios/recetaspy/static/images/doc-thumb-2.jpg View File

Before After
Width: 600  |  Height: 472  |  Size: 75 KiB

+ 21
- 0
RecetasPy/servicios/recetaspy/static/images/portal-logo.svg View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="215px" height="215px" viewBox="0 0 215 215" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 52.6 (67491) - http://www.bohemiancoding.com/sketch -->
<title>portal-logo</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M51.165,8.742 C54.505,12.619 56.876,17.365 57.892,22.588 C60.148,17.225 65.452,13.46 71.636,13.46 C79.867,13.46 86.541,20.134 86.541,28.365 C86.541,36.597 79.867,43.269 71.636,43.269 C63.404,43.269 56.728,36.597 56.728,28.365 C56.728,12.7 44.03,0 28.365,0 C12.7,0 0,12.7 0,28.365 C0,44.031 12.7,56.731 28.365,56.731 C36.419,56.731 43.695,53.393 48.858,48.003 C45.501,44.117 43.128,39.383 42.108,34.14 C39.852,39.504 34.548,43.269 28.365,43.269 C20.133,43.269 13.46,36.597 13.46,28.365 C13.46,20.134 20.133,13.46 28.365,13.46 C36.966,13.46 43.27,20.577 43.27,28.365 C43.27,44.031 55.97,56.731 71.636,56.731 C87.3,56.731 100,44.031 100,28.365 C100,12.7 87.3,0 71.636,0 C63.589,0 56.327,3.358 51.165,8.742 Z" id="path-1"></path>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="portal-logo">
<circle id="Oval" fill="#09B6CA" fill-rule="nonzero" cx="107.5" cy="107.5" r="107.5"></circle>
<g id="logo" transform="translate(58.000000, 79.000000)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="Clip-2"></g>
<polygon id="Fill-1" fill="#FFFFFE" mask="url(#mask-2)" points="-5 61.73 105 61.73 105 -5 -5 -5"></polygon>
</g>
</g>
</g>
</svg>

BIN
RecetasPy/servicios/recetaspy/static/images/profiles/profile-1.png View File

Before After
Width: 120  |  Height: 120  |  Size: 34 KiB

BIN
RecetasPy/servicios/recetaspy/static/images/profiles/profile-2.png View File

Before After
Width: 120  |  Height: 120  |  Size: 35 KiB

BIN
RecetasPy/servicios/recetaspy/static/images/profiles/profile-3.png View File

Before After
Width: 120  |  Height: 120  |  Size: 37 KiB

BIN
RecetasPy/servicios/recetaspy/static/images/profiles/profile-4.png View File

Before After
Width: 120  |  Height: 120  |  Size: 22 KiB

BIN
RecetasPy/servicios/recetaspy/static/images/profiles/profile-5.png View File

Before After
Width: 120  |  Height: 120  |  Size: 36 KiB

BIN
RecetasPy/servicios/recetaspy/static/images/profiles/profile-6.png View File

Before After
Width: 120  |  Height: 120  |  Size: 29 KiB

+ 18
- 0
RecetasPy/servicios/recetaspy/static/images/reymota-logo.svg View File

@ -0,0 +1,18 @@
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg">
<!-- Fondo -->
<rect width="400" height="400" fill="#ffffff" />
<!-- Corona -->
<g transform="translate(100, 100) scale(2)">
<polygon points="50,150 75,50 100,150" fill="#FFD700" />
<polygon points="0,150 50,0 100,150" fill="#FFD700" />
<polygon points="100,150 125,50 150,150" fill="#FFD700" />
</g>
<!-- Letra R -->
<!--
<text x="100" y="360" font-family="Arial, sans-serif" font-size="400" fill="#000000" font-weight="bold">R</text>
-->
<text x="100" y="360" font-family="Open Sans" font-size="400" fill="#000000" font-weight="bold">R</text>
</svg>

BIN
RecetasPy/servicios/recetaspy/static/images/user.png View File

Before After
Width: 120  |  Height: 120  |  Size: 38 KiB

BIN
RecetasPy/servicios/recetaspy/static/images/users/user-1.jpg View File

Before After
Width: 200  |  Height: 200  |  Size: 48 KiB

BIN
RecetasPy/servicios/recetaspy/static/images/users/user-2.jpg View File

Before After
Width: 350  |  Height: 350  |  Size: 28 KiB

BIN
RecetasPy/servicios/recetaspy/static/images/users/user-3.jpg View File

Before After
Width: 200  |  Height: 200  |  Size: 40 KiB

BIN
RecetasPy/servicios/recetaspy/static/images/users/user-4.jpg View File

Before After
Width: 240  |  Height: 240  |  Size: 7.2 KiB

BIN
RecetasPy/servicios/recetaspy/static/images/users/user-5.jpg View File

Before After
Width: 240  |  Height: 240  |  Size: 22 KiB

BIN
RecetasPy/servicios/recetaspy/static/images/users/user-6.jpg View File

Before After
Width: 240  |  Height: 240  |  Size: 9.1 KiB

BIN
RecetasPy/servicios/recetaspy/static/images/users/user-7.jpg View File

Before After
Width: 240  |  Height: 240  |  Size: 22 KiB

BIN
RecetasPy/servicios/recetaspy/static/images/users/user-8.jpg View File

Before After
Width: 240  |  Height: 240  |  Size: 12 KiB

BIN
RecetasPy/servicios/recetaspy/static/images/users/user-9.jpg View File

Before After
Width: 240  |  Height: 240  |  Size: 32 KiB

+ 96
- 0
RecetasPy/servicios/recetaspy/static/js/app.js View File

@ -0,0 +1,96 @@
'use strict';
/* ===== Enable Bootstrap Popover (on element ====== */
const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]')
const popoverList = [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl))
/* ==== Enable Bootstrap Alert ====== */
//var alertList = document.querySelectorAll('.alert')
//alertList.forEach(function (alert) {
// new bootstrap.Alert(alert)
//});
const alertList = document.querySelectorAll('.alert')
const alerts = [...alertList].map(element => new bootstrap.Alert(element))
/* ===== Responsive Sidepanel ====== */
const sidePanelToggler = document.getElementById('sidepanel-toggler');
const sidePanel = document.getElementById('app-sidepanel');
const sidePanelDrop = document.getElementById('sidepanel-drop');
const sidePanelClose = document.getElementById('sidepanel-close');
window.addEventListener('load', function(){
responsiveSidePanel();
});
window.addEventListener('resize', function(){
responsiveSidePanel();
});
function responsiveSidePanel() {
let w = window.innerWidth;
if(w >= 1200) {
// if larger
//console.log('larger');
sidePanel.classList.remove('sidepanel-hidden');
sidePanel.classList.add('sidepanel-visible');
} else {
// if smaller
//console.log('smaller');
sidePanel.classList.remove('sidepanel-visible');
sidePanel.classList.add('sidepanel-hidden');
}
};
sidePanelToggler.addEventListener('click', () => {
if (sidePanel.classList.contains('sidepanel-visible')) {
console.log('visible');
sidePanel.classList.remove('sidepanel-visible');
sidePanel.classList.add('sidepanel-hidden');
} else {
console.log('hidden');
sidePanel.classList.remove('sidepanel-hidden');
sidePanel.classList.add('sidepanel-visible');
}
});
sidePanelClose.addEventListener('click', (e) => {
e.preventDefault();
sidePanelToggler.click();
});
sidePanelDrop.addEventListener('click', (e) => {
sidePanelToggler.click();
});
/* ====== Mobile search ======= */
const searchMobileTrigger = document.querySelector('.search-mobile-trigger');
const searchBox = document.querySelector('.app-search-box');
searchMobileTrigger.addEventListener('click', () => {
searchBox.classList.toggle('is-visible');
let searchMobileTriggerIcon = document.querySelector('.search-mobile-trigger-icon');
if(searchMobileTriggerIcon.classList.contains('fa-magnifying-glass')) {
searchMobileTriggerIcon.classList.remove('fa-magnifying-glass');
searchMobileTriggerIcon.classList.add('fa-xmark');
} else {
searchMobileTriggerIcon.classList.remove('fa-xmark');
searchMobileTriggerIcon.classList.add('fa-magnifying-glass');
}
});

+ 366
- 0
RecetasPy/servicios/recetaspy/static/js/charts-demo.js View File

@ -0,0 +1,366 @@
'use strict';
/* Chart.js docs: https://www.chartjs.org/ */
window.chartColors = {
green: '#75c181', // rgba(117,193,129, 1)
blue: '#5b99ea', // rgba(91,153,234, 1)
gray: '#a9b5c9',
text: '#252930',
border: '#e7e9ed'
};
/* Random number generator for demo purpose */
var randomDataPoint = function(){ return Math.round(Math.random()*100)};
//Area line Chart Demo
var lineChartConfig = {
type: 'line',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'],
datasets: [{
label: 'Dataset',
backgroundColor: "rgba(117,193,129,0.2)",
borderColor: "rgba(117,193,129, 0.8)",
data: [
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint()
],
}]
},
options: {
responsive: true,
legend: {
display: true,
position: 'bottom',
align: 'end',
},
tooltips: {
mode: 'index',
intersect: false,
titleMarginBottom: 10,
bodySpacing: 10,
xPadding: 16,
yPadding: 16,
borderColor: window.chartColors.border,
borderWidth: 1,
backgroundColor: '#fff',
bodyFontColor: window.chartColors.text,
titleFontColor: window.chartColors.text,
callbacks: {
label: function(tooltipItem, data) {
return tooltipItem.value + '%';
}
},
},
hover: {
mode: 'nearest',
intersect: true
},
scales: {
xAxes: [{
display: true,
gridLines: {
drawBorder: false,
color: window.chartColors.border,
},
scaleLabel: {
display: false,
}
}],
yAxes: [{
display: true,
gridLines: {
drawBorder: false,
color: window.chartColors.border,
},
scaleLabel: {
display: false,
},
ticks: {
beginAtZero: true,
userCallback: function(value, index, values) {
return value.toLocaleString() + '%';
}
},
}]
}
}
};
//Bar Chart Demo
var barChartConfig = {
type: 'bar',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'],
datasets: [{
label: 'Dataset 1',
backgroundColor: "rgba(117,193,129,0.8)",
hoverBackgroundColor: "rgba(117,193,129,1)",
data: [
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint()
]
},
{
label: 'Dataset 2',
backgroundColor: "rgba(91,153,234,0.8)",
hoverBackgroundColor: "rgba(91,153,234,1)",
data: [
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint()
]
}
]
},
options: {
responsive: true,
legend: {
position: 'bottom',
align: 'end',
},
tooltips: {
mode: 'index',
intersect: false,
titleMarginBottom: 10,
bodySpacing: 10,
xPadding: 16,
yPadding: 16,
borderColor: window.chartColors.border,
borderWidth: 1,
backgroundColor: '#fff',
bodyFontColor: window.chartColors.text,
titleFontColor: window.chartColors.text,
callbacks: {
label: function(tooltipItem, data) {
return tooltipItem.value + '%';
}
},
},
scales: {
xAxes: [{
display: true,
gridLines: {
drawBorder: false,
color: window.chartColors.border,
},
}],
yAxes: [{
display: true,
gridLines: {
drawBorder: false,
color: window.chartColors.borders,
},
ticks: {
beginAtZero: true,
userCallback: function(value, index, values) {
return value + '%';
}
},
}]
}
}
}
// Pie Chart Demo
var pieChartConfig = {
type: 'pie',
data: {
datasets: [{
data: [
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
],
backgroundColor: [
window.chartColors.green,
window.chartColors.blue,
window.chartColors.gray,
],
label: 'Dataset 1'
}],
labels: [
'Green',
'Blue',
'Gray',
]
},
options: {
responsive: true,
legend: {
display: true,
position: 'bottom',
align: 'center',
},
tooltips: {
titleMarginBottom: 10,
bodySpacing: 10,
xPadding: 16,
yPadding: 16,
borderColor: window.chartColors.border,
borderWidth: 1,
backgroundColor: '#fff',
bodyFontColor: window.chartColors.text,
titleFontColor: window.chartColors.text,
/* Display % in tooltip - https://stackoverflow.com/questions/37257034/chart-js-2-0-doughnut-tooltip-percentages */
callbacks: {
label: function(tooltipItem, data) {
//get the concerned dataset
var dataset = data.datasets[tooltipItem.datasetIndex];
//calculate the total of this data set
var total = dataset.data.reduce(function(previousValue, currentValue, currentIndex, array) {
return previousValue + currentValue;
});
//get the current items value
var currentValue = dataset.data[tooltipItem.index];
//calculate the precentage based on the total and current item, also this does a rough rounding to give a whole number
var percentage = Math.floor(((currentValue/total) * 100)+0.5);
return percentage + "%";
},
},
},
}
};
// Doughnut Chart Demo
var doughnutChartConfig = {
type: 'doughnut',
data: {
datasets: [{
data: [
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
],
backgroundColor: [
window.chartColors.green,
window.chartColors.blue,
window.chartColors.gray,
],
label: 'Dataset 1'
}],
labels: [
'Green',
'Blue',
'Gray',
]
},
options: {
responsive: true,
legend: {
display: true,
position: 'bottom',
align: 'center',
},
tooltips: {
titleMarginBottom: 10,
bodySpacing: 10,
xPadding: 16,
yPadding: 16,
borderColor: window.chartColors.border,
borderWidth: 1,
backgroundColor: '#fff',
bodyFontColor: window.chartColors.text,
titleFontColor: window.chartColors.text,
animation: {
animateScale: true,
animateRotate: true
},
/* Display % in tooltip - https://stackoverflow.com/questions/37257034/chart-js-2-0-doughnut-tooltip-percentages */
callbacks: {
label: function(tooltipItem, data) {
//get the concerned dataset
var dataset = data.datasets[tooltipItem.datasetIndex];
//calculate the total of this data set
var total = dataset.data.reduce(function(previousValue, currentValue, currentIndex, array) {
return previousValue + currentValue;
});
//get the current items value
var currentValue = dataset.data[tooltipItem.index];
//calculate the precentage based on the total and current item, also this does a rough rounding to give a whole number
var percentage = Math.floor(((currentValue/total) * 100)+0.5);
return percentage + "%";
},
},
},
}
};
// Generate charts on load
window.addEventListener('load', function(){
var lineChart = document.getElementById('chart-line').getContext('2d');
window.myLine = new Chart(lineChart, lineChartConfig);
var barChart = document.getElementById('chart-bar').getContext('2d');
window.myBar = new Chart(barChart, barChartConfig);
var pieChart = document.getElementById('chart-pie').getContext('2d');
window.myPie = new Chart(pieChart, pieChartConfig);
var doughnutChart = document.getElementById('chart-doughnut').getContext('2d');
window.myDoughnut = new Chart(doughnutChart, doughnutChartConfig);
});

+ 224
- 0
RecetasPy/servicios/recetaspy/static/js/index-charts.js View File

@ -0,0 +1,224 @@
'use strict';
/* Chart.js docs: https://www.chartjs.org/ */
window.chartColors = {
green: '#75c181',
gray: '#a9b5c9',
text: '#252930',
border: '#e7e9ed'
};
/* Random number generator for demo purpose */
var randomDataPoint = function(){ return Math.round(Math.random()*10000)};
//Chart.js Line Chart Example
var lineChartConfig = {
type: 'line',
data: {
labels: ['Day 1', 'Day 2', 'Day 3', 'Day 4', 'Day 5', 'Day 6', 'Day 7'],
datasets: [{
label: 'Current week',
fill: false,
backgroundColor: window.chartColors.green,
borderColor: window.chartColors.green,
data: [
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint()
],
}, {
label: 'Previous week',
borderDash: [3, 5],
backgroundColor: window.chartColors.gray,
borderColor: window.chartColors.gray,
data: [
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint()
],
fill: false,
}]
},
options: {
responsive: true,
aspectRatio: 1.5,
legend: {
display: true,
position: 'bottom',
align: 'end',
},
title: {
display: true,
text: 'Chart.js Line Chart Example',
},
tooltips: {
mode: 'index',
intersect: false,
titleMarginBottom: 10,
bodySpacing: 10,
xPadding: 16,
yPadding: 16,
borderColor: window.chartColors.border,
borderWidth: 1,
backgroundColor: '#fff',
bodyFontColor: window.chartColors.text,
titleFontColor: window.chartColors.text,
callbacks: {
//Ref: https://stackoverflow.com/questions/38800226/chart-js-add-commas-to-tooltip-and-y-axis
label: function(tooltipItem, data) {
if (parseInt(tooltipItem.value) >= 1000) {
return "$" + tooltipItem.value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
} else {
return '$' + tooltipItem.value;
}
}
},
},
hover: {
mode: 'nearest',
intersect: true
},
scales: {
xAxes: [{
display: true,
gridLines: {
drawBorder: false,
color: window.chartColors.border,
},
scaleLabel: {
display: false,
}
}],
yAxes: [{
display: true,
gridLines: {
drawBorder: false,
color: window.chartColors.border,
},
scaleLabel: {
display: false,
},
ticks: {
beginAtZero: true,
userCallback: function(value, index, values) {
return '$' + value.toLocaleString(); //Ref: https://stackoverflow.com/questions/38800226/chart-js-add-commas-to-tooltip-and-y-axis
}
},
}]
}
}
};
// Chart.js Bar Chart Example
var barChartConfig = {
type: 'bar',
data: {
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
datasets: [{
label: 'Orders',
backgroundColor: window.chartColors.green,
borderColor: window.chartColors.green,
borderWidth: 1,
maxBarThickness: 16,
data: [
23,
45,
76,
75,
62,
37,
83
]
}]
},
options: {
responsive: true,
aspectRatio: 1.5,
legend: {
position: 'bottom',
align: 'end',
},
title: {
display: true,
text: 'Chart.js Bar Chart Example'
},
tooltips: {
mode: 'index',
intersect: false,
titleMarginBottom: 10,
bodySpacing: 10,
xPadding: 16,
yPadding: 16,
borderColor: window.chartColors.border,
borderWidth: 1,
backgroundColor: '#fff',
bodyFontColor: window.chartColors.text,
titleFontColor: window.chartColors.text,
},
scales: {
xAxes: [{
display: true,
gridLines: {
drawBorder: false,
color: window.chartColors.border,
},
}],
yAxes: [{
display: true,
gridLines: {
drawBorder: false,
color: window.chartColors.borders,
},
}]
}
}
}
// Generate charts on load
window.addEventListener('load', function(){
var lineChart = document.getElementById('canvas-linechart').getContext('2d');
window.myLine = new Chart(lineChart, lineChartConfig);
var barChart = document.getElementById('canvas-barchart').getContext('2d');
window.myBar = new Chart(barChart, barChartConfig);
});

+ 4085
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-grid.css
File diff suppressed because it is too large
View File


+ 1
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-grid.css.map
File diff suppressed because it is too large
View File


+ 6
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-grid.min.css
File diff suppressed because it is too large
View File


+ 1
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-grid.min.css.map
File diff suppressed because it is too large
View File


+ 4084
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-grid.rtl.css
File diff suppressed because it is too large
View File


+ 1
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-grid.rtl.css.map
File diff suppressed because it is too large
View File


+ 6
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-grid.rtl.min.css
File diff suppressed because it is too large
View File


+ 1
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-grid.rtl.min.css.map
File diff suppressed because it is too large
View File


+ 593
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-reboot.css View File

@ -0,0 +1,593 @@
/*!
* Bootstrap Reboot v5.3.0 (https://getbootstrap.com/)
* Copyright 2011-2023 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
:root,
[data-bs-theme=light] {
--bs-blue: #0d6efd;
--bs-indigo: #6610f2;
--bs-purple: #6f42c1;
--bs-pink: #d63384;
--bs-red: #dc3545;
--bs-orange: #fd7e14;
--bs-yellow: #ffc107;
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-black: #000;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
--bs-gray-100: #f8f9fa;
--bs-gray-200: #e9ecef;
--bs-gray-300: #dee2e6;
--bs-gray-400: #ced4da;
--bs-gray-500: #adb5bd;
--bs-gray-600: #6c757d;
--bs-gray-700: #495057;
--bs-gray-800: #343a40;
--bs-gray-900: #212529;
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 13, 110, 253;
--bs-secondary-rgb: 108, 117, 125;
--bs-success-rgb: 25, 135, 84;
--bs-info-rgb: 13, 202, 240;
--bs-warning-rgb: 255, 193, 7;
--bs-danger-rgb: 220, 53, 69;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-primary-text-emphasis: #052c65;
--bs-secondary-text-emphasis: #2b2f32;
--bs-success-text-emphasis: #0a3622;
--bs-info-text-emphasis: #055160;
--bs-warning-text-emphasis: #664d03;
--bs-danger-text-emphasis: #58151c;
--bs-light-text-emphasis: #495057;
--bs-dark-text-emphasis: #495057;
--bs-primary-bg-subtle: #cfe2ff;
--bs-secondary-bg-subtle: #e2e3e5;
--bs-success-bg-subtle: #d1e7dd;
--bs-info-bg-subtle: #cff4fc;
--bs-warning-bg-subtle: #fff3cd;
--bs-danger-bg-subtle: #f8d7da;
--bs-light-bg-subtle: #fcfcfd;
--bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: #9ec5fe;
--bs-secondary-border-subtle: #c4c8cb;
--bs-success-border-subtle: #a3cfbb;
--bs-info-border-subtle: #9eeaf9;
--bs-warning-border-subtle: #ffe69c;
--bs-danger-border-subtle: #f1aeb5;
--bs-light-border-subtle: #e9ecef;
--bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255;
--bs-black-rgb: 0, 0, 0;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg: #fff;
--bs-body-bg-rgb: 255, 255, 255;
--bs-emphasis-color: #000;
--bs-emphasis-color-rgb: 0, 0, 0;
--bs-secondary-color: rgba(33, 37, 41, 0.75);
--bs-secondary-color-rgb: 33, 37, 41;
--bs-secondary-bg: #e9ecef;
--bs-secondary-bg-rgb: 233, 236, 239;
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
--bs-tertiary-color-rgb: 33, 37, 41;
--bs-tertiary-bg: #f8f9fa;
--bs-tertiary-bg-rgb: 248, 249, 250;
--bs-heading-color: inherit;
--bs-link-color: #0d6efd;
--bs-link-color-rgb: 13, 110, 253;
--bs-link-decoration: underline;
--bs-link-hover-color: #0a58ca;
--bs-link-hover-color-rgb: 10, 88, 202;
--bs-code-color: #d63384;
--bs-highlight-bg: #fff3cd;
--bs-border-width: 1px;
--bs-border-style: solid;
--bs-border-color: #dee2e6;
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
--bs-border-radius: 0.375rem;
--bs-border-radius-sm: 0.25rem;
--bs-border-radius-lg: 0.5rem;
--bs-border-radius-xl: 1rem;
--bs-border-radius-xxl: 2rem;
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
--bs-border-radius-pill: 50rem;
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
--bs-focus-ring-width: 0.25rem;
--bs-focus-ring-opacity: 0.25;
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
--bs-form-valid-color: #198754;
--bs-form-valid-border-color: #198754;
--bs-form-invalid-color: #dc3545;
--bs-form-invalid-border-color: #dc3545;
}
[data-bs-theme=dark] {
color-scheme: dark;
--bs-body-color: #adb5bd;
--bs-body-color-rgb: 173, 181, 189;
--bs-body-bg: #212529;
--bs-body-bg-rgb: 33, 37, 41;
--bs-emphasis-color: #fff;
--bs-emphasis-color-rgb: 255, 255, 255;
--bs-secondary-color: rgba(173, 181, 189, 0.75);
--bs-secondary-color-rgb: 173, 181, 189;
--bs-secondary-bg: #343a40;
--bs-secondary-bg-rgb: 52, 58, 64;
--bs-tertiary-color: rgba(173, 181, 189, 0.5);
--bs-tertiary-color-rgb: 173, 181, 189;
--bs-tertiary-bg: #2b3035;
--bs-tertiary-bg-rgb: 43, 48, 53;
--bs-primary-text-emphasis: #6ea8fe;
--bs-secondary-text-emphasis: #a7acb1;
--bs-success-text-emphasis: #75b798;
--bs-info-text-emphasis: #6edff6;
--bs-warning-text-emphasis: #ffda6a;
--bs-danger-text-emphasis: #ea868f;
--bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: #031633;
--bs-secondary-bg-subtle: #161719;
--bs-success-bg-subtle: #051b11;
--bs-info-bg-subtle: #032830;
--bs-warning-bg-subtle: #332701;
--bs-danger-bg-subtle: #2c0b0e;
--bs-light-bg-subtle: #343a40;
--bs-dark-bg-subtle: #1a1d20;
--bs-primary-border-subtle: #084298;
--bs-secondary-border-subtle: #41464b;
--bs-success-border-subtle: #0f5132;
--bs-info-border-subtle: #087990;
--bs-warning-border-subtle: #997404;
--bs-danger-border-subtle: #842029;
--bs-light-border-subtle: #495057;
--bs-dark-border-subtle: #343a40;
--bs-heading-color: inherit;
--bs-link-color: #6ea8fe;
--bs-link-hover-color: #8bb9fe;
--bs-link-color-rgb: 110, 168, 254;
--bs-link-hover-color-rgb: 139, 185, 254;
--bs-code-color: #e685b5;
--bs-border-color: #495057;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: #75b798;
--bs-form-valid-border-color: #75b798;
--bs-form-invalid-color: #ea868f;
--bs-form-invalid-border-color: #ea868f;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
border: 0;
border-top: var(--bs-border-width) solid;
opacity: 0.25;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
color: var(--bs-heading-color);
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-left: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-left: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.1875em;
background-color: var(--bs-highlight-bg);
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
text-decoration: underline;
}
a:hover {
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: var(--bs-code-color);
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.1875rem 0.375rem;
font-size: 0.875em;
color: var(--bs-body-bg);
background-color: var(--bs-body-color);
border-radius: 0.25rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: var(--bs-secondary-color);
text-align: left;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
display: none !important;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: left;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: left;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
outline-offset: -2px;
-webkit-appearance: textfield;
}
/* rtl:raw:
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
*/
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
::file-selector-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.css.map */

+ 1
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-reboot.css.map
File diff suppressed because it is too large
View File


+ 6
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-reboot.min.css
File diff suppressed because it is too large
View File


+ 1
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-reboot.min.css.map
File diff suppressed because it is too large
View File


+ 590
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-reboot.rtl.css View File

@ -0,0 +1,590 @@
/*!
* Bootstrap Reboot v5.3.0 (https://getbootstrap.com/)
* Copyright 2011-2023 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
:root,
[data-bs-theme=light] {
--bs-blue: #0d6efd;
--bs-indigo: #6610f2;
--bs-purple: #6f42c1;
--bs-pink: #d63384;
--bs-red: #dc3545;
--bs-orange: #fd7e14;
--bs-yellow: #ffc107;
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-black: #000;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
--bs-gray-100: #f8f9fa;
--bs-gray-200: #e9ecef;
--bs-gray-300: #dee2e6;
--bs-gray-400: #ced4da;
--bs-gray-500: #adb5bd;
--bs-gray-600: #6c757d;
--bs-gray-700: #495057;
--bs-gray-800: #343a40;
--bs-gray-900: #212529;
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 13, 110, 253;
--bs-secondary-rgb: 108, 117, 125;
--bs-success-rgb: 25, 135, 84;
--bs-info-rgb: 13, 202, 240;
--bs-warning-rgb: 255, 193, 7;
--bs-danger-rgb: 220, 53, 69;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-primary-text-emphasis: #052c65;
--bs-secondary-text-emphasis: #2b2f32;
--bs-success-text-emphasis: #0a3622;
--bs-info-text-emphasis: #055160;
--bs-warning-text-emphasis: #664d03;
--bs-danger-text-emphasis: #58151c;
--bs-light-text-emphasis: #495057;
--bs-dark-text-emphasis: #495057;
--bs-primary-bg-subtle: #cfe2ff;
--bs-secondary-bg-subtle: #e2e3e5;
--bs-success-bg-subtle: #d1e7dd;
--bs-info-bg-subtle: #cff4fc;
--bs-warning-bg-subtle: #fff3cd;
--bs-danger-bg-subtle: #f8d7da;
--bs-light-bg-subtle: #fcfcfd;
--bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: #9ec5fe;
--bs-secondary-border-subtle: #c4c8cb;
--bs-success-border-subtle: #a3cfbb;
--bs-info-border-subtle: #9eeaf9;
--bs-warning-border-subtle: #ffe69c;
--bs-danger-border-subtle: #f1aeb5;
--bs-light-border-subtle: #e9ecef;
--bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255;
--bs-black-rgb: 0, 0, 0;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg: #fff;
--bs-body-bg-rgb: 255, 255, 255;
--bs-emphasis-color: #000;
--bs-emphasis-color-rgb: 0, 0, 0;
--bs-secondary-color: rgba(33, 37, 41, 0.75);
--bs-secondary-color-rgb: 33, 37, 41;
--bs-secondary-bg: #e9ecef;
--bs-secondary-bg-rgb: 233, 236, 239;
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
--bs-tertiary-color-rgb: 33, 37, 41;
--bs-tertiary-bg: #f8f9fa;
--bs-tertiary-bg-rgb: 248, 249, 250;
--bs-heading-color: inherit;
--bs-link-color: #0d6efd;
--bs-link-color-rgb: 13, 110, 253;
--bs-link-decoration: underline;
--bs-link-hover-color: #0a58ca;
--bs-link-hover-color-rgb: 10, 88, 202;
--bs-code-color: #d63384;
--bs-highlight-bg: #fff3cd;
--bs-border-width: 1px;
--bs-border-style: solid;
--bs-border-color: #dee2e6;
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
--bs-border-radius: 0.375rem;
--bs-border-radius-sm: 0.25rem;
--bs-border-radius-lg: 0.5rem;
--bs-border-radius-xl: 1rem;
--bs-border-radius-xxl: 2rem;
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
--bs-border-radius-pill: 50rem;
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
--bs-focus-ring-width: 0.25rem;
--bs-focus-ring-opacity: 0.25;
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
--bs-form-valid-color: #198754;
--bs-form-valid-border-color: #198754;
--bs-form-invalid-color: #dc3545;
--bs-form-invalid-border-color: #dc3545;
}
[data-bs-theme=dark] {
color-scheme: dark;
--bs-body-color: #adb5bd;
--bs-body-color-rgb: 173, 181, 189;
--bs-body-bg: #212529;
--bs-body-bg-rgb: 33, 37, 41;
--bs-emphasis-color: #fff;
--bs-emphasis-color-rgb: 255, 255, 255;
--bs-secondary-color: rgba(173, 181, 189, 0.75);
--bs-secondary-color-rgb: 173, 181, 189;
--bs-secondary-bg: #343a40;
--bs-secondary-bg-rgb: 52, 58, 64;
--bs-tertiary-color: rgba(173, 181, 189, 0.5);
--bs-tertiary-color-rgb: 173, 181, 189;
--bs-tertiary-bg: #2b3035;
--bs-tertiary-bg-rgb: 43, 48, 53;
--bs-primary-text-emphasis: #6ea8fe;
--bs-secondary-text-emphasis: #a7acb1;
--bs-success-text-emphasis: #75b798;
--bs-info-text-emphasis: #6edff6;
--bs-warning-text-emphasis: #ffda6a;
--bs-danger-text-emphasis: #ea868f;
--bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: #031633;
--bs-secondary-bg-subtle: #161719;
--bs-success-bg-subtle: #051b11;
--bs-info-bg-subtle: #032830;
--bs-warning-bg-subtle: #332701;
--bs-danger-bg-subtle: #2c0b0e;
--bs-light-bg-subtle: #343a40;
--bs-dark-bg-subtle: #1a1d20;
--bs-primary-border-subtle: #084298;
--bs-secondary-border-subtle: #41464b;
--bs-success-border-subtle: #0f5132;
--bs-info-border-subtle: #087990;
--bs-warning-border-subtle: #997404;
--bs-danger-border-subtle: #842029;
--bs-light-border-subtle: #495057;
--bs-dark-border-subtle: #343a40;
--bs-heading-color: inherit;
--bs-link-color: #6ea8fe;
--bs-link-hover-color: #8bb9fe;
--bs-link-color-rgb: 110, 168, 254;
--bs-link-hover-color-rgb: 139, 185, 254;
--bs-code-color: #e685b5;
--bs-border-color: #495057;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: #75b798;
--bs-form-valid-border-color: #75b798;
--bs-form-invalid-color: #ea868f;
--bs-form-invalid-border-color: #ea868f;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
border: 0;
border-top: var(--bs-border-width) solid;
opacity: 0.25;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
color: var(--bs-heading-color);
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-right: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-right: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.1875em;
background-color: var(--bs-highlight-bg);
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
text-decoration: underline;
}
a:hover {
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: var(--bs-code-color);
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.1875rem 0.375rem;
font-size: 0.875em;
color: var(--bs-body-bg);
background-color: var(--bs-body-color);
border-radius: 0.25rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: var(--bs-secondary-color);
text-align: right;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
display: none !important;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: right;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: right;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
outline-offset: -2px;
-webkit-appearance: textfield;
}
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
::file-selector-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */

+ 1
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-reboot.rtl.css.map
File diff suppressed because it is too large
View File


+ 6
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-reboot.rtl.min.css
File diff suppressed because it is too large
View File


+ 1
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-reboot.rtl.min.css.map
File diff suppressed because it is too large
View File


+ 5399
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-utilities.css
File diff suppressed because it is too large
View File


+ 1
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-utilities.css.map
File diff suppressed because it is too large
View File


+ 6
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-utilities.min.css
File diff suppressed because it is too large
View File


+ 1
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-utilities.min.css.map
File diff suppressed because it is too large
View File


+ 5390
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-utilities.rtl.css
File diff suppressed because it is too large
View File


+ 1
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-utilities.rtl.css.map
File diff suppressed because it is too large
View File


+ 6
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-utilities.rtl.min.css
File diff suppressed because it is too large
View File


+ 1
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap-utilities.rtl.min.css.map
File diff suppressed because it is too large
View File


+ 12071
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap.css
File diff suppressed because it is too large
View File


+ 1
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap.css.map
File diff suppressed because it is too large
View File


+ 6
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap.min.css
File diff suppressed because it is too large
View File


+ 1
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap.min.css.map
File diff suppressed because it is too large
View File


+ 12035
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap.rtl.css
File diff suppressed because it is too large
View File


+ 1
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap.rtl.css.map
File diff suppressed because it is too large
View File


+ 6
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap.rtl.min.css
File diff suppressed because it is too large
View File


+ 1
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/css/bootstrap.rtl.min.css.map
File diff suppressed because it is too large
View File


+ 6306
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/js/bootstrap.bundle.js
File diff suppressed because it is too large
View File


+ 1
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/js/bootstrap.bundle.js.map
File diff suppressed because it is too large
View File


+ 7
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/js/bootstrap.bundle.min.js
File diff suppressed because it is too large
View File


+ 1
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/js/bootstrap.bundle.min.js.map
File diff suppressed because it is too large
View File


+ 4439
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/js/bootstrap.esm.js
File diff suppressed because it is too large
View File


+ 1
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/js/bootstrap.esm.js.map
File diff suppressed because it is too large
View File


+ 7
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/js/bootstrap.esm.min.js
File diff suppressed because it is too large
View File


+ 1
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/js/bootstrap.esm.min.js.map
File diff suppressed because it is too large
View File


+ 4486
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/js/bootstrap.js
File diff suppressed because it is too large
View File


+ 1
- 0
RecetasPy/servicios/recetaspy/static/plugins/bootstrap/js/bootstrap.js.map
File diff suppressed because it is too large
View File


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save