Clear session now deletes all the templates. Added socketio disconnect function too. Need to remove special characters from filepath since glob can't recognize.
This commit is contained in:
Binary file not shown.
Binary file not shown.
@ -1,8 +1,13 @@
|
||||
import requests
|
||||
import shutil
|
||||
import itertools
|
||||
import re
|
||||
import os
|
||||
import csv
|
||||
import glob
|
||||
import pathlib
|
||||
from flask_socketio import SocketIO
|
||||
from datetime import datetime, timezone
|
||||
from .forms import TemplateForm
|
||||
from functools import wraps
|
||||
from flask import (
|
||||
@ -19,12 +24,15 @@ from werkzeug.utils import secure_filename
|
||||
from app import app, forms
|
||||
|
||||
# Upload folder
|
||||
UPLOAD_FOLDER = "/Users/normrasmussen/Documents/Projects/CSM_webapp/app/static/files"
|
||||
# UPLOAD_FOLDER = 'static/files'
|
||||
UPLOAD_FOLDER = "/Users/normrasmussen/Documents/Projects/CSM_webapp/app/static/files/csv"
|
||||
TEMPLATES_FOLDER = "/Users/normrasmussen/Documents/Projects/CSM_webapp/app/static/files/templates/"
|
||||
app.config["UPLOAD_FOLDER"] = UPLOAD_FOLDER
|
||||
app.config["TEMPLATES_FOLDER"] = TEMPLATES_FOLDER
|
||||
ALLOWED_EXTENSIONS = {"csv"}
|
||||
|
||||
# Global Variables
|
||||
socketio = SocketIO(app)
|
||||
specials = '"!@#$%^&[]*()-+?_=,<>/"'
|
||||
url = "https://api.northpass.com/"
|
||||
|
||||
|
||||
@ -72,7 +80,6 @@ def ask_key():
|
||||
Without this key, no other functions will work.
|
||||
It also assigns the api key to the session and clears the session upon each reload.
|
||||
"""
|
||||
specials = '"!@#$%^&*()-+?_=,<>/"'
|
||||
if request.method == "POST":
|
||||
session["key"] = request.form.get("apikey")
|
||||
if any(char in specials for char in session["key"]) or re.search(
|
||||
@ -104,6 +111,19 @@ def render_home():
|
||||
@app.route("/clear_session", methods=["GET", "POST"])
|
||||
def clear_session():
|
||||
if session.get("key"):
|
||||
if session.get("client_path"):
|
||||
client = session["client_path"]
|
||||
print(client)
|
||||
wildcard = glob.glob(client + '_*')
|
||||
print(wildcard)
|
||||
for directory in wildcard:
|
||||
print(directory)
|
||||
try:
|
||||
shutil.rmtree(directory)
|
||||
print(directory)
|
||||
except OSError:
|
||||
print(OSError)
|
||||
print("Error?")
|
||||
session.clear()
|
||||
error = "Session Cleared!"
|
||||
return render_template("index.html", error=error, title="Home, New session")
|
||||
@ -118,7 +138,6 @@ def table():
|
||||
@app.route("/upload_file", methods=["GET", "POST"])
|
||||
@key_required
|
||||
def upload_file():
|
||||
print("Uploading CSV")
|
||||
if request.method == "POST":
|
||||
if "file" not in request.files:
|
||||
flash("No file found or uploaded")
|
||||
@ -312,6 +331,8 @@ def load_templates():
|
||||
nextlink = data["links"]
|
||||
for response in data["data"]:
|
||||
last_updated = response["attributes"]["updated_at"].split("T")
|
||||
full_updated = response["attributes"]["updated_at"]
|
||||
g.full_updated = datetime.fromisoformat(full_updated)
|
||||
last_updated = last_updated[0]
|
||||
name, body, last_updated = (
|
||||
response["attributes"]["name"],
|
||||
@ -340,7 +361,6 @@ def templates():
|
||||
if request.form["submit-template"]:
|
||||
name = request.form.get("template_name")
|
||||
body = request.form.get("body")
|
||||
g.last_template = name
|
||||
if body == "":
|
||||
error = (
|
||||
"Ooph. Looks like you didn't load the changes before submitting."
|
||||
@ -355,15 +375,18 @@ def templates():
|
||||
}
|
||||
payload = {"custom_template": {"name": name, "body": body}}
|
||||
response = requests.post(url + endpoint, json=payload, headers=headers)
|
||||
return check_templates(response)
|
||||
return check_templates(response, name)
|
||||
return load_templates()
|
||||
|
||||
|
||||
def check_templates(response):
|
||||
print(response)
|
||||
def check_templates(response, name):
|
||||
response = str(response)
|
||||
if "201" in response:
|
||||
error = "Success! Templates Uploaded."
|
||||
error = (
|
||||
f"Success! The {name} template was successfully uploaded for "
|
||||
+ session["school"]
|
||||
+ "."
|
||||
)
|
||||
button = "Undo"
|
||||
return render_template(
|
||||
"templates.html", title="Templates Added", error=error, button=button
|
||||
@ -380,16 +403,25 @@ def check_templates(response):
|
||||
|
||||
|
||||
def save_templates_backup(templates):
|
||||
g.client_path = os.path.join(UPLOAD_FOLDER, session["school"])
|
||||
if os.path.exists(g.client_path):
|
||||
session["client_path"] = os.path.join(TEMPLATES_FOLDER, session["school"])
|
||||
if any(char in specials for char in session["client_path"]):
|
||||
for char in specials:
|
||||
session["sanitized_path"] = session["client_path"].replace(char,"")
|
||||
print(session["sanitized_path"])
|
||||
else:
|
||||
session["sanitized_path"] = session["client_path"]
|
||||
print(session["client_path"])
|
||||
today = datetime.now(timezone.utc)
|
||||
if os.path.exists(session["client_path"]):
|
||||
pass
|
||||
else:
|
||||
os.mkdir(g.client_path)
|
||||
path = session["client_path"] + "_" + str(today)
|
||||
os.mkdir(path)
|
||||
|
||||
for tupe in templates:
|
||||
file_name = tupe[0] + ".liquid"
|
||||
file_body = tupe[1]
|
||||
complete_path = os.path.join(g.client_path, file_name)
|
||||
complete_path = os.path.join(path, file_name)
|
||||
|
||||
with open(complete_path, "w+") as temp:
|
||||
temp.write(file_body)
|
||||
@ -399,12 +431,18 @@ def save_templates_backup(templates):
|
||||
@app.route("/undo_template", methods=["POST"])
|
||||
@key_required
|
||||
def undo_template():
|
||||
print(g.client_path)
|
||||
template_path = os.path.join(g.client_path, g.last_template)
|
||||
if request.method == "POST":
|
||||
if request.form["undo_templates"]:
|
||||
if os.path.exists(template_path):
|
||||
print(template_path)
|
||||
pass
|
||||
|
||||
@socketio.on("disconnect")
|
||||
def test_disconnect():
|
||||
print("Client disconnected")
|
||||
|
||||
|
||||
@socketio.on("connect")
|
||||
def test_connect():
|
||||
print("connection established")
|
||||
|
||||
|
||||
@app.route("/cmtest", methods=["GET", "POST"])
|
||||
|
||||
@ -1,49 +0,0 @@
|
||||
<a class="np-card" href="{% route course_enrollment, code: course.enrollment_code %}">
|
||||
<div class="np-card-container">
|
||||
{% if course.ribbon %}
|
||||
<div class="np-card-ribbon">
|
||||
{{ course.ribbon }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<video class='left-video' autoplay muted loop>
|
||||
<source src="{{course.promo_video_embed_url}}" type="video/mp4" alt="{{ course.name }}">
|
||||
</video>
|
||||
<div class="np-card-content-bottom">
|
||||
<h3 class="np-card-content-title np-color-white">
|
||||
{{ course.name }}
|
||||
</h3>
|
||||
<div class='np-card-content-description'>
|
||||
{{ course.full_description }}
|
||||
</div>
|
||||
|
||||
<div class="np-card-content-progress np-button-color">
|
||||
{% t shared.progress, count: course.progress %}
|
||||
</div>
|
||||
<div class="np-card-content-category">
|
||||
{{course.categories.first.name}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<style>
|
||||
.np-card {
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
}
|
||||
.np-card-content-category {
|
||||
border-top: 1px solid lightgray;
|
||||
padding: 10px;
|
||||
}
|
||||
.np-card-content-description {
|
||||
display: block;
|
||||
color: lightgray;
|
||||
}
|
||||
.np-card-content-bottom {
|
||||
padding: 15px;
|
||||
}
|
||||
.np-button-color {
|
||||
color: lightslategray;
|
||||
font-size: 15px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,44 +0,0 @@
|
||||
<div class="np-card np-no-horizontal-padding">
|
||||
<div class="np-card-container">
|
||||
<div class="np-learning-path np-featured-course">
|
||||
<div class="np-featured-course-img-container" style="overflow: hidden">
|
||||
<video class='featured-video' autoplay muted loop style="margin-left: -60px;">
|
||||
<source id="featured_video" src="{{course.promo_video_embed_url}}" type="video/mp4" alt="{{ course.name }}" />
|
||||
</video>
|
||||
<div class="np-card-image-content-top">
|
||||
</div>
|
||||
</div>
|
||||
<div class="np-card-text-wrapper">
|
||||
<div class="np-card-content np-card-padding np-card-content-vertical">
|
||||
<h3 class="np-card-content-title">
|
||||
{{ course.name }}
|
||||
</h3>
|
||||
<div class="np-card-content-description">
|
||||
{{ course.full_description }}
|
||||
</div>
|
||||
|
||||
<div class="np-card-content-footer" style='display: flex; flex-direction: row; justify-content: space-between;'>
|
||||
<a
|
||||
class="np-top-button np-button-font-color np-button" href="{% route course_enrollment, code: course.enrollment_code %}"
|
||||
>
|
||||
{% if course.enrolled? == false %}
|
||||
{% t shared.enroll %}
|
||||
{% elsif course.started? == false %}
|
||||
{% t shared.start, key: current_school.course_vocabulary %}
|
||||
{% elsif course.completed? %}
|
||||
{% t shared.course.view, key: current_school.course_vocabulary %}
|
||||
{% else %}
|
||||
{% t shared.continue %}
|
||||
{% endif %}
|
||||
</a>
|
||||
<div class="np-card-image-content-bottom" style="position: unset;">
|
||||
<div class="np-card-content-progress np-button-color">
|
||||
{% t shared.progress, count: course.progress %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,80 +0,0 @@
|
||||
<footer class="np-footer">
|
||||
<div class="np-footer-top">
|
||||
{% if website_footer.show_navigation_links? %}
|
||||
<div class="np-footer-navigation">
|
||||
<ul class="np-footer-navigation-list">
|
||||
{% for website_navigation in navigations.footer_navigations %}
|
||||
{% if website_navigation.external? %}
|
||||
<li class="np-footer-navigation-item">
|
||||
<a
|
||||
class="np-footer-navigation-link np-button-color"
|
||||
href="{{ website_navigation.path }}"
|
||||
{% if website_navigation.external? %} target="_blank" {% endif %}
|
||||
>
|
||||
{{ website_navigation.name }}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if current_school.logo_url %}
|
||||
<h2 class="np-footer-logo">
|
||||
<a href="{% route home %}">
|
||||
<img
|
||||
alt="{{ current_school.name }}"
|
||||
class="np-footer-logo-image"
|
||||
src="{{ current_school.logo_url }}"
|
||||
/>
|
||||
</a>
|
||||
</h2>
|
||||
{% else %}
|
||||
<div class="np-school-name np-header-font-color">
|
||||
{{ current_school.name }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="np-footer-bottom">
|
||||
<nav class="np-footer-social-links">
|
||||
{% if website_footer.show_social_media_links? %}
|
||||
<ul class="np-footer-social-links-list">
|
||||
{% for social_media_link in website_footer.social_media_links %}
|
||||
<li class="np-footer-social-links-item">
|
||||
<a
|
||||
class="np-footer-social-links-link np-button-color"
|
||||
href="{{ social_media_link.link }}"
|
||||
target="_blank" title="{{ social_media_link.name }}"
|
||||
>
|
||||
<i class="np-footer-social-links-icon
|
||||
np-button-color
|
||||
fab fa-{{ social_media_link.name }}"
|
||||
></i>
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</nav>
|
||||
|
||||
{% if website_footer.show_customer_service_email? and
|
||||
website_footer.school_customer_service_email
|
||||
%}
|
||||
<div class="np-footer-support">
|
||||
<div class="np-footer-support-item np-footer-support-help np-fc-white np-opacity-50">
|
||||
{% t .need_help %}
|
||||
</div>
|
||||
<div class="np-footer-support-item np-footer-support-email np-fc-white np-opacity-50">
|
||||
{% t .email %}
|
||||
</div>
|
||||
<a
|
||||
class="np-footer-support-item np-footer-support-link np-button-color"
|
||||
href="mailto:{{ website_footer.school_customer_service_email }}"
|
||||
>
|
||||
support@menlosecurity.com
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</footer>
|
||||
@ -1,11 +0,0 @@
|
||||
{% styles default %}
|
||||
{% styles colors %}
|
||||
{% styles custom %}
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Raleway:wght@200;300;400;500&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.css" integrity="sha512-wR4oNhLBHf7smjy0K4oqzdWumd+r5/+6QO/vDda76MW5iug4PT7v86FoEkySIJft3XA0Ae6axhIvHrqwm793Nw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.min.js" type="text/javascript"></script>
|
||||
@ -1,183 +0,0 @@
|
||||
<header class="np-header np-header-color" >
|
||||
<div class="np-header-content">
|
||||
<div class="np-hidden-desktop np-header-mobile-menu-nav">
|
||||
{% if current_person.signed_in? %}
|
||||
<button
|
||||
data-toggle-class="np-hidden"
|
||||
class="np-header-mobile-menu-nav-button fal fa-times np-hidden np-header-font-color"
|
||||
data-toggle-target=".np-header-mobile-avatar-menu,
|
||||
.np-header-mobile-menu-content, .np-main, .np-footer"
|
||||
></button>
|
||||
<button
|
||||
data-test="open-mobile-menu"
|
||||
data-toggle-class="np-hidden"
|
||||
class="np-header-mobile-menu-nav-button np-header-mobile-avatar-menu"
|
||||
data-toggle-target=".fa-times, .np-header-mobile-menu-content, .np-main, .np-footer"
|
||||
>
|
||||
<img
|
||||
alt="{{ current_person.name }}"
|
||||
class="np-header-avatar-image"
|
||||
src="{{ current_person.avatar_url }}"
|
||||
/>
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if current_school.logo_url %}
|
||||
<h1 class="np-header-logo">
|
||||
<a href="{% route home %}">
|
||||
<img
|
||||
alt="{{ current_school.name }}"
|
||||
class="np-header-logo-image"
|
||||
src="{{ current_school.logo_url }}"
|
||||
/>
|
||||
</a>
|
||||
</h1>
|
||||
{% else %}
|
||||
<a href="{% route home %}" class="np-school-name np-header-font-color">
|
||||
{{ current_school.name }}
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
<div class="np-hidden-mobile np-header-desktop-nav">
|
||||
<ul class="np-header-desktop-nav-list">
|
||||
{% for website_navigation in navigations.header_navigations_external %}
|
||||
<li class= "np-header-desktop-nav-item">
|
||||
<a
|
||||
href="{{ website_navigation.path }}"
|
||||
class="np-header-desktop-nav-link np-header-font-color"
|
||||
target="_blank"
|
||||
>
|
||||
{{ website_navigation.name }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{% if current_person.signed_in? %}
|
||||
<div class="np-hidden-mobile np-header-search np-header-search-expanded">
|
||||
<form action="{% route search %}" method="get" data-test="desktop-search">
|
||||
<input
|
||||
aria-label="{% t .search %}"
|
||||
class="np-header-search-input np-header-font-background-color"
|
||||
type="text"
|
||||
name="q"
|
||||
placeholder="{% t .search %}"
|
||||
/>
|
||||
<i class="np-header-search-icon far fa-search"></i>
|
||||
</form>
|
||||
</div>
|
||||
<div class="np-hidden-mobile np-header-avatar">
|
||||
<button
|
||||
class="np-header-avatar-button"
|
||||
data-test="open-desktop-menu"
|
||||
data-toggle-class-on-target="np-hidden"
|
||||
data-toggle-target=".np-header-avatar-tooltip"
|
||||
data-toggle-outside
|
||||
>
|
||||
<img
|
||||
alt="{{ current_person.name }}"
|
||||
class="np-header-avatar-image"
|
||||
src="{{ current_person.avatar_url }}"
|
||||
>
|
||||
</button>
|
||||
<div class="np-header-avatar-tooltip np-hidden" role="tooltip">
|
||||
<span class="np-header-avatar-tooltip-arrow-up"></span>
|
||||
<div class="np-header-avatar-tooltip-learner">
|
||||
<div class="np-header-avatar-tooltip-learner-name">
|
||||
{{ current_person.name }}
|
||||
</div>
|
||||
<div class="np-header-avatar-tooltip-learner-email">
|
||||
{{ current_person.email }}
|
||||
</div>
|
||||
</div>
|
||||
<nav class="np-header-avatar-tooltip-navigation">
|
||||
<a class="np-header-avatar-tooltip-navigation-link" onclick="buildURL(window.location.pathname)" style="cursor:pointer">
|
||||
Default
|
||||
</a>
|
||||
{% unless current_school.sso_active? %}
|
||||
<a
|
||||
class="np-header-avatar-tooltip-navigation-link"
|
||||
href="{% route account %}"
|
||||
>
|
||||
{% t .profile_settings %}
|
||||
</a>
|
||||
{% endunless %}
|
||||
<a
|
||||
class="np-header-avatar-tooltip-navigation-link np-danger"
|
||||
href="{% route logout %}"
|
||||
>
|
||||
{% t .sign_out %}
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<a
|
||||
class="np-header-sign-in np-header-desktop-nav-link np-header-font-color"
|
||||
href="{% route login %}"
|
||||
>
|
||||
{% t shared.sign_in %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="np-hidden-desktop">
|
||||
<div class="np-header-mobile-menu-content np-hidden">
|
||||
{% if current_person.signed_in? %}
|
||||
<img
|
||||
alt="{{ current_person.name }}"
|
||||
class="np-header-mobile-menu-content-avatar"
|
||||
src="{{ current_person.avatar_url }}"
|
||||
/>
|
||||
<div class="np-header-mobile-menu-content-name">
|
||||
{{ current_person.name }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="np-header-mobile-menu-content-nav">
|
||||
<form
|
||||
class="np-header-search"
|
||||
data-test="mobile-search"
|
||||
method="get"
|
||||
action="{% route search %}"
|
||||
>
|
||||
<input
|
||||
aria-label="{% t .search %}"
|
||||
class="np-header-search-input"
|
||||
type="text"
|
||||
name="q"
|
||||
placeholder="{% t .search %}"
|
||||
/>
|
||||
<i class="np-header-search-icon far fa-search"></i>
|
||||
</form>
|
||||
{% for website_navigation in navigations.header_navigations %}
|
||||
<a
|
||||
href="{{ website_navigation.path }}"
|
||||
class="np-header-mobile-menu-content-button"
|
||||
{% if website_navigation.external? %} target="_blank" {% endif %}
|
||||
>
|
||||
{{ website_navigation.name }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
<div class="np-header-mobile-menu-content-line"></div>
|
||||
{% unless current_school.sso_active? %}
|
||||
<a
|
||||
class="np-header-mobile-menu-content-button"
|
||||
href="{% route account %}"
|
||||
>
|
||||
{% t .profile_settings %}
|
||||
</a>
|
||||
{% endunless %}
|
||||
<a
|
||||
class="np-header-mobile-menu-content-button np-danger"
|
||||
href="{% route logout %}"
|
||||
>
|
||||
{% t .sign_out %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include "messages" %}
|
||||
|
||||
@ -1,109 +0,0 @@
|
||||
<div class="np-homepage-featured np-faq np-max-width">
|
||||
<div class="np-homepage-featured-text">
|
||||
<div class="np-homepage-headline">
|
||||
Frequently Asked Questions
|
||||
</div>
|
||||
</div>
|
||||
<div class="row np-faqs">
|
||||
<div class="col-md-6">
|
||||
<div class="np-accordion">
|
||||
<div class="accordion-btn">
|
||||
<i class="fal fa-plus"></i>
|
||||
<div class="accordion-title"><strong>Q:</strong> I'm not in shape. Can I still go to a climbing gym?</div>
|
||||
</div>
|
||||
<div class="accordion-panel">
|
||||
<div class="accordion-panel-content">
|
||||
<p><strong>A:</strong> Absolutely. Climbing is a wonderful full-body and full-mind workout. If you're looking to get in shapre but tired of pumping iron, climbing is a fantastic option.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="np-accordion">
|
||||
<div class="accordion-btn">
|
||||
<i class="fal fa-plus"></i>
|
||||
<div class="accordion-title"><strong>Q:</strong> I'm scared of heights. Should I try climbing?</div>
|
||||
</div>
|
||||
<div class="accordion-panel">
|
||||
<div class="accordion-panel-content">
|
||||
<p><strong>A:</strong> Many climbers have a fear of heights! However, it goes away when you use your own strength and technique to get to the top of a wall. Start small by climbing in a gym first.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="np-accordion">
|
||||
<div class="accordion-btn">
|
||||
<i class="fal fa-plus"></i>
|
||||
<div class="accordion-title"><strong>Q:</strong> Should I hire someone to belay me at a gym?</div>
|
||||
</div>
|
||||
<div class="accordion-panel">
|
||||
<div class="accordion-panel-content">
|
||||
<p><strong>A:</strong> You absolutely can as a quick introduction. However, what would be even better is to grab a friend and take a belay class at your local gym.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="np-accordion">
|
||||
<div class="accordion-btn">
|
||||
<i class="fal fa-plus"></i>
|
||||
<div class="accordion-title"><strong>Q:</strong> What is bouldering?</div>
|
||||
</div>
|
||||
<div class="accordion-panel">
|
||||
<div class="accordion-panel-content">
|
||||
<p><strong>A:</strong> Great question! Bouldering is a form of climbing, done on shorter walls. You use a crash pad under your climb to cushion your fall. Be warned, bouldering is much more powerful and has a steeper learning curve.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="np-accordion">
|
||||
<div class="accordion-btn">
|
||||
<i class="fal fa-plus"></i>
|
||||
<div class="accordion-title"><strong>Q:</strong> What are those people with all that gear hanging from their harness doing?</div>
|
||||
</div>
|
||||
<div class="accordion-panel">
|
||||
<div class="accordion-panel-content">
|
||||
<p><strong>A:</strong> Chances are you saw a trad climber! Short for traditional climbing, that gear serves as removable protection. When the climbing pair is done with the climb, nothing is left on the rock.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="np-accordion">
|
||||
<div class="accordion-btn">
|
||||
<i class="fal fa-plus"></i>
|
||||
<div class="accordion-title"><strong>Q:</strong> None of my friends are interested in climbing. How can I find partners?</div>
|
||||
</div>
|
||||
<div class="accordion-panel">
|
||||
<div class="accordion-panel-content">
|
||||
<p><strong>A:</strong>The best way to meet people is to join a gym a start climbing! Climbers are social and you'll start meeting people. You can also use online resources like Mountain Project's Partner Finder.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
/
|
||||
<style>
|
||||
.fa-plus {
|
||||
background-image: unset;
|
||||
background: #0297FA;
|
||||
}
|
||||
.fa-minus {
|
||||
background-image: unset;
|
||||
background: #0297FA; }
|
||||
</style>
|
||||
|
||||
<script>
|
||||
let accordions = document.getElementsByClassName("accordion-btn");
|
||||
|
||||
for (let i = 0; i < accordions.length; i++) {
|
||||
accordions[i].addEventListener("click", function() {
|
||||
this.querySelector('.fal').classList.toggle("fa-plus");
|
||||
this.querySelector('.fal').classList.toggle("fa-minus");
|
||||
|
||||
let panel = this.nextElementSibling;
|
||||
panel.classList.toggle("panel-open");
|
||||
if (panel.style.maxHeight) {
|
||||
panel.style.maxHeight = null;
|
||||
} else {
|
||||
panel.style.maxHeight = panel.scrollHeight + "px";
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
@ -1,91 +0,0 @@
|
||||
<div class="np-homepage-featured np-homepage-featured-items np-max-width">
|
||||
<div class="np-homepage-featured-text">
|
||||
<div class="np-homepage-headline">
|
||||
Recommended Gear
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="featured-photography-carousel np-carousel np-carousel-bg-blue" id="featured-photography-carousel">
|
||||
<div class="np-carousel-card">
|
||||
<div>
|
||||
<img src=https://5prq858zcb-flywheel.netdna-ssl.com/wp-content/uploads/2016/12/50823_4WhiteBG-1-600x625.png" alt="Featured Photography" class='customer-carousel-image'/>
|
||||
<div class="slide-label">Misty Mountain Cadillav Harness</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="np-carousel-card">
|
||||
<div>
|
||||
<img src="https://outdoorgearlab-mvnab3pwrvp3t0.stackpathdns.com/photos/18/97/311203_1848_XXXL.jpg" alt="Featured Photography" class='customer-carousel-image'/>
|
||||
<div class="slide-label">Gri-Gri Belay Device</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="np-carousel-card">
|
||||
<div>
|
||||
<img src="https://lcdn.sportiva.com/pub/media/catalog/product/8/0/800_yellow_katanalace_1_7_4.jpg" alt="Featured Photography" class='customer-carousel-image'/>
|
||||
<div class="slide-label">La Sportiva Katana Lace Shoes</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="np-carousel-card">
|
||||
<div>
|
||||
<img src="https://s3.amazonaws.com/static.northpass.com/demos/hsbc-old-logo.png" alt="Featured Photography" class='customer-carousel-image'/>
|
||||
<div class="slide-label">Metolious Helmet</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="np-carousel-card">
|
||||
<div>
|
||||
<img src="https://s3.amazonaws.com/static.northpass.com/demos/sandia-labs-logo.jpg" alt="Featured Photography" class='customer-carousel-image'/>
|
||||
<div class="slide-label">Unknown</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
|
||||
$("#featured-photography-carousel").slick({
|
||||
slidesToShow: 3.5,
|
||||
prevArrow: '<i class="fal fa-chevron-left"></i>',
|
||||
nextArrow: '<i class="fal fa-chevron-right"></i>',
|
||||
infinite: false,
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 1350,
|
||||
settings: {
|
||||
slidesToShow: 2.3,
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 1024,
|
||||
settings: {
|
||||
slidesToShow: 2,
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 768,
|
||||
settings: {
|
||||
slidesToShow: 1,
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.featured-photography-carousel .fa-chevron-right::before {
|
||||
right: -6px !important;
|
||||
}
|
||||
.customer-carousel-image {
|
||||
width: 292px;
|
||||
height: 292px;
|
||||
object-fit: contain;
|
||||
}
|
||||
.featured-photography-carousel .slick-initialized .slick-slide {
|
||||
margin: 10px 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,39 +0,0 @@
|
||||
{% include "header" %}
|
||||
{% include "course_version_outdated_alert", courses: courses.in_catalog %}
|
||||
<div class="np-homepage-hero">
|
||||
<div class="np-homepage-hero-image">
|
||||
</div>
|
||||
<div class="np-homepage-hero-content">
|
||||
<div class="np-homepage-headline np-header-font-color">
|
||||
Menlo Security Resrouces
|
||||
</div>
|
||||
<div class="np-homepage-subheadline np-header-font-color">
|
||||
Resources to help you make the most of your Security Training
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include "sub_navigation" %}
|
||||
{% include "courses_catalog" %}
|
||||
</main>
|
||||
{% include "footer" %}
|
||||
|
||||
<style>
|
||||
.np-card-content-description {
|
||||
height: 100px;
|
||||
}
|
||||
.np-card-content-title {
|
||||
height: 58px;
|
||||
overflow: clip;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<script>
|
||||
window.onload = function() {
|
||||
[].slice.call(document.getElementsByClassName("np-card-content-description")).forEach(function(element) {
|
||||
if(element.innerText.length > 150){
|
||||
element.innerText = element.innerText.slice(0,150) + '...'
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
@ -1,33 +0,0 @@
|
||||
{% include 'header' %}
|
||||
<main class="np-main np-homepage">
|
||||
<div class="np-homepage-hero">
|
||||
<h1 class="community-headline">Explore</h1>
|
||||
</div>
|
||||
{% include 'sub_navigation' %}
|
||||
<div class='discussion-container' style="border: 18px solid rgb(0, 0, 0); overflow: hidden; margin-left: 100px; margin-top: 35px; width: 1065px;">
|
||||
<iframe scrolling="yes" src="https://www.mountainproject.com/" style="border: 0px none; margin-left: 15px auto; height: 1954px; margin-top: -100px; width: 1060px;"></iframe>
|
||||
</div>
|
||||
</main>
|
||||
{% include 'footer' %}
|
||||
|
||||
<style>
|
||||
.discussion-frame {
|
||||
min-width: 100%;
|
||||
margin-left: -10px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.discussion-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.community-headline {
|
||||
font-size: 32px;
|
||||
line-height: 48px;
|
||||
font-family: "Raleway", "Helvetic", "Arial" sans-serif;
|
||||
color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user