Commit 2f031c25 authored by Douwe Maan's avatar Douwe Maan

Merge branch '2501-trial-and-license-ee-frontend' into...

Merge branch '2501-trial-and-license-ee-frontend' into '2501-trial-and-license-purchases-inside-gitlab-ee'

Frontend for trial and license purchases inside GitLab EE

See merge request !2301
parents 6562dfb8 3cb2c12b
import Cookies from 'js-cookie';
export default class EETrialBanner {
constructor($trialBanner) {
this.COOKIE_KEY = 'show_ee_trial_banner';
this.$trialBanner = $trialBanner;
this.$mainNavbar = this.$trialBanner.siblings('.js-navbar-gitlab');
this.$secondaryNavbar = this.$mainNavbar.siblings('.js-page-with-sidebar');
this.licenseExpiresOn = new Date(this.$trialBanner.data('license-expiry'));
}
init() {
// Wait for navbars to render before querying
this.setCookies();
this.$trialBanner.on('close.bs.alert', e => this.handleTrialBannerDismiss(e));
}
/**
* Trial Expiring/Expired Banner has two stages;
* 1. Show banner when user enters last 7 days of trial
* 2. Show banner again when last 7 days are over and license has expired
*
* Stage 1:
* Banner is showed when `trial_license_message` is sent by backend
* for the first time (in `app/views/layouts/header/_default.html.haml`).
* Here, we perform following steps;
*
* 1. Set cookie `show_ee_trial_banner` with expiry same as license
* 2. Set cookie value to `true`
* 3. Show banner using `toggleBanner(true)`
*
* At this stage, if user dismisses banner, we set cookie value to `false`
* and everytime page is initialized, we check for cookie existence as
* well as its value, and decide show/hide status of banner
*
* Stage 2:
* At this point, Cookie we had set earlier will be expired and
* backend will now send updated message in `trial_license_message`.
* Here, we perform following steps;
*
* 1. Check if cookie is defined (it'll not be defined as it is expired now)
* 2. If cookie is gone, we re-set `show_ee_trial_banner` cookie but with
* expiry of 20 years
* 3. Set cookie value to `true`
* 4. Show banner using `toggleBanner(true)`, which now has updated message
*
* At this stage, if user dismisses banner, we set cookie value to `false`
* and our existing logic of show/hide banner based on cookie value continues
* to work. And since, cookie is set to expire after 20 years, user won't be
* seeing banner again.
*/
setCookies() {
const today = new Date();
// Check if Cookie is defined
if (!Cookies.get(this.COOKIE_KEY)) {
// Cookie was not defined, let's define with default value
// Check if License is yet to expire
if (today < this.licenseExpiresOn) {
// License has not expired yet, we show initial banner of 7 days
// with cookie set to validity same as license expiry
Cookies.set(this.COOKIE_KEY, 'true', { expires: this.licenseExpiresOn });
} else {
// License is already expired so we show final Banner with cookie set to 20 years validity.
Cookies.set(this.COOKIE_KEY, 'true', { expires: 7300 });
}
this.toggleBanner(true);
} else {
// Cookie was defined, let's read value and show/hide banner
this.toggleBanner(Cookies.get(this.COOKIE_KEY) === 'true');
}
}
toggleMainNavbarMargin(state) {
if (this.$mainNavbar.length) {
this.$mainNavbar.toggleClass('has-trial-banner', state);
}
}
toggleSecondaryNavbarMargin(state) {
if (this.$secondaryNavbar.length) {
this.$secondaryNavbar.toggleClass('has-trial-banner', state);
}
}
toggleBanner(state) {
this.$trialBanner.toggleClass('hidden', !state);
this.toggleMainNavbarMargin(state);
this.toggleSecondaryNavbarMargin(state);
}
handleTrialBannerDismiss() {
this.toggleMainNavbarMargin(false);
this.toggleSecondaryNavbarMargin(false);
if (Cookies.get(this.COOKIE_KEY)) {
Cookies.set(this.COOKIE_KEY, 'false');
}
}
}
import EETrialBanner from './ee_trial_banner';
$(() => {
const $trialBanner = $('.js-gitlab-ee-trial-banner');
if ($trialBanner.length) {
const eeTrialBanner = new EETrialBanner($trialBanner);
eeTrialBanner.init();
}
});
......@@ -168,6 +168,7 @@ import './zen_mode';
import './admin_email_select';
import './application_settings';
import './approvals';
import './ee_trial_banner';
import './ldap_groups_select';
import './path_locks';
import './weight_select';
......
.blank-state-parent-container {
display: flex;
.section-container {
display: flex;
flex: 1;
padding: 10px;
}
.section-body {
width: 100%;
height: 100%;
border: 1px solid $border-color;
border-radius: $border-radius-default;
&.section-ee-trial {
display: flex;
align-items: center;
justify-content: center;
}
}
}
.blank-state-welcome {
text-align: center;
border-bottom: 1px solid $border-color;
.blank-state-text {
margin-bottom: 0;
......@@ -10,6 +32,10 @@
.blank-state {
padding-top: 20px;
padding-bottom: 20px;
}
.blank-state.ee-trial {
padding: 20px;
text-align: center;
}
......@@ -20,20 +46,32 @@
.blank-state-icon {
padding-bottom: 20px;
color: $gray-darkest;
font-size: 56px;
path,
polygon {
fill: currentColor;
svg {
display: block;
margin: auto;
}
}
.section-admin-welcome {
/**
* This is slight increase over 25% of col-md-offset-3 for
* admin welcome page
*/
.blank-state-icon.col-md-offset-3 {
margin-left: 30%;
@media (max-width: $screen-md-min) {
margin-left: auto;
}
}
}
.blank-state-title {
margin-top: 0;
margin-bottom: 5px;
margin-bottom: 10px;
font-size: 18px;
font-weight: normal;
}
.blank-state-text {
......@@ -49,3 +87,24 @@
.blank-state-welcome-title {
font-size: 24px;
}
@media (max-width: $screen-md-min) {
.blank-state-parent-container {
&,
.section-container {
display: block;
}
}
.blank-state {
text-align: center;
}
.blank-state-icon {
padding-bottom: 0;
}
.blank-state-body {
margin-top: 15px;
}
}
......@@ -9,6 +9,7 @@
.prepend-top-0 { margin-top: 0; }
.prepend-top-5 { margin-top: 5px; }
.prepend-top-10 { margin-top: 10px; }
.prepend-top-15 { margin-top: 15px; }
.prepend-top-default { margin-top: $gl-padding !important; }
.prepend-top-20 { margin-top: 20px; }
.prepend-left-5 { margin-left: 5px; }
......
.trial-form-container {
.start-trial-header,
.start-trial-body {
margin-top: 30px;
}
.start-trial-header {
.trial-description {
color: $gl-gray-light;
}
}
}
.start-trial-body {
.ee-features {
border: 1px solid $border-color;
border-radius: $border-radius-default;
padding: 20px 40px;
}
}
.start-trial-body {
.trial-form {
label {
font-weight: normal;
}
}
}
.start-trial-body {
.feature-list li {
margin-top: 35px;
svg {
display: block;
margin: auto;
}
.feature-item-description {
h4 {
margin-top: 0;
}
p {
color: $gl-gray-light;
}
}
}
}
@media (max-width: $screen-md-min) {
.start-trial-body {
.feature-item-description {
margin-top: 15px;
h4,
p {
text-align: center;
}
}
.trial-form {
margin-top: 25px;
}
}
}
/* EE Trial Banner Styles */
/* Main Nav Overrides */
.navbar-gitlab.has-trial-banner {
top: 52px;
}
/* Secondary Nav Overrides - Old Nav */
.page-with-sidebar.has-trial-banner {
margin-top: 102px;
}
/* Sidebar Nav Overrides - New Nav */
.page-with-sidebar.has-trial-banner .nav-sidebar {
top: 102px;
}
/* Trial Banner */
.gitlab-ee-trial-banner.alert {
position: fixed;
top: 0;
width: 100%;
background: $white-light;
text-align: center;
z-index: 400;
p a {
color: $gl-link-color;
text-decoration: none;
font-weight: bold;
&:hover {
color: $gl-link-hover-color;
text-decoration: underline;
}
}
}
\ No newline at end of file
.blank-state-container {
margin-top: 35px;
.trial-description {
color: $gl-gray-light;
}
}
\ No newline at end of file
......@@ -286,8 +286,7 @@ table.u2f-registrations {
}
.user-callout {
margin: 0 auto;
max-width: $screen-lg-min;
margin: 20px -5px 0;
.bordered-box {
border: 1px solid $blue-300;
......
= link_to 'Buy License', "#{Gitlab::SUBSCRIPTIONS_URL}/plans", target: '_blank', rel: 'noopener noreferrer nofollow', class: "btn btn-new btn-inverted pull-right btn-buy-license"
= link_to 'Upload New License', new_admin_license_path, class: "btn pull-right btn-upload-license append-right-10"
......@@ -2,14 +2,13 @@
%h3.page-title
Your License
= link_to 'Buy License', "#{Gitlab::SUBSCRIPTIONS_URL}/plans", target: '_blank', class: "btn btn-new pull-right"
= link_to 'Upload New License', new_admin_license_path, class: "btn pull-right"
= render "upload_buy_license"
%hr
%h4 You do not have a license.
%p You can start a free trial of GitLab Enterprise Edition without any obligation or payment details.
= link_to 'Start free trial', new_admin_trials_url, class: "btn btn-new"
.container.blank-state-container
.text-center
= custom_icon("missing_license")
%h4 You do not have a license.
%p.trial-description You can start a free trial of GitLab Enterprise Edition without any obligation or payment details.
= link_to 'Start free trial', new_admin_trials_url, class: "btn btn-new btn-start-trial prepend-top-10"
......@@ -2,8 +2,7 @@
%h3.page-title
Your License
- if current_license.trial?
= link_to 'Buy License', "#{Gitlab::SUBSCRIPTIONS_URL}/plans", target: '_blank', class: "btn btn-new pull-right"
= link_to 'Upload New License', new_admin_license_path, class: "btn pull-right"
= render "upload_buy_license"
- else
= link_to 'Upload New License', new_admin_license_path, class: "btn btn-new pull-right"
......@@ -39,7 +38,7 @@
- if @license.will_expire?
%strong= time_ago_with_tooltip(@license.expires_at)
- if @license.trial?
%span= "(Free trial will expire in #{pluralize(@license.remaining_days, 'day')})"
%span Free trial will expire in #{pluralize(@license.remaining_days, 'day')}
- else
%strong Never
......
- page_title 'Trial license'
%h3.page-title Trial License
.container-fluid.trial-form-container
.text-center.start-trial-header
%h2 Free Trial of GitLab Enterprise Edition
%p.lead.trial-description No credit card required. 30 days free trial of all premium features.
%main{ :role => "main" }
.actions
= form_tag admin_trials_path, method: :post do
.form-group
= label_tag :first_name
= text_field_tag :first_name, params[:first_name], class: "form-control", required: true
.form-group
= label_tag :last_name
= text_field_tag :last_name, params[:last_name], class: "form-control", required: true
.form-group
= label_tag :work_email
= text_field_tag :work_email, params[:work_email], class: "form-control", required: true
.form-group
= label_tag :company_name
= text_field_tag :company_name, params[:company_name], class: "form-control", required: true
.form-group
= label_tag :phone_number
= text_field_tag :phone_number, params[:phone_number], class: "form-control", required: true
.form-group
= label_tag :number_of_developers
= text_field_tag :number_of_developers, params[:number_of_developers], class: "form-control", required: true
.form-group
= label_tag :number_of_users
= text_field_tag :number_of_users, params[:number_of_users], class: "form-control", required: true
.form-group
= label_tag :country
= select_tag :country, options_for_select(CountryCodes.for_select, params[:country]), prompt: '- Select One -', class: "form-control", required: true
.form-group
= submit_tag 'Start your free trial', class: "btn btn-default"
.row.start-trial-body
.col-md-6
.section-body.ee-features
%ul.list-unstyled.feature-list
%li.row
.col-md-4
= custom_icon("ee_ldap_sync")
.col-md-8.feature-item-description
%h4 LDAP Group Sync
%p
Automatically sync groups and manage SSH-keys, permissions,
and authentication.
%li.row
.col-md-4
= custom_icon("ee_mr_approvals")
.col-md-8.feature-item-description
%h4 Merge Request Approval
%p
Make sure every merge request is approved by one or more people.
%li.row
.col-md-4
= custom_icon("ee_audit_events")
.col-md-8.feature-item-description
%h4 Project Audit Events
%p
View any modifications made within the GitLab server in an
advanced audit log system.
%li.row
.col-md-4
= custom_icon("ee_file_locking")
.col-md-8.feature-item-description
%h4 File Locking
%p
Scan or modify the code to meet your security and development needs.
%hr
%p.text-center
= link_to 'More premium features', '#'
.col-md-6
.section-body.trial-form
= form_tag admin_trials_path, method: :post do
.form-group
= label_tag :first_name
= text_field_tag :first_name, params[:first_name], class: "form-control", required: true
.form-group
= label_tag :last_name
= text_field_tag :last_name, params[:last_name], class: "form-control", required: true
.form-group
= label_tag :work_email
= text_field_tag :work_email, params[:work_email], class: "form-control", required: true
.form-group
= label_tag :company_name
= text_field_tag :company_name, params[:company_name], class: "form-control", required: true
.form-group
= label_tag :phone_number
= text_field_tag :phone_number, params[:phone_number], class: "form-control", required: true
%hr
.form-group
= label_tag :number_of_developers
= text_field_tag :number_of_developers, params[:number_of_developers], class: "form-control", required: true
.form-group
= label_tag :number_of_users
= text_field_tag :number_of_users, params[:number_of_users], class: "form-control", required: true
.form-group
= label_tag :country
= select_tag :country, options_for_select(CountryCodes.for_select, params[:country]), prompt: '- Select One -', class: "form-control", required: true
.form-group
= submit_tag 'Start your free trial', class: "btn btn-primary"
- state_offset_class = current_license&.trial? ? 'col-md-offset-3' : 'col-md-offset-1'
- state_icon_class = current_license&.trial? ? 'col-md-1' : 'col-md-2'
- state_body_class = current_license&.trial? ? 'col-md-5' : 'col-md-8'
.row.blank-state.clearfix
.blank-state-icon{ class: "#{state_icon_class} #{state_offset_class}" }
= custom_icon("add_new_user", size: 50)
.blank-state-body{ class: state_body_class }
%h3.blank-state-title
Add user
%p.blank-state-text
Add your team members and others to GitLab.
= link_to new_admin_user_path, class: "btn btn-new" do
New user
.row.blank-state.clearfix
.blank-state-icon{ class: "#{state_icon_class} #{state_offset_class}" }
= custom_icon("configure_server", size: 50)
.blank-state-body{ class: state_body_class }
%h3.blank-state-title
Configure GitLab
%p.blank-state-text
Make adjustments to how your GitLab instance is set up.
= link_to admin_root_path, class: "btn btn-new" do
Configure
- if current_user.can_create_group?
.row.blank-state.clearfix
.blank-state-icon{ class: "#{state_icon_class} #{state_offset_class}" }
= custom_icon("add_new_group", size: 50)
.blank-state-body{ class: state_body_class }
%h3.blank-state-title
Create a group
%p.blank-state-text
Groups are a great way to organise projects and people.
= link_to new_group_path, class: "btn btn-new" do
New group
.blank-state.ee-trial.clearfix
.blank-state-icon
= custom_icon("ee_trial", size: 50)
.blank-state-body
%h3.blank-state-title
Unlock more features with GitLab Enterprise Edition
%p.blank-state-text
GitLab is free to use.
Many features for larger teams are part of
our paid
= succeed "." do
= link_to "Enterprise Edition products", "https://about.gitlab.com/products/", target: "_blank", rel: "noopener noreferrer nofollow"
You can try these out for free without
any obligation or payment details.
= link_to new_trial_path, class: "btn btn-new" do
Start free trial
- public_project_count = ProjectsFinder.new(current_user: current_user).execute.count
- if current_user.can_create_group?
.blank-state.clearfix
.col-md-1.col-md-offset-3.blank-state-icon
= custom_icon("add_new_group", size: 50)
.col-md-5.blank-state-body
%h3.blank-state-title
Create a group for several dependent projects.
%p.blank-state-text
Groups are the best way to manage projects and members.
= link_to new_group_path, class: "btn btn-new" do
New group
.blank-state.clearfix
.col-md-1.col-md-offset-3.blank-state-icon
= custom_icon("add_new_project", size: 50)
.col-md-5.blank-state-body
%h3.blank-state-title
Create a project
%p.blank-state-text
- if current_user.can_create_project?
You don't have access to any projects right now.
You can create up to
%strong= number_with_delimiter(current_user.projects_limit)
= succeed "." do
= "project".pluralize(current_user.projects_limit)
- else
If you are added to a project, it will be displayed here.
- if current_user.can_create_project?
= link_to new_project_path, class: "btn btn-new" do
New project
- if public_project_count > 0
.blank-state.clearfix
.col-md-1.col-md-offset-3.blank-state-icon
= custom_icon("globe", size: 50)
.col-md-5.blank-state-body
%h3.blank-state-title
Explore public projects
%p.blank-state-text
There are
= number_with_delimiter(public_project_count)
public projects on this server.
Public projects are an easy way to allow
everyone to have read-only access.
= link_to trending_explore_projects_path, class: "btn btn-new" do
Browse projects
- publicish_project_count = ProjectsFinder.new(current_user: current_user).execute.count
.blank-state.blank-state-welcome
%h2.blank-state-welcome-title
Welcome to GitLab
%p.blank-state-text
Code, test, and deploy together
- if current_user.can_create_group?
.blank-state
.blank-state-icon
= custom_icon("group", size: 50)
%h3.blank-state-title
You can create a group for several dependent projects.
%p.blank-state-text
Groups are the best way to manage projects and members.
= link_to new_group_path, class: "btn btn-new" do
New group
.blank-state
.blank-state-icon
= custom_icon("project", size: 50)
%h3.blank-state-title
You don't have access to any projects right now
%p.blank-state-text
- if current_user.can_create_project?
You can create up to
%strong= number_with_delimiter(current_user.projects_limit)
= succeed "." do
= "project".pluralize(current_user.projects_limit)
- else
If you are added to a project, it will be displayed here.
- if current_user.can_create_project?
= link_to new_project_path, class: "btn btn-new" do
New project
- if publicish_project_count > 0
.blank-state
.blank-state-icon
= icon("globe")
%h3.blank-state-title
There are
= number_with_delimiter(publicish_project_count)
public projects on this server.
%p.blank-state-text
Public projects are an easy way to allow everyone to have read-only access.
= link_to trending_explore_projects_path, class: "btn btn-new" do
Browse projects
.row.blank-state-parent-container
.col-md-6.section-container
.section-body.section-welcome{ class: "#{ 'section-admin-welcome' if current_user.admin? }" }
.blank-state.blank-state-welcome
%h2.blank-state-welcome-title
Welcome to GitLab
%p.blank-state-text
Code, test, and deploy together
- if current_user.admin?
= render "blank_state_admin_welcome"
- else
= render "blank_state_welcome"
- if !current_license&.trial? && current_user.admin?
.col-md-6.section-container
.section-body.section-ee-trial
= render "blank_state_ee_trial"
.page-with-sidebar{ class: "#{('page-with-new-sidebar' if defined?(@new_sidebar) && @new_sidebar)} #{page_gutter_class}" }
.page-with-sidebar.js-page-with-sidebar{ class: "#{('page-with-new-sidebar' if defined?(@new_sidebar) && @new_sidebar)} #{page_gutter_class}" }
- if show_new_nav?
- if defined?(nav) && nav
= render "layouts/nav/#{nav}"
......
%header.navbar.navbar-gitlab{ class: nav_header_class }
- if current_user.admin? && license_message.present?
.alert.alert-dismissible.gitlab-ee-trial-banner.hidden.js-gitlab-ee-trial-banner{ role: 'alert', 'data-license-expiry' => current_license.expires_at }
%button.close{ type: 'button', 'data-dismiss' => 'alert', 'aria-label' => 'Dismiss banner' }
= icon('times', 'aria-hidden' => 'true')
%p
= license_message
%header.navbar.navbar-gitlab.js-navbar-gitlab{ class: nav_header_class }
.navbar-border
%a.sr-only.gl-accessibility{ href: "#content-body", tabindex: "1" } Skip to content
.container-fluid
- if current_license&.trial? && license_message.present?
%p.text-center= license_message
.header-content
.dropdown.global-dropdown
%button.global-dropdown-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
......
%header.navbar.navbar-gitlab.navbar-gitlab-new{ class: nav_header_class }
- if current_user.admin? && license_message.present?
.alert.alert-dismissible.gitlab-ee-trial-banner.hidden.js-gitlab-ee-trial-banner{ role: 'alert', 'data-license-expiry' => current_license.expires_at }
%button.close{ type: 'button', 'data-dismiss' => 'alert', 'aria-label' => 'Dismiss banner' }
= icon('times', 'aria-hidden' => 'true')
%p
= license_message
%header.navbar.navbar-gitlab.navbar-gitlab-new.js-navbar-gitlab{ class: nav_header_class }
%a.sr-only.gl-accessibility{ href: "#content-body", tabindex: "1" } Skip to content
.container-fluid
.header-content
......
<svg xmlns="http://www.w3.org/2000/svg" width="78" height="82" viewBox="0 0 78 82">
<g fill="none" fill-rule="evenodd">
<path fill="#000" fill-opacity=".03" d="M2.12 42C2.04 43 2 44 2 45c0 20.43 16.57 37 37 37s37-16.57 37-37c0-1-.04-2-.12-3C74.35 61.03 58.42 76 39 76S3.65 61.03 2.12 42z"/>
<path fill="#EEE" fill-rule="nonzero" d="M39 78C17.46 78 0 60.54 0 39S17.46 0 39 0s39 17.46 39 39-17.46 39-39 39zm0-4c19.33 0 35-15.67 35-35S58.33 4 39 4 4 19.67 4 39s15.67 35 35 35z"/>
<path fill="#E1DBF2" fill-rule="nonzero" d="M59.65 32.65H60l-2-2.42-2 2.4-2-2.4-2 2.4-2-2.4-2 2.4-2-2.4-2 2.42h.77C45.57 34.6 46 36.75 46 39c0 2.84-.7 5.5-1.92 7.86 1.97 2.28 4.83 3.64 7.92 3.64 5.8 0 10.5-4.74 10.5-10.6 0-2.8-1.08-5.36-2.85-7.25zM43.18 29.6c2.4-2.1 5.52-3.3 8.82-3.3 7.46 0 13.5 6.1 13.5 13.6S59.46 53.5 52 53.5c-3.68 0-7.1-1.5-9.6-4.04C39.3 53.44 34.44 56 29 56c-9.4 0-17-7.6-17-17s7.6-17 17-17c3.22 0 6.23.9 8.8 2.45 2.13 1.3 3.97 3.05 5.38 5.16zM17 34c-.65 1.54-1 3.23-1 5 0 7.18 5.82 13 13 13s13-5.82 13-13c0-1.77-.35-3.46-1-5h-9c-.53 0-1.04-.2-1.4-.6L29 31.84l-1.6 1.58c-.36.4-.87.6-1.4.6h-9zm21.38-4c-2.4-2.5-5.76-4-9.38-4-3.62 0-6.98 1.5-9.38 4h5.55l2.42-2.4c.74-.8 2-.8 2.8 0l2.4 2.4h5.54z"/>
<path fill="#6B4FBB" d="M47.6 42.32c-.66 0-1.2-.54-1.2-1.2 0-.68.54-1.22 1.2-1.22.66 0 1.2.54 1.2 1.2 0 .68-.54 1.22-1.2 1.22zm8.8 0c-.66 0-1.2-.54-1.2-1.2 0-.68.54-1.22 1.2-1.22.66 0 1.2.54 1.2 1.2 0 .68-.54 1.22-1.2 1.22zM25 44h8c0 2.2-1.8 4-4 4s-4-1.8-4-4zm-1.5-1c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="78" height="82" viewBox="0 0 78 82"><g fill="none" fill-rule="evenodd"><path fill="#F9F9F9" d="M2.12 42c-.08.99-.12 1.99-.12 3 0 20.435 16.565 37 37 37s37-16.565 37-37c0-1.01-.04-2.01-.12-3C74.353 61.032 58.425 76 39 76 19.575 76 3.647 61.032 2.12 42z"/><path fill="#EEE" fill-rule="nonzero" d="M39 78C17.46 78 0 60.54 0 39S17.46 0 39 0s39 17.46 39 39-17.46 39-39 39zm0-4c19.33 0 35-15.67 35-35S58.33 4 39 4 4 19.67 4 39s15.67 35 35 35z"/><path fill="#FEE1D3" fill-rule="nonzero" d="M30 24a4 4 0 0 0-4 4v22a4 4 0 0 0 4 4h18a4 4 0 0 0 4-4V28a4 4 0 0 0-4-4H30zm0-4h18a8 8 0 0 1 8 8v22a8 8 0 0 1-8 8H30a8 8 0 0 1-8-8V28a8 8 0 0 1 8-8z"/><path fill="#FC6D26" d="M33 30h8a2 2 0 1 1 0 4h-8a2 2 0 1 1 0-4zm0 7h12a2 2 0 1 1 0 4H33a2 2 0 1 1 0-4zm0 7h12a2 2 0 1 1 0 4H33a2 2 0 1 1 0-4z"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="78" height="82" viewBox="0 0 78 82">
<g fill="none" fill-rule="evenodd">
<path fill="#000" fill-opacity=".03" d="M2.12 42C2.04 43 2 44 2 45c0 20.43 16.57 37 37 37s37-16.57 37-37c0-1-.04-2-.12-3C74.35 61.03 58.42 76 39 76S3.65 61.03 2.12 42z"/>
<path fill="#EEE" fill-rule="nonzero" d="M39 78C17.46 78 0 60.54 0 39S17.46 0 39 0s39 17.46 39 39-17.46 39-39 39zm0-4c19.33 0 35-15.67 35-35S58.33 4 39 4 4 19.67 4 39s15.67 35 35 35z"/>
<path fill="#E1DBF2" d="M44 31l-2.5-3-2.5 3-2.5-3-2.5 3-2.5-3-2.5 3h-2.72c2.65-4.2 7.36-7 12.72-7s10.07 2.8 12.72 7H49l-2.5-3-2.5 3z"/>
<path fill="#E1DBF2" fill-rule="nonzero" d="M39 57c-9.4 0-17-7.6-17-17s7.6-17 17-17 17 7.6 17 17-7.6 17-17 17zm0-4c7.18 0 13-5.82 13-13s-5.82-13-13-13-13 5.82-13 13 5.82 13 13 13z"/>
<path fill="#6B4FBB" d="M35 45h8c0 2.2-1.8 4-4 4s-4-1.8-4-4zm-1.5-2c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="78" height="82" viewBox="0 0 78 82">
<g fill="none" fill-rule="evenodd">
<path fill="#000" fill-opacity=".03" d="M2.12 42C2.04 43 2 44 2 45c0 20.43 16.57 37 37 37s37-16.57 37-37c0-1-.04-2-.12-3C74.35 61.03 58.42 76 39 76S3.65 61.03 2.12 42z"/>
<path fill="#EEE" fill-rule="nonzero" d="M39 78C17.46 78 0 60.54 0 39S17.46 0 39 0s39 17.46 39 39-17.46 39-39 39zm0-4c19.33 0 35-15.67 35-35S58.33 4 39 4 4 19.67 4 39s15.67 35 35 35z"/>
<path fill="#FEE1D3" fill-rule="nonzero" d="M24.92 35.15c-1.72-1.4-1.98-3.9-.6-5.63l1.26-1.55c1.4-1.72 3.9-2 5.63-.6l.7.56c.7-.4 1.4-.73 2.1-1V26c0-2.2 1.8-4 4-4h2c2.2 0 4 1.8 4 4v.92c.8.28 1.5.62 2.1 1l.7-.55c1.7-1.4 4.3-1.12 5.7.6l1.3 1.55c1.4 1.72 1.2 4.23-.6 5.63l-.7.6c.3.74.4 1.5.5 2.3l.9.2c2.2.5 3.5 2.64 3 4.8L56.4 45c-.5 2.15-2.64 3.5-4.8 3l-.88-.2c-.44.63-.92 1.24-1.46 1.8l.4.82c.9 1.98.1 4.38-1.9 5.35l-1.8.87c-2 .97-4.37.15-5.34-1.84l-.46-.85c-.34.03-.74.05-1.13.05-.4 0-.8-.02-1.2-.05l-.4.85c-.95 2-3.34 2.8-5.33 1.84l-1.8-.87c-1.97-.97-2.8-3.37-1.83-5.35l.4-.8c-.54-.58-1.02-1.2-1.46-1.83l-.8.2c-2.2.5-4.3-.9-4.8-3l-.4-2c-.5-2.2.85-4.3 3-4.8l.9-.2c.1-.8.3-1.6.5-2.3l-.7-.6zm4.95.77c-.53 1.2-.83 2.47-.87 3.8-.02.9-.66 1.68-1.55 1.9l-2.32.53.45 1.94 2.3-.6c.9-.2 1.8.2 2.23 1 .7 1.1 1.5 2.2 2.5 3 .7.6.9 1.6.5 2.4l-1 2.1 1.8.9 1.1-2.1c.4-.8 1.3-1.3 2.2-1.1.7.1 1.3.2 2 .2s1.3-.1 2-.2c.9-.2 1.8.3 2.2 1.1l1 2.1 1.8-.9-1.2-2c-.4-.8-.2-1.8.5-2.4 1-.85 1.84-1.88 2.45-3.05.4-.82 1.33-1.24 2.2-1.04l2.33.54.45-1.95-2.32-.54c-.9-.2-1.52-.97-1.54-1.88-.03-1.4-.33-2.6-.86-3.8-.4-.9-.2-1.8.5-2.4l1.9-1.5-1.3-1.6-1.8 1.5c-.8.5-1.8.6-2.5 0-1.1-.8-2.3-1.4-3.5-1.7-.9-.2-1.5-1-1.5-1.9V26h-2v2.38c0 .9-.6 1.7-1.5 1.93-1.3.4-2.5 1-3.5 1.7-.8.6-1.8.6-2.5 0l-1.9-1.5-1.26 1.6 1.8 1.5c.7.6.94 1.6.6 2.4z"/>
<path fill="#FC6D26" fill-rule="nonzero" d="M39 46c-3.3 0-6-2.7-6-6s2.7-6 6-6 6 2.7 6 6-2.7 6-6 6zm0-4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2z"/>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="74" height="78" viewBox="0 0 74 78"><g fill="none" fill-rule="evenodd"><path fill="#F9F9F9" d="M.053 39A37.599 37.599 0 0 0 0 41c0 20.435 16.565 37 37 37s37-16.565 37-37c0-.671-.018-1.338-.053-2C72.907 58.505 56.764 74 37 74 17.236 74 1.092 58.505.053 39z"/><path fill="#EEE" fill-rule="nonzero" d="M37 70c18.225 0 33-14.775 33-33S55.225 4 37 4 4 18.775 4 37s14.775 33 33 33zm0 4C16.565 74 0 57.435 0 37S16.565 0 37 0s37 16.565 37 37-16.565 37-37 37z"/><g fill-rule="nonzero"><path fill="#E1DBF2" d="M37 49c-6.406 0-12.228-2.843-17.38-8.412a4 4 0 0 1-.267-5.113C24.53 28.559 30.434 25 37 25c6.566 0 12.47 3.56 17.647 10.475a4 4 0 0 1-.266 5.113C49.228 46.158 43.406 49 37 49zm0-4c5.225 0 10.012-2.337 14.445-7.128C46.966 31.89 42.173 29 37 29s-9.966 2.89-14.445 8.872C26.988 42.662 31.775 45 37 45z"/><path fill="#6B4FBB" d="M37 45a8 8 0 1 1 0-16 8 8 0 0 1 0 16zm0-4a4 4 0 1 0 0-8 4 4 0 0 0 0 8zm0-1a3 3 0 1 1 0-6 3 3 0 0 1 0 6z"/></g></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="78" height="82" viewBox="0 0 78 82"><g fill="none" fill-rule="evenodd"><path fill="#F9F9F9" d="M2.12 42c-.08.99-.12 1.99-.12 3 0 20.435 16.565 37 37 37s37-16.565 37-37c0-1.01-.04-2.01-.12-3C74.353 61.032 58.425 76 39 76 19.575 76 3.647 61.032 2.12 42z"/><path fill="#EEE" fill-rule="nonzero" d="M39 78C17.46 78 0 60.54 0 39S17.46 0 39 0s39 17.46 39 39-17.46 39-39 39zm0-4c19.33 0 35-15.67 35-35S58.33 4 39 4 4 19.67 4 39s15.67 35 35 35z"/><path fill="#6B4FBB" fill-rule="nonzero" d="M48 31h-4a5 5 0 0 0-10 0h-4a9 9 0 1 1 18 0zm-18 0h4v3h-4v-3zm14 0h4v3h-4v-3z"/><path fill="#E1DBF2" fill-rule="nonzero" d="M30 37a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h18a1 1 0 0 0 1-1V38a1 1 0 0 0-1-1H30zm0-4h18a5 5 0 0 1 5 5v12a5 5 0 0 1-5 5H30a5 5 0 0 1-5-5V38a5 5 0 0 1 5-5z"/><path fill="#6B4FBB" d="M38 43.732a2 2 0 1 1 2 0V45a1 1 0 0 1-2 0v-1.268z"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="78" height="82" viewBox="0 0 78 82"><g fill="none" fill-rule="evenodd"><path fill="#F9F9F9" d="M2.12 42c-.08.99-.12 1.99-.12 3 0 20.435 16.565 37 37 37s37-16.565 37-37c0-1.01-.04-2.01-.12-3C74.353 61.032 58.425 76 39 76 19.575 76 3.647 61.032 2.12 42z"/><path fill="#EEE" fill-rule="nonzero" d="M39 78C17.46 78 0 60.54 0 39S17.46 0 39 0s39 17.46 39 39-17.46 39-39 39zm0-4c19.33 0 35-15.67 35-35S58.33 4 39 4 4 19.67 4 39s15.67 35 35 35z"/><path fill="#6B4BBE" fill-rule="nonzero" d="M40 28c5.523 0 10 4.477 10 10 0 2.279-.76 4.434-2.141 6.184A3 3 0 0 0 52.57 47.9C54.778 45.1 56 41.64 56 38c0-8.837-7.163-16-16-16v-3.131a1 1 0 0 0-1.555-.833l-9.197 6.132a1 1 0 0 0 0 1.664l9.197 6.132A1 1 0 0 0 40 31.13V28z"/><path fill="#E1DBF2" fill-rule="nonzero" d="M38 50c-5.523 0-10-4.477-10-10 0-2.25.742-4.38 2.09-6.12a3 3 0 0 0-4.742-3.675A15.941 15.941 0 0 0 22 40c0 8.837 7.163 16 16 16v3.131a1 1 0 0 0 1.555.833l9.197-6.132a1 1 0 0 0 0-1.664l-9.197-6.132A1 1 0 0 0 38 46.87V50z"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="74" height="78" viewBox="0 0 74 78"><g fill="none" fill-rule="evenodd"><path fill="#F9F9F9" d="M.053 39A37.599 37.599 0 0 1 0 37C0 16.565 16.565 0 37 0s37 16.565 37 37c0 .671-.018 1.338-.053 2 .035.662.053 1.329.053 2 0 20.435-16.565 37-37 37S0 61.435 0 41c0-.671.018-1.338.053-2zM37 74c20.435 0 37-16.565 37-37S57.435 0 37 0 0 16.565 0 37s16.565 37 37 37z"/><path fill="#EEE" fill-rule="nonzero" d="M37 70c18.225 0 33-14.775 33-33S55.225 4 37 4 4 18.775 4 37s14.775 33 33 33zm0 4C16.565 74 0 57.435 0 37S16.565 0 37 0s37 16.565 37 37-16.565 37-37 37z"/><path fill="#E1DBF2" fill-rule="nonzero" d="M40 23c5.523 0 10 4.477 10 10v12h-4V33a6 6 0 0 0-6-6v1.826a1 1 0 0 1-1.65.759l-4.464-3.826a1 1 0 0 1 0-1.518l4.463-3.826a1 1 0 0 1 1.651.76V23z"/><path fill="#E1DBF2" d="M28 43.341a6 6 0 1 1-4 0V29h4v14.341zM26 51a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"/><circle cx="26" cy="25" r="4" stroke="#6B4FBB" stroke-width="4"/><path fill="#6B4FBB" fill-rule="nonzero" d="M48 55a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-4a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="330" height="132" viewBox="0 0 330 132">
<g fill="none" fill-rule="evenodd">
<path fill="#000" fill-opacity=".03" d="M174.12 42c-.08 1-.12 2-.12 3 0 20.43 16.57 37 37 37s37-16.57 37-37c0-1-.04-2-.12-3-1.53 19.03-17.46 34-36.88 34s-35.35-14.97-36.88-34z"/>
<path fill="#EEE" fill-rule="nonzero" d="M211 78c-21.54 0-39-17.46-39-39s17.46-39 39-39 39 17.46 39 39-17.46 39-39 39zm0-4c19.33 0 35-15.67 35-35S230.33 4 211 4s-35 15.67-35 35 15.67 35 35 35z"/>
<g fill-rule="nonzero">
<path fill="#FEE1D3" d="M211.5 51c-6.42 0-12.26-2.84-17.43-8.4-1.32-1.43-1.43-3.58-.27-5.13C199 30.57 204.92 27 211.5 27s12.5 3.56 17.7 10.47c1.16 1.55 1.05 3.7-.27 5.12-5.17 5.53-11 8.4-17.43 8.4zm0-4c5.25 0 10.05-2.34 14.5-7.13-4.5-5.98-9.3-8.87-14.5-8.87-5.2 0-10 2.9-14.5 8.87 4.45 4.8 9.25 7.13 14.5 7.13z"/>
<path fill="#FC6D26" d="M211 47c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm0-4c2.2 0 4-1.8 4-4s-1.8-4-4-4-4 1.8-4 4 1.8 4 4 4zm0-1c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3z"/>
</g>
<path fill="#000" fill-opacity=".03" d="M88.12 83c-.08 1-.12 2-.12 3 0 20.43 16.57 37 37 37s37-16.57 37-37c0-1-.04-2-.12-3-1.53 19.03-17.46 34-36.88 34s-35.35-14.97-36.88-34z"/>
<path fill="#EEE" fill-rule="nonzero" d="M125 119c-21.54 0-39-17.46-39-39s17.46-39 39-39 39 17.46 39 39-17.46 39-39 39zm0-4c19.33 0 35-15.67 35-35s-15.67-35-35-35-35 15.67-35 35 15.67 35 35 35z"/>
<path fill="#FEE1D3" fill-rule="nonzero" d="M116 86.34c2.33.83 4 3.05 4 5.66 0 3.3-2.7 6-6 6s-6-2.7-6-6c0-2.6 1.67-4.83 4-5.66V72h4v14.34zM128 66c5.52 0 10 4.48 10 10v12h-4V76c0-3.3-2.7-6-6-6v1.83c0 .55-.45 1-1 1-.24 0-.47-.1-.65-.24l-4.46-3.87c-.46-.36-.5-1-.15-1.4.03-.05.07-.1.1-.12l4.47-3.82c.42-.35 1.05-.3 1.4.1.16.2.25.43.25.66V66zm-14 28c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2z"/>
<path fill="#FC6D26" fill-rule="nonzero" d="M114 74c-3.3 0-6-2.7-6-6s2.7-6 6-6 6 2.7 6 6-2.7 6-6 6zm0-4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm22 28c-3.3 0-6-2.7-6-6s2.7-6 6-6 6 2.7 6 6-2.7 6-6 6zm0-4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2z"/>
<path fill="#000" fill-opacity=".03" d="M2.12 52C2.04 53 2 54 2 55c0 20.43 16.57 37 37 37s37-16.57 37-37c0-1-.04-2-.12-3C74.35 71.03 58.42 86 39 86S3.65 71.03 2.12 52z"/>
<path fill="#EEE" fill-rule="nonzero" d="M39 88C17.46 88 0 70.54 0 49s17.46-39 39-39 39 17.46 39 39-17.46 39-39 39zm0-4c19.33 0 35-15.67 35-35S58.33 14 39 14 4 29.67 4 49s15.67 35 35 35z"/>
<path fill="#6B4FBB" fill-rule="nonzero" d="M48 41h-4c0-2.76-2.24-5-5-5s-5 2.24-5 5h-4c0-4.97 4.03-9 9-9s9 4.03 9 9zm-18 0h4v3h-4v-3zm14 0h4v3h-4v-3z"/>
<path fill="#E1DBF2" fill-rule="nonzero" d="M30 47c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h18c.55 0 1-.45 1-1V48c0-.55-.45-1-1-1H30zm0-4h18c2.76 0 5 2.24 5 5v12c0 2.76-2.24 5-5 5H30c-2.76 0-5-2.24-5-5V48c0-2.76 2.24-5 5-5z"/>
<path fill="#6B4FBB" d="M38 53.73c-.6-.34-1-1-1-1.73 0-1.1.9-2 2-2s2 .9 2 2c0 .74-.4 1.4-1 1.73V55c0 .55-.45 1-1 1s-1-.45-1-1v-1.27z"/>
<path fill="#000" fill-opacity=".03" d="M254.12 92c-.08 1-.12 2-.12 3 0 20.43 16.57 37 37 37s37-16.57 37-37c0-1-.04-2-.12-3-1.53 19.03-17.46 34-36.88 34s-35.35-14.97-36.88-34z"/>
<path fill="#EEE" fill-rule="nonzero" d="M291 128c-21.54 0-39-17.46-39-39s17.46-39 39-39 39 17.46 39 39-17.46 39-39 39zm0-4c19.33 0 35-15.67 35-35s-15.67-35-35-35-35 15.67-35 35 15.67 35 35 35z"/>
<path fill="#6B4BBE" fill-rule="nonzero" d="M292 78c5.52 0 10 4.48 10 10 0 2.28-.76 4.43-2.14 6.18-1.03 1.3-.8 3.2.5 4.22 1.3 1.02 3.2.8 4.2-.5 2.22-2.8 3.44-6.26 3.44-9.9 0-8.84-7.16-16-16-16v-3.13c0-.2-.06-.4-.17-.56-.3-.42-.93-.54-1.38-.23l-9.2 6.13c-.1.06-.2.16-.28.27-.3.45-.18 1.08.28 1.38l9.2 6.13c.16.1.35.17.55.17.55 0 1-.45 1-1V78z"/>
<path fill="#E1DBF2" fill-rule="nonzero" d="M290 100c-5.52 0-10-4.48-10-10 0-2.25.74-4.38 2.1-6.12 1-1.3.77-3.2-.54-4.2-1.3-1.02-3.2-.78-4.2.53C275.18 83 274 86.4 274 90c0 8.84 7.16 16 16 16v3.13c0 .55.45 1 1 1 .2 0 .4-.06.55-.17l9.2-6.13c.46-.3.6-.93.28-1.38-.07-.1-.17-.2-.28-.28l-9.2-6.13c-.45-.3-1.08-.2-1.38.27-.1.2-.17.4-.17.6v3.1z"/>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="78" height="82" viewBox="0 0 78 82"><g fill="none" fill-rule="evenodd"><path fill="#F9F9F9" d="M2.12 42c-.08.99-.12 1.99-.12 3 0 20.435 16.565 37 37 37s37-16.565 37-37c0-1.01-.04-2.01-.12-3C74.353 61.032 58.425 76 39 76 19.575 76 3.647 61.032 2.12 42z"/><path fill="#EEE" fill-rule="nonzero" d="M39 78C17.46 78 0 60.54 0 39S17.46 0 39 0s39 17.46 39 39-17.46 39-39 39zm0-4c19.33 0 35-15.67 35-35S58.33 4 39 4 4 19.67 4 39s15.67 35 35 35z"/><path fill="#E1DBF2" d="M30.24 27.823A14.98 14.98 0 0 0 24 40c0 2.549.636 4.949 1.757 7.051-.297-2.684.644-4.026 2.823-4.026 3.707 0 2.462 5.365 4.473 5.761 2.01.396 4.175.396 4.267 3.29.04 1.257-.265 2.157-.917 2.7a15.095 15.095 0 0 0 8.555-1.006c.035-1.91.303-4.941 2.21-5.61 2.373-.833-.55-1.431.734-3.368 1.17-1.762-3.297-5.2 0-4.832 3.477.388 5.044-.816 6.024-1.456a14.903 14.903 0 0 0-1.373-4.94c-.873.4-2.19.465-3.702-.538-.757-.502-1.084-3.944-2.107-3.944-3.823 0-4.065 3.17-5.994 3.944-1.076.431-4.193 3.773-5.614 3.596-1.126-.14-1.071-4.417-2.45-5.166-1.359-.738-2.174-1.948-2.447-3.633zM39 59c-10.493 0-19-8.507-19-19s8.507-19 19-19 19 8.507 19 19-8.507 19-19 19z"/></g></svg>
\ No newline at end of file
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment