diff --git a/ui/bundle_templates.js b/ui/bundle_templates.js index 95dfd733e4..5aa1ef359e 100644 --- a/ui/bundle_templates.js +++ b/ui/bundle_templates.js @@ -140,5 +140,13 @@ window.templates = { campaignAssignLayout: require('./src/templates/campaign/campaign-assign-layout.hbs'), }, + welcome: { + welcomeCard: + require('./src/templates/welcome/welcome-card.hbs'), + serviceCard: + require('./src/templates/welcome/service-card.hbs'), + othersCard: + require('./src/templates/welcome/others-card.hbs'), + }, }; diff --git a/ui/src/pages/welcome/welcome-page.js b/ui/src/pages/welcome/welcome-page.js new file mode 100644 index 0000000000..c4b615098e --- /dev/null +++ b/ui/src/pages/welcome/welcome-page.js @@ -0,0 +1,78 @@ +import './welcome-page.scss'; + +$(function () { + + for (let index = 0; index < onboardingCard.length; index++) { + const card = onboardingCard[index]; + + const $newCard = $(templates.welcome.welcomeCard(card)); + + $newCard.on('click', function (e) { + e.preventDefault(); + var targetId = $(this).attr("href"); + var targetElement = $(targetId); + + if (targetElement.length) { + var offset = targetElement.offset().top - 100; + + $("html, body").animate({ + scrollTop: offset + }, 800); + + targetElement.css({ + "border": "3px solid #0e70f6", + "transition": "border-color 1s ease-out" + }); + + setTimeout(function () { + targetElement.css("border-color", "transparent"); + }, 1000); + } + }); + + $newCard.appendTo('.welcome-page .onboarding-cards-container'); + } + + for (let index = 0; index < serviceCards.length; index++) { + const card = serviceCards[index]; + + let targetContainer = null; + + if (card.featureFlag === "displays.view") { + targetContainer = ".service-card-container .displays-enabled"; + } else if (Array.isArray(card.featureFlag) && card.featureFlag.includes("library.view") || card.featureFlag.includes("layout.view")) { + targetContainer = ".service-card-container .library-layout-enabled"; + } else if (card.featureFlag === "schedule.view") { + targetContainer = ".service-card-container .schedule-enabled"; + } + + if (targetContainer && $(targetContainer).length) { + const $serviceCard = $(templates.welcome.serviceCard(card)); + $serviceCard.appendTo(targetContainer); + } + } + + for (let index = 0; index < othersCards.length; index++) { + const card = othersCards[index]; + + const $othersCard = $(templates.welcome.othersCard(card)); + + $othersCard.appendTo('.welcome-page .others-card-container'); + } + + var scrollUpButton = $(".scroll-up"); + + $(window).on("scroll", function () { + if ($(window).scrollTop() > 200) { + scrollUpButton.fadeIn(); + } else { + scrollUpButton.fadeOut(); + } + }); + + scrollUpButton.on("click", function (e) { + e.preventDefault(); + $("html, body").animate({ scrollTop: 0 }, "smooth"); + }); + +}); diff --git a/ui/src/pages/welcome/welcome-page.scss b/ui/src/pages/welcome/welcome-page.scss new file mode 100644 index 0000000000..8585f1c377 --- /dev/null +++ b/ui/src/pages/welcome/welcome-page.scss @@ -0,0 +1,316 @@ +$blue: #0e70f6; +$blue-dark: #0b5ac5; +$orange: #eb7857; +$orange-dark: #bc6046; + +@mixin box-shadow($shadow: 0px 5px 30px 0px rgba(0, 0, 0, 0.1)) { + box-shadow: $shadow; +} + +.welcome-page { + display: flex; + flex-direction: column; + background-color: #ffffff; + background-size: cover; + background-position: top; + background-repeat: no-repeat; + padding: 80px 80px; + overflow: hidden; + position: relative; + top: -15px; + right: -8px; +} + +.welcome-header { + display: flex; + width: 100%; + align-items: center; + + h2 { + font-size: 40px; + color: $blue; + margin-bottom: 16px; + } + + p { + font-size: 20px; + } + + .header-text-content { + display: flex; + flex-direction: column; + width: 50%; + padding-right: 120px; + } + + .header-image-box { + display: flex; + width: 50%; + } +} + +@media (max-width: 1400px) { + .welcome-page { + padding: 60px 40px; + } + .welcome-header { + flex-direction: column; + row-gap: 40px; + + .header-text-content { + width: 100%; + padding-right: 0; + } + .header-image-box { + width: 100%; + } + } + + .onboarding-cards-container { + margin-top: 40px !important; + } + + .service-card-container { + margin-top: 40px !important; + } +} + +@media (max-width: 1290px) { + .others-card-container { + grid-template-columns: 1fr !important; + } +} + +@media (max-width: 1215px) { + .welcome-page { + padding: 35px 30px; + } + + .service-card { + flex-direction: column; + flex-wrap: wrap; + + .service-card-text { + margin-top: 20px; + } + } +} + +@media (max-width: 995px) { + .onboarding-cards-container { + display: grid !important; + grid-template-columns: 1fr 1fr; + + .onboarding-card { + width: 100%; + } + } + + .line-curve { + bottom: -15% !important; + } + + .welcome-page { + right: -4px; + } +} + +.btn-rounded { + border-radius: 100px; + padding: 7px 20px; + font-size: 16px; + font-weight: bold; + transition: background-color 0.3s ease; + text-decoration: none !important; +} + +.btn-orange { + background-color: $orange; + color: #fff; + border: none; + + &:hover { + background-color: $orange-dark; + color: #fff; + } +} + +.btn-outlined { + background-color: #fff; + color: $blue; + border: 2px solid $blue; + + &:hover { + background-color: $blue; + color: #fff; + } +} + +.onboarding-cards-container { + display: flex; + flex-wrap: wrap; + gap: 20px; + margin-top: 80px; + position: relative; +} + +.onboarding-card { + @include box-shadow; + display: flex; + flex-direction: column; + border-radius: 8px; + height: 160px; + width: 234px; + padding: 20px; + justify-content: space-between; + color: $blue; + transition: background-color 0.3s ease; + background-color: #ffffff; + z-index: 2; + cursor: pointer; + text-decoration: none; + + h3 { + font-size: 20px; + line-height: 16px; + margin-bottom: 0; + font-weight: 600; + text-decoration: none; + } + + &:hover { + background-color: $blue; + color: #ffffff; + text-decoration: none; + } +} + +.onboarding-welcome-image { + @include box-shadow; + border-radius: 20px; + width: 100%; + height: 500px; + object-fit: cover; +} + +.service-card { + @include box-shadow; + display: flex; + padding: 40px; + column-gap: 86px; + border-radius: 20px; + background-color: #ffffff; + position: relative; + z-index: 2; + + h3 { + color: $blue; + font-size: 20px; + margin: 0; + } + p { + color: #484848; + font-size: 16px; + margin-bottom: 0; + } + .text-link { + text-decoration: underline !important; + font-weight: 600 !important; + color: #484848; + } + .service-card-image { + width: 274px; + height: 154px; + } + .service-card-text { + display: flex; + flex-direction: column; + row-gap: 20px; + } +} + +.line-curve { + position: absolute; + z-index: 0; + right: -50%; + bottom: -50%; + height: 137.9px !important; +} + +.others-card-container { + margin-top: 40px; + flex-wrap: wrap; + justify-content: space-between; + display: grid; + grid-template-columns: 1fr 1fr 1fr; + gap: 32px; +} + +.others-card { + @include box-shadow; + display: flex; + flex-direction: column; + padding: 24px; + row-gap: 15px; + background-color: #fff; + border-radius: 20px; + align-items: start; + + h3 { + font-size: 24px; + font-weight: 600; + color: #1775f6; + } + + p { + font-size: 16px; + color: #484848; + line-height: normal; + } + + a { + color: #1775f6; + font-size: 16px; + font-weight: 500; + text-decoration: none; + + &:hover { + text-decoration: none; + color: $blue-dark; + } + } + + .links-list { + display: flex; + column-gap: 24px; + margin-top: auto; + } +} + +.optional-link { + color: #1775f6; + text-decoration: underline; + position: relative; + font-size: 16px; + font-weight: bold; + padding: 9px 20px; + + &::after { + content: " >"; + font-weight: bold; + position: absolute; + right: 8px; + } + + &:hover { + color: $blue-dark; + } +} + +.scroll-up { + position: fixed; + margin: 30px; + bottom: 0; + right: 0; + z-index: 3; +} diff --git a/ui/src/templates/welcome/others-card.hbs b/ui/src/templates/welcome/others-card.hbs new file mode 100644 index 0000000000..6fa0db2af0 --- /dev/null +++ b/ui/src/templates/welcome/others-card.hbs @@ -0,0 +1,9 @@ +
+ {{iconName}} +

{{title}}

+

{{text}}

+ +
\ No newline at end of file diff --git a/ui/src/templates/welcome/service-card.hbs b/ui/src/templates/welcome/service-card.hbs new file mode 100644 index 0000000000..cae8afba8a --- /dev/null +++ b/ui/src/templates/welcome/service-card.hbs @@ -0,0 +1,17 @@ +
+ {{serviceId}} +
+

{{title}}

+

{{{text}}}

+
+ {{#if showLink}} + Upload Content + Schedule Content + Learn More + {{else}} + Get Started + Learn More + {{/if}} +
+
+
\ No newline at end of file diff --git a/ui/src/templates/welcome/welcome-card.hbs b/ui/src/templates/welcome/welcome-card.hbs new file mode 100644 index 0000000000..a5c6453b2d --- /dev/null +++ b/ui/src/templates/welcome/welcome-card.hbs @@ -0,0 +1,6 @@ + +

{{ title }}

+
+ {{links}} +
+
\ No newline at end of file diff --git a/views/components.twig b/views/components.twig deleted file mode 100644 index 801f420d27..0000000000 --- a/views/components.twig +++ /dev/null @@ -1,40 +0,0 @@ -{% macro welcomeCard(title, iconName) %} -
-

{{ title | raw }}

-
- {{iconName}} -
-
-{% endmacro %} - -{% macro serviceCard(title, text, firstLink, secondLink, imageUrl, otherLink="") %} -
- {{ imageUrl }} -
-

{{ title }}

-

{{ text | raw }}

-
- - {% if title == "Existing Content" %} - Upload Content - Schedule Content - Learn More - {%else%} - Get Started - Learn More - {% endif %} -
-
-
-{% endmacro %} - -{% macro othersCard(title, text, links, iconName) %} -
- {{ iconName }} -

{{title}}

-

{{text}}

- -
-{% endmacro %} \ No newline at end of file diff --git a/views/welcome-page.twig b/views/welcome-page.twig index 8016ad9d73..eec9f94a45 100644 --- a/views/welcome-page.twig +++ b/views/welcome-page.twig @@ -21,145 +21,169 @@ */ #} {% extends "authed.twig" %} -{% import "components.twig" as components %} - -{% set isXiboThemed = theme.getThemeConfig("app_name") == "Xibo" %} {% block title %}{{ "Welcome"|trans }} | {% endblock %} {% block pageContent %}
-
-
+
+
{% set productName = theme.getThemeConfig('theme_title') %} -

{% trans %}Welcome to the {{productName}} CMS{% endtrans %}

-

{% trans %}The Content Management System (CMS) lets you create, manage, and update content. You can upload images and videos, design layouts, schedule content timing and location, and control the whole display network.{% endtrans %}

+

{% trans %}Welcome to the {{productName}} CMS{% endtrans %}

+

{% trans %}The Content Management System (CMS) lets you create, manage, and update content. + You can upload images and videos, design layouts, schedule content timing and location, + and control the whole display network.{% endtrans %}

-
+
Welcome Image
- {% set onboardingCard = [ - { - title: 'Displays' | trans, - iconName: 'displays-icon' - }, - { - title: 'Existing

Content' | trans, - iconName: 'existing-content-icon' - }, - { - title: 'Playlists' | trans, - iconName: 'playlist-icon' - }, - { - title: 'Create

Content' | trans, - iconName: 'create-content-icon' - }, - { - title: 'Schedule' | trans, - iconName: 'schedule-icon' - }, - ] %}
- {% for card in onboardingCard %} - {{ components.welcomeCard( - card.title, - card.iconName, - ) }} - {% endfor %} Welcome Image
- {% set title_displays = 'Displays'|trans %} - {% set text_displays = 'Get started by installing one of our Players and entering the pairing code into the Displays page so that you can show your content. - If you don’t have a device to use as a Player you can preview and test scheduling in your web browser.'|trans %} - {% set firstLink_displays = url_for("display.view") %} - {% set secondLink_displays = helpService.getLandingPage() ~ "displays.html" %} - {% set iconName_displays = 'displays' %} - - {% set title_existing_content = 'Existing Content'|trans %} - {% set text_existing_content = 'Do you already have content ready to show? Get started showing that in 2 easy steps. Upload any existing full-screen - images or videos to the Media Library, and then schedule those to be shown when you want on your display from the Schedule page.'|trans %} - {% set firstLink_existing_content = url_for("library.view") %} - {% set secondLink_existing_content = url_for("schedule.view") %} - {% set secondLink_existing_otherLink = helpService.getLandingPage() ~ "media_library.html" %} - {% set iconName_existing_content = 'existing-content' %} - - {% set title_playlists = 'Playlists'|trans %} - {% set text_playlists = 'If you’ve got lots of images or videos to show, then put them into a - Playlist and then schedule the Playlist on your display for easier management.'|trans %} - {% set firstLink_playlists = url_for("playlist.view") %} - {% set secondLink_playlists = helpService.getLandingPage() ~ "media_playlists.html" %} - {% set iconName_playlists = 'playlists' %} - - {% set title_create_content = 'Create Content'|trans %} - {% set text_create_content = 'If you need to create more complex content, the Layout Editor is there to help you create something stunning. - There are pre-designed templates that you can work from, or you can create something from scratch.'|trans %} - {% set firstLink_create_content = url_for("layout.view") %} - {% set secondLink_create_content = helpService.getLandingPage() ~ "layouts_editor.html" %} - {% set iconName_create_content = 'create-content' %} - - {% set title_schedule = 'Schedule'|trans %} - {% set text_schedule = 'You can mix and match between scheduling media items, layouts, and campaigns as you want. - If you schedule multiple things at the same time, they’ll be shown one after the other.'|trans %} - {% set firstLink_schedule = url_for("schedule.view") %} - {% set secondLink_schedule = helpService.getLandingPage() ~ "scheduling_events.html" %} - {% set iconName_schedule = 'schedule' %} - -
+
{% if currentUser.featureEnabled("displays.view") %} - {{ components.serviceCard(title_displays, text_displays, firstLink_displays, secondLink_displays, iconName_displays) }} +
{% endif %} {% if currentUser.featureEnabled("library.view") or currentUser.featureEnabled("layout.view") %} - {{ components.serviceCard(title_existing_content, text_existing_content, firstLink_existing_content, secondLink_existing_content, iconName_existing_content, secondLink_existing_otherLink ) }} - {{ components.serviceCard(title_playlists, text_playlists, firstLink_playlists, secondLink_playlists, iconName_playlists) }} - {{ components.serviceCard(title_create_content, text_create_content, firstLink_create_content, secondLink_create_content, iconName_create_content) }} +
{% endif %} {% if currentUser.featureEnabled("schedule.view") %} - {{ components.serviceCard(title_schedule, text_schedule, firstLink_schedule, secondLink_schedule, iconName_schedule) }} +
{% endif %} -
- {% set documentationTitle %}{{ 'Documentation'|trans }}{% endset %} - {% set documentationText %}{{ 'Our documentation is there to help you at every turn. It’s updated regularly to reflect changes and additions to the platform, and so it’s a valuable reference tool for all users.'|trans }}{% endset %} - {% set documentationLinks %} - {{ 'User Manual'|trans }} - {% if isXiboThemed and currentUser.isSuperAdmin() %} - {{ 'Admin'|trans }} - {{ 'Developer'|trans }} - {% endif %} - {% endset %} - - {% set trainingTitle %}{{ 'Training'|trans }}{% endset %} - {% set trainingText %}{{ 'Self-paced online training videos designed to get you up and running with Xibo in no time.'|trans }}{% endset %} - {% set trainingLinks %} - {{ 'New User Training'|trans }} - {% endset %} - - {% set helpTitle %}{{ 'Help'|trans }}{% endset %} - {% set helpText %}{{ 'We are here to help! All the support you’re looking for, at your fingertips.'|trans }}{% endset %} - {% set helpLinks %} - {% if isXiboThemed %} - {{ 'Help Centre'|trans }} - {{ 'Community'|trans }} - {% endif %} - {% endset %} -
- {{ components.othersCard(documentationTitle, documentationText, documentationLinks, "documentation") }} - {% if isXiboThemed %} - {{ components.othersCard(trainingTitle, trainingText, trainingLinks, "training") }} - {% endif %} - {{ components.othersCard(helpTitle, helpText, helpLinks, "help") }}
+{% endblock %} + +{% block javaScript %} + {# Initialise JS variables and translations #} + + + {# Add page source code bundle ( JS and CSS ) #} + {% endblock %} \ No newline at end of file diff --git a/web/theme/default/css/xibo.css b/web/theme/default/css/xibo.css index 5d9c5e0a29..5159b3110a 100644 --- a/web/theme/default/css/xibo.css +++ b/web/theme/default/css/xibo.css @@ -1618,337 +1618,3 @@ div.dataTables_wrapper div.dataTables_info { line-height: 1; border-radius: 2px; } - - -.welcome-page { - display: flex; - flex-direction: column; - background-color: #FFFFFF; - background-size: cover; - background-position: top; - background-repeat: no-repeat; - padding: 80px 80px; - overflow: hidden; - position: relative; - top: -15px; - right: -8px; -} - -.welcome-header { - display: flex; - width: 100%; - align-items: center; -} - -.welcome-header .text-left { - display: flex; - flex-direction: column; - width: 50%; -} - -.welcome-header .welcome-image-box { - display: flex; - flex-grow: 1; - width: 50%; -} - -@media (max-width: 1400px) { - .welcome-page{ - padding: 80px 20px; - } - .welcome-header{ - flex-direction: column; - } - - .welcome-header .welcome-image-box { - margin-top: 80px; - width: 100%; - } - .welcome-header .text-left{ - width: 100%; - } -} - -@media (max-width: 1850px) { - .others-card-container { - justify-content: start !important; - gap: 32px; - } -} - -@media (max-width: 765px) { - .service-card { - flex-direction: column; - } - .service-card h3 { - margin-top: 16px; - } -} - - -.btn-rounded { - border-radius: 100px; - padding: 9px 20px; - font-size: 20px; - font-weight: bold; - transition: background-color 0.3s ease; - text-decoration: none !important; -} - - -.btn-orange { - background-color: #EB7857; - color: #fff; - border: none; -} - -.btn-orange:hover { - background-color: #BC6046; - color: #fff; -} - -.btn-outlined { - background-color: #fff; - color: #0E70F6; - border: 2px solid #0E70F6; -} - -.btn-outlined:hover { - background-color: #0E70F6; - color: #fff; -} - -.onboarding-cards-container { - display: flex; - flex-wrap: wrap; - gap: 20px; - margin-top: 80px; - position: relative; -} - -.onboarding-card { - display: flex; - flex-direction: column; - border-radius: 8px; - height: 160px; - width: 234px; - padding: 20px; - box-shadow: 0px 5px 30px 0px rgba(0, 0, 0, 0.10); - justify-content: space-between; - color: #0E70F6; - transition: background-color 0.3s ease; - background-color: #FFFFFF; - z-index: 2; -} - - -.onboarding-card h3 { - font-size: 24px; - line-height: 16px; - margin-bottom: 0; - font-weight: 600; -} - -.onboarding-card:hover { - background-color: #0E70F6; - color: #ffffff; -} - -.onboarding-welcome-image { - border-radius: 20px; - box-shadow: 0px 5px 30px 0px rgba(0, 0, 0, 0.10); - width: 100%; - height: 500px; - object-fit: cover; -} - -.service-card { - display: flex; - padding: 40px; - column-gap: 86px; - border-radius: 20px; - box-shadow: 0px 5px 30px 0px rgba(0, 0, 0, 0.10); - background-color: #FFFFFF; - z-index: 2; -} - -.service-card h3 { - color: #0E70F6; - font-size: 32px; -} - -.service-card p { - color: #484848; - font-size: 24px; - margin-bottom: 0; -} - -.service-card .text-link { - text-decoration: underline !important; - font-weight: 600 !important; - color: #484848; -} - - - -.service-card-image { - width: 274px; - height: 154px; -} - -.service-card-text { - display: flex; - flex-direction: column; - row-gap: 20px; -} - -.line-curve { - position: absolute; - z-index: 0; - right: -50%; - bottom: -50%; - height: 137.9px !important; -} - -.others-card-container{ - margin-top: 40px; - display: flex; - flex-wrap: wrap; - justify-content: space-between; -} - -.others-card { - display: flex; - flex-direction: column; - padding: 24px; - row-gap: 15px; - background-color: #fff; - border-radius: 20px; - box-shadow: 0px 5px 30px 0px rgba(0, 0, 0, 0.10); - align-items: start; - width: 480px; - height: 312px; -} - -.others-card h3 { - font-size: 24px; - font-weight: 600; - color: #1775F6; -} - -.others-card p { - font-size: 16px; - color: #484848; - line-height: normal -} - -.others-card a { - color: #1775F6; - font-size: 16px; - font-weight: 500; -} - -.links-list { - display: flex; - column-gap: 24px; - margin-top: auto; -} - -.optional-link { - color: #1775F6; - text-decoration: underline; - position: relative; - font-size: 16px; - font-weight: bold; - padding: 9px 20px; -} - -.optional-link::after { - content: ' >'; - color: #1775F6; - font-weight: bold; - position: absolute; - right: 8px; -} - -.scroll-up { - position: fixed; - margin: 30px; - bottom: 0; - right: 0; - z-index: 3; -} - -/* Reminder Events and Schedule Criteria */ -.reminder-event-row, .schedule-criteria-row { - display: inline-flex !important; - width: 100%; - gap: 12px; - padding: 0 15px; - margin-bottom: 8px; -} - -.reminder-event-cell label, .schedule-criteria-cell label { - width: 100%; -} - -.reminder-event-btn, .schedule-criteria-btn { - flex-grow: 1; - text-align: right; -} - -.schedule-criteria-type, .schedule-criteria-condition, .schedule-criteria-metric { - flex-basis: 165px; -} - -.schedule-criteria-value { - flex-basis: 130px; -} - -.reminder-event-value { - flex-basis: 100px; -} - -.reminder-event-type { - flex-basis: 120px; -} - -.reminder-event-option { - flex-basis: 200px; -} - -.reminder-event-email { - flex-basis: 180px; -} - -@media screen and (max-width: 992px) { - .reminder-event-row, .schedule-criteria-row { - gap: 8px; - padding: 0; - } - - .schedule-criteria-type, .schedule-criteria-condition, .schedule-criteria-metric { - flex-basis: 95px; - } - - .schedule-criteria-value { - flex-basis: 85px; - } - - .reminder-event-value { - flex-basis: 60px; - } - - .reminder-event-type { - flex-basis: 85px; - } - - .reminder-event-option { - flex-basis: 140px; - } - - .reminder-event-email { - flex-basis: 80px; - line-height: 1.2rem; - } -} diff --git a/webpack.config.js b/webpack.config.js index 1df84597bb..5c4a159dc7 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -170,6 +170,7 @@ const pageConfig = Object.assign({}, config, { 'campaign-page': './ui/src/pages/campaign/campaing-page.js', 'developer-template-page': './ui/src/pages/developer-template/developer-template-page.js', + 'welcome-page': './ui/src/pages/welcome/welcome-page.js', }, output: { path: path.resolve(__dirname, 'web/dist/pages'),