Chubb script and removed Pipedrive's old templates.

This commit is contained in:
Norm Rasmussen
2025-07-15 14:12:28 -04:00
parent 4a93905830
commit 8b741ea223
11 changed files with 1118 additions and 1 deletions

View File

@ -0,0 +1,172 @@
<div class="avatar-text">
<h4 class="strong">
<span class="lang-en">Profile picture</span>
<span class="lang-de">Profilbild</span>
<span class="lang-es">Foto de perfil</span>
<span class="lang-fr">Photo de profil</span>
<span class="lang-br">Foto do perfil</span>
</h4>
<div>
<span class="lang-en">Photo helps personalize your account</span>
<span class="lang-de">Personalisieren Sie Ihr Konto mit einem Foto</span>
<span class="lang-es">La foto ayuda a personalizar su cuenta</span>
<span class="lang-fr">La photo permet de personnaliser votre compte</span>
<span class="lang-br">A foto ajuda a personalizar sua conta</span>
</div>
</div>
<img
alt="default avatar"
class="np-account-avatar-image"
src="https://s3.amazonaws.com/static.northpass.com/pipedrive/Avatar.png"
id="{{version}}_gravatar_img"
{% unless form.use_gravatar? %}style="display: none"{% endunless %}
/>
<img
alt="avatar"
class="np-account-avatar-image"
src="{% if form.secure_custom_avatar_url contains "https://secure.gravatar.com/avatar" %}https://s3.amazonaws.com/static.northpass.com/pipedrive/Avatar.png{% else %}{{ form.secure_custom_avatar_url }}{% endif %}"
id="{{version}}_custom_avatar_img"
{% if form.use_gravatar? %}style="display: none"{% endif %}
/>
<div class="np-account-avatar-choice">
<div class="np-form-field np-hidden">
<label class="radio radio-before np-input-label" for="{{version}}_learner_use_gravatar_true">
<span class="radio__input">
<input
id="{{version}}_learner_use_gravatar_true"
name="learner[use_gravatar]"
type="radio"
value="true"
{% if form.use_gravatar? %}checked{% endif %}
/>
<span class="np-button-color radio__control"></span>
</span>
<span class="radio__label"></span>
</label>
</div>
<div class="np-form-field np-hidden">
<label class="radio radio-before np-input-label" for="{{version}}_learner_use_gravatar_false">
<span class="radio__input">
<input
id="{{version}}_learner_use_gravatar_false"
name="learner[use_gravatar]"
type="radio"
value="false"
{% unless form.use_gravatar? %}checked{% endunless %}
/>
<span class="np-button-color radio__control"></span>
</span>
<span class="radio__label">
<span class="lang-en">Upload custom photo</span>
<span class="lang-de">Foto hochladen</span>
<span class="lang-es">Subir foto personalizada</span>
<span class="lang-fr">Téléverser une photo personnalisée</span>
<span class="lang-br">Carregar foto personalizada</span>
</span>
</label>
</div>
<button
id="{{version}}_upload_avatar"
type="button"
class="upload-avatar-button{% if form.use_gravatar? %} np-hidden{% endif %}"
>
<i class="far fa-paperclip"></i>
<span class="lang-en">Upload custom photo</span>
<span class="lang-de">Foto hochladen</span>
<span class="lang-es">Subir foto personalizada</span>
<span class="lang-fr">Téléverser une photo personnalisée</span>
<span class="lang-br">Carregar foto personalizada</span>
</button>
<div class="avatar-checkbox-wrapper" onclick="toggleGravatar()">
<div class="avatar-checkbox {% if form.use_gravatar? %} avatar-checkbox-selected {% endif %}" id="gravatar-checkbox">
<svg class="avatar-checkbox-mark" width="13" height="11" viewBox="0 0 13 11" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.7856 0.703847C11.2758 0.349665 11.9541 0.468775 12.3006 0.969886C12.6471 1.471 12.5305 2.16435 12.0403 2.51853C9.89294 4.07001 7.5045 6.58636 4.89298 10.0653C4.50422 10.5832 3.76456 10.6485 3.29465 10.2065L0.350947 7.43754C-0.0907947 7.02203 -0.119375 6.31912 0.287111 5.86757C0.693596 5.41601 1.38122 5.3868 1.82296 5.80231L3.89947 7.75555C6.35518 4.59965 8.64604 2.24967 10.7856 0.703847Z" fill="white"/>
</svg>
</div>
<span>
<span class="lang-en">Use default avatar</span>
<span class="lang-de">Standard-Avatar verwenden</span>
<span class="lang-es">Usar avatar predeterminado</span>
<span class="lang-fr">Utiliser l'avatar par défaut</span>
<span class="lang-br">Use o avatar padrão</span>
</span>
</div>
</div>
<style>
#desktop_custom_avatar_img {
border-radius: 50%;
border: 2px solid #E4E6E9;
}
.avatar-text > h4 {
margin-bottom: 20px;
}
.np-account-avatar-choice {
margin-left: 0;
}
.avatar-checkbox {
width: 20px;
height: 20px;
border: 1px solid var(--black-digital);
border-radius: 2px;
}
.avatar-checkbox-wrapper {
display: flex;
gap: 10px;
align-items: center;
cursor: pointer;
}
.avatar-checkbox.avatar-checkbox-selected {
border: none;
background: var(--green);
display: flex;
}
.avatar-checkbox-mark {
display: none;
margin: auto;
}
.avatar-checkbox.avatar-checkbox-selected .avatar-checkbox-mark {
display: block;
}
.upload-avatar-button {
border: none;
background: none;
color: #0070D6;
margin-bottom: 20px;
padding: 0;
}
.upload-avatar-button:hover {
color: #0055a3;
}
.upload-avatar-button > i {
rotate: -45deg;
}
#desktop_gravatar_img {
border: 2px solid #E4E6E9;
border-radius: 50%;
}
</style>
<script>
function toggleGravatar() {
let checkbox = document.querySelector('#gravatar-checkbox');
checkbox.classList.toggle('avatar-checkbox-selected');
document.querySelector('.upload-avatar-button').classList.toggle('np-hidden')
if (checkbox.classList.contains('avatar-checkbox-selected')) {
document.querySelector(('#desktop_learner_use_gravatar_true')).click()
} else {
document.querySelector(('#desktop_learner_use_gravatar_false')).click()
}
}
{% if current_person.avatar_url contains "https://secure.gravatar.com/avatar" and form.use_gravatar? == false %}
window.addEventListener("DOMContentLoaded", () => {
let a = document.querySelector('#gravatar-checkbox');
if (!a.classList.contains('avatar-checkbox-selected')) {
a.click()
}
})
{% endif %}
</script>

View File

@ -0,0 +1,160 @@
<div class="account-deletion">
<h4 class="strong">
<span class="lang-en">Delete your account</span>
<span class="lang-de">Ihr Konto löschen</span>
<span class="lang-es">Eliminar tu cuenta</span>
<span class="lang-fr">Supprimer votre compte</span>
<span class="lang-br">Exclua sua conta</span>
</h4>
<div class="account-deletion-description">
<span class="lang-en">Your account will be permanently deleted and you will no longer be able to access any data or information associated with this account. This action cannot be undone.</span>
<span class="lang-de">Ihr Account wird dauerhaft gelöscht und Sie haben keinen Zugriff mehr auf die mit diesem Konto verbundenen Daten und Informationen. Diese Aktion kann nicht rückgängig gemacht werden.</span>
<span class="lang-es">Tu cuenta será eliminada permanentemente y ya no podrás acceder a ningún dato o información asociada a esta cuenta. Esta acción no se puede deshacer.</span>
<span class="lang-fr">Votre compte sera définitivement supprimé et vous ne pourrez plus accéder aux données ou informations associées à ce compte. Cette action ne peut être annulée.</span>
<span class="lang-br">Sua conta será excluída permanentemente e você não poderá mais acessar quaisquer dados ou informações associados a ela. Esta ação não pode ser desfeita.</span>
</div>
<div class="button-1 button-large button-deletion" onclick="
document.querySelector('.account-deletion-popup-wrapper').classList.remove('np-hidden');
document.querySelector('.account-deletion-popup').classList.remove('np-hidden');"
>
<span class="lang-en">Delete my account</span>
<span class="lang-de">Meinen Account löschen</span>
<span class="lang-es">Eliminar mi cuenta</span>
<span class="lang-fr">Supprimer mon compte</span>
<span class="lang-br">Excluir minha conta</span>
</div>
</div>
<div class="account-deletion-popup-wrapper np-hidden" onclick="
document.querySelector('.account-deletion-popup-wrapper').classList.add('np-hidden');
document.querySelector('.account-deletion-popup').classList.add('np-hidden');"
>
</div>
<div class="account-deletion-popup np-hidden">
<div class="account-deletion-popup-confirmation">
<label class="account-deletion-confirmation-label" for="account-deletion-confirmation-input">
<span class="lang-en">To confirm account deletion, type <em>delete</em> in the field below.</span>
<span class="lang-de">Um die Löschung des Accounts zu bestätigen, geben Sie <em>löschen</em> in das Feld unten ein.</span>
<span class="lang-es">Para confirmar la eliminación de la cuenta, escribe <em>eliminar</em> en el siguiente campo.</span>
<span class="lang-fr">Pour confirmer la suppression de votre compte, tapez <em>supprimer</em> dans le champ ci-dessous.</span>
<span class="lang-br">Para confirmar a exclusão da conta, digite <em>excluir</em> no campo abaixo.</span>
</label>
<input id="account-deletion-confirmation-input" class="np-input" placeholder="delete" autocomplete="off">
<div id="confirm-deletion" class="button-1 button-medium button-deletion button-deletion-disabled" onclick="sendDeleteRequest();">
<span class="lang-en">Delete</span>
<span class="lang-de">löschen</span>
<span class="lang-es">Eliminar</span>
<span class="lang-fr">Supprimer</span>
<span class="lang-br">Excluir</span>
</div>
</div>
<h5 class="account-deletion-popup-goodbye np-hidden">
<span class="lang-en">Your account will be deleted shortly</span>
<span class="lang-de">Ihr Account wird in Kürze gelöscht</span>
<span class="lang-es">Tu cuenta será eliminada en breve</span>
<span class="lang-fr">Votre compte sera supprimé dans les plus brefs délais</span>
<span class="lang-br">Sua conta será excluída em breve</span>
</h5>
</div>
<style>
.account-deletion h4 {
margin-top: 80px;
margin-bottom: 20px;
}
.button-deletion {
width: fit-content;
background: #FFE7E6;
color: #C7201B;
margin-top: 20px;
}
.button-deletion:hover {
background: #FF5550;
color: #FFF;
}
.button-deletion-disabled, .button-deletion-disabled:hover {
background: #FFE7E6;
color: gray;
cursor: default;
}
.account-deletion-popup-wrapper {
width: 100%;
height: 100%;
position: fixed;
background: rgba(60, 60, 60, 0.5);
top: 0;
left: 0;
}
.account-deletion-popup {
position: absolute;
top: 50%;
left: 50%;
background: #FFF;
border-radius: 4px;
transform: translate(-50%, -50%);
}
.account-deletion-popup-confirmation {
display: flex;
flex-direction: column;
padding: 40px;
gap: 20px;
}
.account-deletion-popup-goodbye {
padding: 60px;
}
#account-deletion-confirmation-input::placeholder {
font-style: italic;
color: #999FA7;
opacity: 1;
}
@media only screen and (min-width: 500px) {
.account-deletion-popup-confirmation {
min-width: 450px;
}
}
@media only screen and (min-width: 1024px) {
.account-deletion h4 {
margin-top: 40px;
}
}
</style>
<script>
{% if current_school.properties.sandbox == false %}
const deletionInput = document.getElementById('account-deletion-confirmation-input');
deletionInput.addEventListener('input', () => {
const button = document.querySelector('#confirm-deletion');
if (deletionInput.value.toLowerCase() !== 'delete') {
button.classList.add('button-deletion-disabled');
} else {
button.classList.remove('button-deletion-disabled');
}
});
function sendDeleteRequest() {
document.querySelector('.account-deletion-popup-confirmation').classList.add('np-hidden');
document.querySelector('.account-deletion-popup-goodbye').classList.remove('np-hidden');
const personUUID = '{{ current_person.id }}';
const personEmail = '{{ current_person.email }}'
const personTime = '{{ current_person.created_at | replace_first: " ", "T" | replace_first: " +0000", ".000000+00:00" }}';
const xhr = new XMLHttpRequest();
{% if current_school.sso_active? %}
var url = 'https://webhooks.workato.com/webhooks/rest/bd1a1eb7-7e79-4208-a1db-8e9c7440bcc9/pipedrive-sso-delete-myself'
{% else %}
var url = 'https://webhooks.workato.com/webhooks/rest/bd1a1eb7-7e79-4208-a1db-8e9c7440bcc9/pipedrive-open-delete-myself'
{% endif %}
xhr.open('POST', url);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({
"personUUID": personUUID,
"personEmail": personEmail,
"personTime": personTime
}));
xhr.addEventListener('load', () => {
setTimeout(() => {
window.location.replace('/learners/sign_out');
}, 3000);
});
}
{% endif %}
</script>

View File

@ -0,0 +1,31 @@
<form class="np-form" action="{{ form.options.action }}" method="post" id="desktop_edit_learner" novalidate>
<input type="hidden" name="_method" value="{{ form.options.http_method }}">
{% form_authenticity_token %}
<div class="np-card">
<div class="container">
<h1 class="account-form-title">
<span class="lang-en">My profile</span>
<span class="lang-de">Mein Profil</span>
<span class="lang-es">Mi perfil</span>
<span class="lang-fr">Mon profil</span>
<span class="lang-br">Meu perfil</span>
</h1>
<div class="row">
<div class="col-xs-12 col-md-7 np-account-form">
{% render "account_form", form: form, version: "desktop" %}
<button type="submit" class="np-button np-button-big np-button-large-font np-form-action">
<span class="lang-en">Save profile</span>
<span class="lang-de">Profil speichern</span>
<span class="lang-es">Guardar perfil</span>
<span class="lang-fr">Sauvegarder le profil</span>
<span class="lang-br">Salvar perfil</span>
</button>
</div>
<div class="col-xs-12 col-md-5">
{% include "account_avatar", version: "desktop" %}
{% include "account_deletion" %}
</div>
</div>
</div>
</div>
</form>

View File

@ -0,0 +1,176 @@
<div class="np-form-field {% if form.errors contains 'email' %}np-account-form-field-error{% endif %}">
<label class="account-label" for="{{version}}_learner_email">
<span class="lang-en">Email</span>
<span class="lang-de">E-Mail</span>
<span class="lang-es">Correo electrónico</span>
<span class="lang-fr">E-mail</span>
<span class="lang-br">Email</span> *
</label>
<input
{% if form.options.invite? %} disabled {% endif %}
autofocus="autofocus"
class="np-input"
id="{{version}}_learner_email"
name="learner[email]"
type="email"
value="{{ form.email }}"
/>
</div>
<div class="np-form-field {% if form.errors contains 'first_name' %}np-account-form-field-error{% endif %}">
<label class="account-label" for="{{version}}_learner_first_name">
<span class="lang-en">First name</span>
<span class="lang-de">Vorname</span>
<span class="lang-es">Nombre de pila</span>
<span class="lang-fr">Prénom</span>
<span class="lang-br">Nome</span> *
</label>
<input
class="np-input"
id="{{version}}_learner_first_name"
name="learner[first_name]"
value="{{ form.first_name }}"
/>
</div>
<div class="np-form-field {% if form.errors contains 'last_name' %}np-account-form-field-error{% endif %}">
<label class="account-label" for="{{version}}_learner_last_name">
<span class="lang-en">Last name</span>
<span class="lang-de">Nachname</span>
<span class="lang-es">Apellidos</span>
<span class="lang-fr">Nom de famille</span>
<span class="lang-br">Sobrenome</span> *
</label>
<input
class="np-input"
id="{{version}}_learner_last_name"
name="learner[last_name]"
value="{{ form.last_name }}"
/>
</div>
<div class="np-form-field {% if form.errors contains 'display_name' %}np-account-form-field-error{% endif %}" style="display: none">
<label class="account-label" for="{{version}}_learner_display_name">
<span class="lang-en">Display name</span>
<span class="lang-de"></span>
<span class="lang-es"></span>
<span class="lang-fr"></span>
<span class="lang-br"></span>
</label>
<input
class="np-input"
id="{{version}}_learner_display_name"
name="learner[display_name]"
value="{{ form.display_name }}"
/>
</div>
{% unless form.options.invite? %}
<div class="np-form-field {% if form.errors contains 'current_password' %}np-account-form-field-error{% endif %}">
<label class="account-label" for="{{version}}_learner_current_password">
<span class="lang-en">Current password</span>
<span class="lang-de">Aktuelles Passwort</span>
<span class="lang-es">Contraseña actual</span>
<span class="lang-fr">Mot de passe actuel</span>
<span class="lang-br">Senha atual</span>
</label>
<input
class="np-input"
id="{{version}}_learner_current_password"
name="learner[current_password]"
type="password"
/>
</div>
<div class="np-form-field {% if form.errors contains 'password' %}np-account-form-field-error{% endif %}">
<label class="account-label" for="{{version}}_learner_password">
<span class="lang-en">New password</span>
<span class="lang-de">Neues Passwort</span>
<span class="lang-es">Nueva contraseña</span>
<span class="lang-fr">Nouveau mot de passe</span>
<span class="lang-br">Nova senha</span>
</label>
<input
class="np-input"
id="{{version}}_learner_password"
name="learner[password]"
type="password"
/>
</div>
<div class="np-form-field {% if form.errors contains 'password_confirmation' %}np-account-form-field-error{% endif %}">
<label class="account-label" for="{{version}}_learner_password_confirmation">
<span class="lang-en">Confirm new password</span>
<span class="lang-de">Passwort bestätigen</span>
<span class="lang-es">Confirmar nueva contraseña</span>
<span class="lang-fr">Confirmer le mot de passe</span>
<span class="lang-br">Confirmar nova senha</span>
</label>
<input
class="np-input"
id="{{version}}_learner_password_confirmation"
name="learner[password_confirmation]"
type="password"
/>
</div>
{% endunless %}
{% if form.options.invite? %}
<div class="np-form-field {% if form.errors contains 'password' %}np-account-form-field-error{% endif %}">
<label class="account-label" for="{{version}}_learner_password">
<span class="lang-en">Password</span>
<span class="lang-de">Passwort</span>
<span class="lang-es">Contraseña</span>
<span class="lang-fr">Mot de passe</span>
<span class="lang-br">Senha</span> *
</label>
<input
class="np-input"
id="{{version}}_learner_password"
name="learner[password]"
type="password"
/>
</div>
{% if form.terms_of_service_required? %}
<div class="np-form-field terms-of-service {% if form.errors contains 'terms_of_service_accepted' %}np-account-form-field-error{% endif %}">
<input
id="{{version}}_learner_terms_of_service"
name="learner[terms_of_service_accepted]"
type="checkbox"
/>
<div class="label">
<span class="lang-en">{% t .terms_of_service %}</span>
<span class="lang-de"></span>
<span class="lang-es"></span>
<span class="lang-fr"></span>
<span class="lang-br"></span>
</div>
</div>
{% else %}
<div class="np-margin-top">
<span class="np-form-terms">
<span class="lang-en">By submitting this form you agree to the </span>
<span class="lang-de">Mit dem Absenden dieses Formulars erklären Sie sich mit den </span>
<span class="lang-es">Al enviar este formulario acepta las </span>
<span class="lang-fr">En soumettant ce formulaire, vous acceptez les </span>
<span class="lang-br">Ao enviar este formulário, você concorda com os </span>
<a
class="np-form-link np-button-color"
target="_blank"
href={{ form.terms_of_service_url }}
>
<span class="lang-en">Terms of Use</span>
<span class="lang-de">Nutzungsbedingungen einverstanden</span>
<span class="lang-es">Condiciones de uso</span>
<span class="lang-fr">conditions d'utilisation.</span>
<span class="lang-br">Termos de Uso</span>
</a>
</span>
</div>
{% endif %}
<input
id="{{version}}_invite_token"
name="learner[token]"
value="{{ form.invite_token }}"
type="hidden"
/>
{% endif %}

View File

@ -0,0 +1,17 @@
<form class="np-form" action="{{ form.options.action }}" method="post" id="mobile_edit_learner" novalidate>
<input type="hidden" name="_method" value="{{ form.options.http_method }}">
{% form_authenticity_token %}
<div class="np-card np-account-form">
<div class="np-card-container np-card-padding">
{% render "account_form", form: form, version: "mobile" %}
</div>
</div>
<div class="np-card np-account-avatar">
<div class="np-card-container np-card-padding">
{% include "account_avatar", version: "mobile" %}
</div>
</div>
<button type="submit" class="np-button np-button-big np-button-large-font np-form-action">
{% t shared.account.save %}
</button>
</form>

View File

@ -0,0 +1,155 @@
<div class="green-banner-wrapper green-banner-wrapper-image">
<div class="green-banner width-limit">
<img class="green-banner-image" alt="banner image" src="https://s3.us-east-1.amazonaws.com/static.northpass.com/pipedrive/images/7.webp">
<div class="green-banner-content">
<h1 class="green-banner-title">
<span class="lang-en">Courses</span>
<span class="lang-de">Kurse</span>
<span class="lang-es">Cursos</span>
<span class="lang-fr">Cours</span>
<span class="lang-br">Cursos</span>
</h1>
<div class="green-banner-text">
<span class="lang-en">Welcome! We have saved your progress about courses</span>
<span class="lang-de">Willkommen! Wir haben Ihren Fortschritt zu den Kursen gespeichert</span>
<span class="lang-es">¡Bienvenido! Hemos guardado tu progreso en los cursos</span>
<span class="lang-fr">Bienvenue ! Nous avons enregistré votre progression concernant les cours</span>
<span class="lang-br">Bem-vindo! Salvamos o seu progresso nos cursos</span>
</div>
<div class="homepage-banner-stats">
{% assign in_progress = 0 %}
{% assign not_started = 0 %}
{% assign completed = 0 %}
{% for course in courses.in_catalog %}
{% if course.ribbon != 'VIDEO' %}
{% if course.completed? %}
{% assign completed = completed | plus: 1 %}
{% elsif course.started? == false %}
{% assign not_started = not_started | plus: 1 %}
{% else %}
{% assign in_progress = in_progress | plus: 1 %}
{% endif %}
{% endif %}
{% endfor %}
<div class="homepage-banner-stat">
<div class="stat-dot" style="color: #FFCC00;">
<i class="fas fa-circle"></i>
</div>
<div class="stat-number strong">
{{ in_progress }}
</div>
<div class="stat-text body-s">
<span class="lang-en">In progress</span>
<span class="lang-de">In Arbeit</span>
<span class="lang-es">En curso</span>
<span class="lang-fr">En cours</span>
<span class="lang-br">Em andamento</span>
</div>
</div>
<div class="homepage-banner-stat">
<div class="stat-dot" style="color: var(--green);">
<i class="fas fa-circle"></i>
</div>
<div class="stat-number strong">
{{ completed }}
</div>
<div class="stat-text body-s">
<span class="lang-en">Completed</span>
<span class="lang-de">Abgeschlossen</span>
<span class="lang-es">Completado</span>
<span class="lang-fr">Complété</span>
<span class="lang-br">Concluído</span>
</div>
</div>
</div>
</div>
</div>
</div>
<style>
.homepage-banner-image {
width: 100%;
}
.homepage-banner-stat {
background: #FFF;
margin-bottom: 10px;
padding: 12px 20px;
display: flex;
align-items: center;
border-radius: 4px;
width:100%;
}
.homepage-banner-stat > div {
text-align: center;
margin-right: 8px;
}
.stat-dot {
font-size: 8px;
}
.homepage-banner-stat .stat-number {
font-size: 18px;
line-height: 30px;
}
.homepage-banner-stat .stat-text {
font-size: 14px;
line-height: 25px;
}
@media only screen and (min-width: 768px) {
.homepage-banner .green-banner {
padding-bottom: 0;
overflow: clip;
}
.homepage-banner .green-banner-title {
word-break: break-word;
}
.homepage-banner .green-banner {
display: flex;
flex-direction: row-reverse;
justify-content: space-between;
}
.homepage-banner .green-banner-content {
padding-bottom: 40px;
align-self: center;
}
.homepage-banner-image {
height: 250px;
align-self: end;
object-fit: contain;
width: auto;
margin-right: -10%;
}
}
@media only screen and (min-width: 880px) {
.homepage-banner-image {
height: 300px;
}
}
@media only screen and (min-width: 1200px) {
.homepage-banner-image {
margin-right: -5%;
height: 350px;
}
.homepage-banner .green-banner-content {
flex: 1 1 0px;
width: 0;
}
.homepage-banner-stats {
display: flex;
gap: 20px;
}
.homepage-banner-stat {
margin-bottom: 0;
}
}
@media only screen and (min-width: 1400px) {
.homepage-banner-image {
margin-right: 0;
height: 100%;
}
}
</style>

View File

@ -0,0 +1,21 @@
<div class="green-banner-wrapper green-banner-wrapper-image">
<div class="green-banner width-limit">
<img class="green-banner-image" alt="banner image" src="https://s3.us-east-1.amazonaws.com/static.northpass.com/pipedrive/images/7.webp">
<div class="green-banner-content">
<h1 class="green-banner-title">
<span class="lang-en">Courses</span>
<span class="lang-de">Kurse</span>
<span class="lang-es">Cursos</span>
<span class="lang-fr">Cours</span>
<span class="lang-br">Cursos</span>
</h1>
<div class="green-banner-text">
<span class="lang-en">Take in-depth training courses to level up your CRM and sales skills. Earn certificates.</span>
<span class="lang-de">Absolvieren Sie umfassende Schulungskurse, um Ihre CRM- und Vertriebsfähigkeiten zu verbessern. Erhalten Sie Zertifikate.</span>
<span class="lang-es">Realiza cursos de formación en profundidad para mejorar tus habilidades en CRM y ventas. Obtén certificados.</span>
<span class="lang-fr">Suivez des formations approfondies pour améliorer vos compétences en CRM et en vente. Obtenez des certificats.</span>
<span class="lang-br">Faça cursos de treinamento aprofundados para aprimorar suas habilidades em CRM e vendas. Ganhe certificados.</span>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,227 @@
<div class="green-banner-wrapper green-banner-wrapper-image">
<div class="green-banner width-limit">
<img class="green-banner-image" alt="banner image" src="https://s3.us-east-1.amazonaws.com/static.northpass.com/pipedrive/images/1.webp">
<div class="green-banner-content">
<h1 class="green-banner-title">
<span class="lang-en">Hi</span>
<span class="lang-de">Hallo</span>
<span class="lang-es">Hola</span>
<span class="lang-fr">Salut</span>
<span class="lang-br">Oi</span>
{{current_person.first_name}}!
</h1>
<div class="green-banner-text">
<span class="lang-en">Find the best training courses, video tutorials and webinars to master your CRM and sales skills.</span>
<span class="lang-de">Finden Sie die besten Schulungskurse, Video-Tutorials und Webinare, um Ihre CRM- und Vertriebsfähigkeiten zu meistern.</span>
<span class="lang-es">Encuentra los mejores cursos de formación, tutoriales en vídeo y seminarios web para dominar tu CRM y tus habilidades de ventas.</span>
<span class="lang-fr">Trouvez les meilleures formations, vidéos tutoriels et webinaires pour maîtriser votre CRM et vos compétences commerciales.</span>
<span class="lang-br">Encontre os melhores cursos de treinamento, tutoriais em vídeo e webinars para dominar seu CRM e suas habilidades em vendas.</span>
</div>
<div class="green-banner-search">
<form action="{% route search %}" method="get" data-test="desktop-search" class="banner-search-form">
<input aria-label="{% t .search %}" class="banner-search-input" type="text" name="q" placeholder="Search Pipedrive Academy">
<i class="banner-search-icon fal fa-search" aria-hidden="true"></i>
<button type="button" class="clear-btn" aria-label="Clear input">
<img class="close-icon" src="https://s3.us-east-1.amazonaws.com/static.northpass.com/pipedrive/close.svg" alt="">
</button>
</form>
</div>
</div>
</div>
</div>
<style>
.banner-search-input:focus-visible {
outline: 2px solid #017737;
border-radius: 100px;
}
.banner-search-form {
max-width: 530px;
position: relative;
}
.banner-search-icon {
position: absolute;
right: 0;
top: 50%;
}
.banner-search-icon {
position: absolute;
left: 0;
top: 0;
height: 100%;
display: flex;
align-items: center;
padding-left: 17.5px;
pointer-events: none;
transition: opacity 0.2s ease;
}
.banner-search-input {
max-width: 530px;
width: 100%;
border-radius: 100px;
border: none;
height: 50px;
padding: 0 22px 0 44px;
}
.clear-btn {
position: absolute;
right: 20px;
top: 0;
height: 100%;
padding-left: 17.5px;
background: none;
border: none;
cursor: pointer;
display: none;
align-items: center;
justify-content: center;
color: #999;
}
.close-icon {
width: 100%;
}
.homepage-banner-image {
width: 100%;
}
.homepage-banner-stat {
background: #FFF;
margin-bottom: 10px;
padding: 12px 20px;
display: flex;
align-items: center;
border-radius: 4px;
width:100%;
}
.homepage-banner-stat > div {
text-align: center;
margin-right: 8px;
}
.stat-dot {
font-size: 8px;
}
.homepage-banner-stat .stat-number {
font-size: 18px;
line-height: 30px;
}
.homepage-banner-stat .stat-text {
font-size: 14px;
line-height: 25px;
}
.banner-search-form {
max-width: 530px;
}
@media only screen and (max-width: 768px) {
.banner-search-input, .banner-search-form {
max-width: 100%;
}
}
@media only screen and (min-width: 768px) {
.homepage-banner .green-banner {
padding-bottom: 0;
overflow: clip;
}
.homepage-banner .green-banner-title {
word-break: break-word;
}
.homepage-banner .green-banner {
display: flex;
flex-direction: row-reverse;
justify-content: space-between;
}
.homepage-banner .green-banner-content {
padding-bottom: 40px;
align-self: center;
}
.homepage-banner-image {
height: 250px;
align-self: end;
object-fit: contain;
width: auto;
margin-right: -10%;
}
}
@media only screen and (min-width: 880px) {
.homepage-banner-image {
height: 300px;
}
}
@media only screen and (min-width: 1200px) {
.homepage-banner-image {
margin-right: -5%;
height: 350px;
}
.homepage-banner .green-banner-content {
flex: 1 1 0px;
width: 0;
}
.homepage-banner-stats {
display: flex;
gap: 20px;
}
.homepage-banner-stat {
margin-bottom: 0;
}
}
@media only screen and (min-width: 1400px) {
.homepage-banner-image {
margin-right: 0;
height: 100%;
}
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
const searchParam = new URLSearchParams(window.location.search);
const searchQuery = searchParam.get('q');
const searchInput = document.querySelector('.banner-search-input');
if (searchParam.has('q')) {
const searchInput = document.querySelector('.banner-search-input');
if (searchInput) {
searchInput.value = searchParam.get('q');
}
}
if (searchInput) {
searchInput.addEventListener('focus', function() {
this.placeholder = '';
});
searchInput.addEventListener('blur', function() {
this.placeholder = 'Search Pipedrive Academy';
});
}
const input = document.querySelector('.banner-search-input');
const icon = document.querySelector('.banner-search-icon');
const clearBtn = document.querySelector('.clear-btn');
function updateState() {
const hasValue = input.value.trim().length > 0;
icon.style.display = hasValue ? 'none' : 'flex';
clearBtn.style.display = hasValue ? 'flex' : 'none';
if (hasValue) {
input.focus();
}
}
input.addEventListener('input', updateState);
clearBtn.addEventListener('click', () => {
input.value = '';
window.location.href = '/app';
input.focus();
updateState();
});
updateState();
});
</script>

View File

@ -0,0 +1,82 @@
{% assign activities_count = 0 %}
{% for section in course.sections %}
{% assign activities_count = activities_count | plus: section.activities.size %}
{% endfor %}
{% capture course_path %}{% route course, id: course.id %}{% endcapture %}
{% assign scaled_image_url = "" | append: course.image_url | replace: "resize=width:819,height:503", "resize=width:912,height:503" %}
<div class="course-card col-xs-12 col-sm-6 col-lg-4" language="{{course.properties.course_language}}" item-categories="{{ course.categories | map: 'id' | join: " " }}">
<a class="course-card-wrapper" href="{{ course_path }}">
{% if course.ribbon and course.ribbon.size > 0 %}
{% assign course_ribbon_uppercase = course.ribbon | upcase %}
<div class="course-card-ribbon body-xs {% if course_ribbon_uppercase == 'NEW' %}ribbon-blue{% endif %}">
{{ course.ribbon }}
</div>
{% endif %}
<img class="course-card-image" src="{{ scaled_image_url }}" alt="{{ course.name }}">
<div class="course-card-content">
<div class="course-card-info body-xs">
{{ activities_count }}
{% if activities_count == 1 %}
<span class="lang-en">lesson</span>
<span class="lang-de">Lektion</span>
<span class="lang-es">lección</span>
<span class="lang-fr">leçon</span>
<span class="lang-br">lição</span>
{% else %}
<span class="lang-en">lessons</span>
<span class="lang-de">Lektionen</span>
<span class="lang-es">lecciones</span>
<span class="lang-fr">leçons</span>
<span class="lang-br">lições</span>
{% endif %}
<span class="course-card-info-separator">|</span>
{% if course.properties.course_time != 'NULL' %}
{{ course.properties.course_time }}
{% endif %}
</div>
{% if course.started? %}
<div class="course-card-progress">
<div class="course-card-progress-info">
<span class="lang-en">Progress</span>
<span class="lang-de">Fortschritt</span>
<span class="lang-fr">Progression</span>
<span class="lang-es">Progreso</span>
<span class="lang-br">Progresso</span>
</div>
<div class="course-card-progress-bar">
<div class="course-card-progress-bar-fill" style="width: {{ course.progress }}%"></div>
</div>
<div class="course-card-progress-value body-s strong">
{{ course.progress }}%
</div>
</div>
{% endif %}
<h5 class="course-card-title">
{{ course.name }}
</h5>
<div class="course-card-description">
{{ course.short_description }}
</div>
<div class="course-card-footer">
<div class="course-card-button button-wrapper">
<div class="button-2 button-medium">
{% if course.started? %}
<span class="lang-en">Continue</span>
<span class="lang-de">Weiter</span>
<span class="lang-es">Continuar</span>
<span class="lang-fr">Continuer</span>
<span class="lang-br">Continuar</span>
{% else %}
<span class="lang-en">Take this course</span>
<span class="lang-de">Diesen Kurs belegen</span>
<span class="lang-es">Tomar este curso</span>
<span class="lang-fr">Suivre ce cours</span>
<span class="lang-br">Faça este curso</span>
{% endif %}
</div>
</div>
</div>
</div>
</a>
</div>

View File

@ -0,0 +1,76 @@
{% assign activities_count = 0 %}
{% for section in course.sections %}
{% assign activities_count = activities_count | plus: section.activities.size %}
{% endfor %}
{% capture course_path %}{% route course, id: course.id %}{% endcapture %}
{% assign scaled_image_url = "" | append: course.image_url | replace: "resize=width:819,height:503", "resize=width:912,height:503" %}
<div class="course-card col-xs-12 col-sm-6 col-lg-4" language="{{course.properties.course_language}}" item-categories="{{ course.categories | map: 'id' | join: " " }}">
<a class="course-card-wrapper" href="{{ course_path }}">
{% if course.ribbon and course.ribbon.size > 0 %}
{% assign course_ribbon_uppercase = course.ribbon | upcase %}
<div class="course-card-ribbon body-xs {% if course_ribbon_uppercase == 'NEW' %}ribbon-blue{% endif %}">
{{ course.ribbon }}
</div>
{% endif %}
<img class="course-card-image" src="{{ scaled_image_url }}" alt="{{ course.name }}">
<div class="course-card-content">
<div class="course-card-info body-xs">
{{ activities_count }}
{% if activities_count == 1 %}
<span class="lang-en">lesson</span>
<span class="lang-de">Lektion</span>
<span class="lang-es">lección</span>
<span class="lang-fr">leçon</span>
<span class="lang-br">lição</span>
{% else %}
<span class="lang-en">lessons</span>
<span class="lang-de">Lektionen</span>
<span class="lang-es">lecciones</span>
<span class="lang-fr">leçons</span>
<span class="lang-br">lições</span>
{% endif %}
<span class="course-card-info-separator">|</span>
{% if course.properties.course_time != 'NULL' %}
{{ course.properties.course_time }}
{% endif %}
</div>
{% if course.started? %}
<div class="course-card-progress">
<div class="course-card-progress-info">Progress</div>
<div class="course-card-progress-bar">
<div class="course-card-progress-bar-fill" style="width: {{ course.progress }}%"></div>
</div>
<div class="course-card-progress-value body-s strong">
{{ course.progress }}%
</div>
</div>
{% endif %}
<h5 class="course-card-title">
{{ course.name }}
</h5>
<div class="course-card-description">
{{ course.short_description }}
</div>
<div class="course-card-footer">
<div class="course-card-button button-wrapper">
<div class="button-2 button-medium">
{% if course.started? %}
<span class="lang-en">Continue</span>
<span class="lang-de">Weiter</span>
<span class="lang-es">Continuar</span>
<span class="lang-fr">Continuer</span>
<span class="lang-br">Continuar</span>
{% else %}
<span class="lang-en">Take this course</span>
<span class="lang-de">Diesen Kurs belegen</span>
<span class="lang-es">Tomar este curso</span>
<span class="lang-fr">Suivre ce cours</span>
<span class="lang-br">Faça este curso</span>
{% endif %}
</div>
</div>
</div>
</div>
</a>
</div>

View File

@ -11,7 +11,7 @@ HEADERS = {
"X-Api-Key": APIKEY,
}
BASEURL = "https://api.northpass.com/v2/"
IMPORTFILE = "/Users/normrasmussen/Downloads/cisa-063025.csv"
IMPORTFILE = "/Users/normrasmussen/Downloads/cisa071525.csv"
def bulk_invite_and_group():