diff --git a/app/_config/config.yml b/app/_config/config.yml index 2e526ca..58ca3f0 100644 --- a/app/_config/config.yml +++ b/app/_config/config.yml @@ -1,15 +1,10 @@ --- Name: webapp --- + SilverStripe\Core\Manifest\ModuleManifest: project: app -SilverStripe\View\SSViewer: - source_file_comments: true - themes: - - '$public' - - '$default' - Page: default_container_class: 'container' diff --git a/app/_config/extensions.yml b/app/_config/extensions.yml index 10d6644..a65b9f9 100644 --- a/app/_config/extensions.yml +++ b/app/_config/extensions.yml @@ -11,15 +11,21 @@ SilverStripe\Blog\Model\BlogPost: extensions: - Site\Extensions\BlogPostExtension +Sheadawson\Linkable\Models\EmbeddedObject: + extensions: + - Site\Extensions\EmbeddedObjectExtension + Dynamic\FlexSlider\Model\SlideImage: extensions: - - Site\Extensions\SlideImageExtension + - Site\Extensions\SlideImageExtension SilverStripe\Core\Injector\Injector: SilverStripe\UserForms\Model\UserDefinedForm: class: Site\Extensions\CMSMain_HiddenClass SilverStripe\Security\MemberAuthenticator\LostPasswordHandler: class: Site\Extensions\LostPasswordHandlerExtension + Sheadawson\Linkable\Forms\EmbeddedObjectField: + class: Site\Extensions\EmbedObjectField # User Forms SilverStripe\UserForms\Form\UserForm: diff --git a/app/_config/themes.yml b/app/_config/themes.yml new file mode 100644 index 0000000..e02cde1 --- /dev/null +++ b/app/_config/themes.yml @@ -0,0 +1,9 @@ +--- +Name: webapp-themes +--- + +SilverStripe\View\SSViewer: + source_file_comments: true + themes: + - '$public' + - '$default' diff --git a/app/client/src/js/_components/_ui.carousel.js b/app/client/src/js/_components/_ui.carousel.js index 4f0b84f..14ff826 100644 --- a/app/client/src/js/_components/_ui.carousel.js +++ b/app/client/src/js/_components/_ui.carousel.js @@ -53,6 +53,37 @@ const CarouselUI = (($) => { // init carousel $e.carousel(); + const $youtubeSlides = $e.find('iframe[src^="https://www.youtube.com/embed/"]'); + + $e.on('slide.bs.carousel', () => { + if ($youtubeSlides.length) { + $youtubeSlides.each((i, e) => { + const $e = $(e); + try { + $e.data('player', new YT.Player(e, { + events: { + 'onReady': () => { + $e.data('player').pauseVideo(); + } + } + })); + + $e.data('player').pauseVideo(); + } catch (e) {} + }); + } + }); + + $e.find('.carousel-control-prev').on('click', (e) => { + e.preventDefault(); + $e.carousel('prev'); + }); + + $e.find('.carousel-control-next').on('click', (e) => { + e.preventDefault(); + $e.carousel('next'); + }); + // init touch swipes $e.hammer().bind('swipeleft', (event) => { $(event.target).carousel('next'); @@ -70,7 +101,7 @@ const CarouselUI = (($) => { $(event.target).carousel('prev'); }); - $e.hammer().bind('tap', (event) => { + $e.find('.carousel-item').hammer().bind('tap', (event) => { $(event.target).carousel('next'); }); }); diff --git a/app/client/src/js/_components/_ui.form.validate.field.js b/app/client/src/js/_components/_ui.form.validate.field.js index 277dda2..44f0bf0 100644 --- a/app/client/src/js/_components/_ui.form.validate.field.js +++ b/app/client/src/js/_components/_ui.form.validate.field.js @@ -82,7 +82,7 @@ const FormValidateField = (($) => { isHtml(str) { const doc = new DOMParser().parseFromString(str, "text/html"); - return Array.from(doc.body.childNodes).some(node => node.nodeType === 1); + return Array.from(doc.body.childNodes).some((node) => node.nodeType === 1); } valideURL(str) { diff --git a/app/client/src/js/_main.js b/app/client/src/js/_main.js index 072dc92..57f424f 100644 --- a/app/client/src/js/_main.js +++ b/app/client/src/js/_main.js @@ -246,6 +246,11 @@ const MainUI = (($) => { if (W.URLDetails['hash'].indexOf('printpage') > -1) { W.print(); } + + // load youtube API + if ($('iframe[src^="https://www.youtube.com/embed/"]').length) { + $Body.append(''); + } } static updateLocation(url) { diff --git a/app/client/src/scss/_components/_ui.carousel.scss b/app/client/src/scss/_components/_ui.carousel.scss index babd8dd..1c42710 100644 --- a/app/client/src/scss/_components/_ui.carousel.scss +++ b/app/client/src/scss/_components/_ui.carousel.scss @@ -2,12 +2,32 @@ * Bootstrap carousel improvement */ -.carousel-item { +/*.carousel-item { &.active { display: flex !important; justify-content: center; align-items: flex-start; } +}*/ + +.carousel-slide { + display: flex; + justify-content: center; + align-items: flex-start; + + .video { + width: 100%; + + iframe { + width: 100% !important; + height: auto !important; + } + } + + .img { + display: block; + width: 100%; + } } .carousel-control-prev, diff --git a/app/client/src/scss/_components/_ui.main.scss b/app/client/src/scss/_components/_ui.main.scss index 3c398e9..21582e6 100644 --- a/app/client/src/scss/_components/_ui.main.scss +++ b/app/client/src/scss/_components/_ui.main.scss @@ -204,3 +204,35 @@ button, input, optgroup, select, textarea, z-index: 1; } } + +// dark dropdowns +.dropdown-menu.bg-dark { + border-color: $dark; + + .nav-link { + color: $navbar-dark-color; + + @include hover-focus { + color: $navbar-dark-hover-color; + } + + + &.disabled { + color: $navbar-dark-disabled-color; + } + } + + .show > .nav-link, + .active > .nav-link, + .nav-link.show, + .nav-link.active { + color: $navbar-dark-active-color; + } + + .dropdown-item { + @include hover-focus { + color: $navbar-dark-brand-hover-color; + background: $dark; + } + } +} diff --git a/app/client/src/scss/_variables.scss b/app/client/src/scss/_variables.scss index 173dc6e..aac06bf 100644 --- a/app/client/src/scss/_variables.scss +++ b/app/client/src/scss/_variables.scss @@ -21,9 +21,12 @@ $bg-alt: $yellow; $body-color: $gray-900; $navbar-light-active-color: $blue; +$navbar-dark-hover-background: $dark; +$navbar-dark-active-background: $dark; + $dropdown-border-color: $white; -$footer-size: 16rem; +$footer-size: 18.5rem; $footer-bar-size: 2.5rem; /* diff --git a/app/lang/en.yml b/app/lang/en.yml index 300b5d5..a33f9de 100644 --- a/app/lang/en.yml +++ b/app/lang/en.yml @@ -21,3 +21,6 @@ en: EMPTY: "Please prove you are human - check the Captcha box." NOSCRIPT: "You must enable JavaScript to submit this form" VALIDATE_ERROR: "Captcha could not be validated" + Dynamic\FlexSlider\Model\SlideImage: + SINGULARNAME: 'Slide' + PLURALNAME: 'Slides' diff --git a/app/src/Elements/SliderElement.php b/app/src/Elements/SliderElement.php index 8dafcb0..f9e637a 100644 --- a/app/src/Elements/SliderElement.php +++ b/app/src/Elements/SliderElement.php @@ -14,6 +14,7 @@ use Dynamic\FlexSlider\ORM\FlexSlider; use SilverStripe\Core\Injector\Injector; use SilverStripe\Forms\CheckboxField; use SilverStripe\Forms\LiteralField; +use SilverStripe\Forms\NumericField; use SilverStripe\Forms\ReadonlyField; use Symbiote\GridFieldExtensions\GridFieldEditableColumns; @@ -27,6 +28,10 @@ class SliderElement extends ElementSlideshow private static $table_name = 'SliderElement'; + private static $db = [ + 'Interval' => 'Int', + ]; + private static $extensions = [ FlexSlider::class, ]; @@ -60,6 +65,10 @@ class SliderElement extends ElementSlideshow 'CarouselThumbnailCt', ]); + $fields->addFieldsToTab('Root.Settings', [ + NumericField::create('Interval', 'Auto-play Interval'), + ]); + $grid = $fields->dataFieldByName('Slides'); if ($grid) { $config = $grid->getConfig(); @@ -99,4 +108,13 @@ class SliderElement extends ElementSlideshow return $this->items; } + + public function onBeforeWrite() + { + parent::onBeforeWrite(); + + if(!$this->getField('Interval')){ + $this->setField('Interval', 5000); + } + } } diff --git a/app/src/Extensions/ElementRows.php b/app/src/Extensions/ElementRows.php index 34f1b7c..3c28249 100644 --- a/app/src/Extensions/ElementRows.php +++ b/app/src/Extensions/ElementRows.php @@ -200,7 +200,7 @@ class ElementRows extends DataExtension { return $this->owner->getField('ExtraClass') .( - $this->isColumn() + $this->isColumn() ? ' '.Config::inst()->get(self::class, 'column_class').$this->owner->getField('Size') : '' ); @@ -221,4 +221,4 @@ class ElementRows extends DataExtension return $type; } -} +} \ No newline at end of file diff --git a/app/src/Extensions/EmbedObjectField.php b/app/src/Extensions/EmbedObjectField.php new file mode 100644 index 0000000..00bfd50 --- /dev/null +++ b/app/src/Extensions/EmbedObjectField.php @@ -0,0 +1,42 @@ +getName(); + + $fields = [ + CheckboxField::create( + $name . '[autoplay]', + _t(self::CLASS.'AUTOPLAY', 'Autoplay video?') + )->setValue($this->object->Autoplay), + + CheckboxField::create( + $name . '[loop]', + _t(self::CLASS.'LOOP', 'Loop video?') + )->setValue($this->object->Loop) + ]; + + return CompositeField::create(array_merge([ + LiteralField::create( + $name.'Options', + parent::FieldHolder($properties) + ) + ], $fields)); + } +} \ No newline at end of file diff --git a/app/src/Extensions/EmbeddedObjectExtension.php b/app/src/Extensions/EmbeddedObjectExtension.php new file mode 100644 index 0000000..6606380 --- /dev/null +++ b/app/src/Extensions/EmbeddedObjectExtension.php @@ -0,0 +1,60 @@ + 'Boolean(0)', + 'Loop' => 'Boolean(0)', + ]; + + public function Embed() + { + $this->owner->Embed(); + $this->setEmbedParams(); + + return $this->owner; + } + + public function setEmbedParams($params = []) + { + // YouTube params + if(stripos($this->owner->EmbedHTML, 'https://www.youtube.com/embed/') > 0) { + $params = array_merge([ + 'feature=oembed', + 'wmode=transparent', + 'enablejsapi=1', + 'disablekb=1', + 'iv_load_policy=3', + 'modestbranding=1', + 'rel=0', + 'showinfo=0', + ], $params); + + if ($this->owner->Autoplay) { + $params[] = 'autoplay=1'; + } + + if ($this->owner->Loop) { + $params[] = 'loop=1'; + } + + $this->owner->EmbedHTML = preg_replace( + '/src="([A-z0-9:\/\.]+)\??(.*?)"/', + 'src="${1}?' . implode('&', $params) . '"', + $this->owner->EmbedHTML + ); + } + } + + public function onBeforeWrite() + { + parent::onBeforeWrite(); + $this->setEmbedParams(); + } +} \ No newline at end of file diff --git a/app/src/Extensions/UserDefinedFormExtension.php b/app/src/Extensions/UserDefinedFormExtension.php index 5167979..afbf61e 100644 --- a/app/src/Extensions/UserDefinedFormExtension.php +++ b/app/src/Extensions/UserDefinedFormExtension.php @@ -12,11 +12,11 @@ use SilverStripe\UserForms\Model\EditableFormField; class UserDefinedFormExtension extends DataExtension { - private static $db = [ + /*private static $db = [ 'CustomThankYouCode' => 'HTMLText', 'RedirectOnComplete' => 'Boolean(0)', 'RedirectOnCompleteURL' => 'Varchar(255)', - ]; + ];*/ private static $many_many = [ 'SubmissionColumns' => EditableFormField::class, @@ -44,7 +44,7 @@ class UserDefinedFormExtension extends DataExtension /*$tab->push(CheckboxField::create('RedirectOnComplete')); $tab->push(TextField::create('RedirectOnCompleteURL'));*/ - $tab->push(TextareaField::create('CustomThankYouCode')); + //$tab->push(TextareaField::create('CustomThankYouCode')); $grid = $fields->dataFieldByName('Submissions'); @@ -65,7 +65,7 @@ class UserDefinedFormExtension extends DataExtension $name = $col->getField('Name'); $columns[$name] = [ 'title' => $title, - 'callback' => function($item) use ($name) { + 'callback' => function ($item) use ($name) { return $item->relField($name); } ]; diff --git a/app/src/Templates/DeferedRequirements.php b/app/src/Templates/DeferedRequirements.php index bc463bb..575f057 100644 --- a/app/src/Templates/DeferedRequirements.php +++ b/app/src/Templates/DeferedRequirements.php @@ -9,7 +9,6 @@ use SilverStripe\Core\Config\Config; use SilverStripe\Control\Director; use SilverStripe\Core\Path; use SilverStripe\Core\Manifest\ManifestFileFinder; -use SilverStripe\CMS\Controllers\CMSMain; class DeferedRequirements implements TemplateGlobalProvider { @@ -36,15 +35,21 @@ class DeferedRequirements implements TemplateGlobalProvider public static function Auto($class = false) { - if (is_a(Controller::curr(), CMSMain::class)) { - return; - } - $config = Config::inst()->get(self::class); $projectName = WebpackTemplateProvider::projectName(); $mainTheme = WebpackTemplateProvider::mainTheme(); $mainTheme = $mainTheme ? $mainTheme : $projectName; + $dir = Path::join( + Director::publicFolder(), + ManifestFileFinder::RESOURCES_DIR, + $projectName, + 'client', + 'dist' + ); + $cssPath = Path::join($dir, 'css'); + $jsPath = Path::join($dir, 'js'); + // Initialization Requirements::block(THIRDPARTY_DIR.'/jquery/jquery.js'); /*if (defined('FONT_AWESOME_DIR')) { @@ -60,7 +65,6 @@ class DeferedRequirements implements TemplateGlobalProvider if (!$config['nofontawesome']) { DeferedRequirements::loadCSS('//use.fontawesome.com/releases/v5.4.0/css/all.css'); } - DeferedRequirements::loadCSS($mainTheme.'.css'); DeferedRequirements::loadJS($mainTheme.'.js'); @@ -78,25 +82,18 @@ class DeferedRequirements implements TemplateGlobalProvider } $class = str_replace('\\', '.', $class); - $dir = Path::join( - Director::publicFolder(), - ManifestFileFinder::RESOURCES_DIR, - $projectName, - 'client', - 'dist' - ); // Controller requirements - $themePath = Path::join($dir, 'css', $mainTheme.'_'.$class . '.css'); - $projectPath = Path::join($dir, 'css', $projectName.'_'.$class . '.css'); + $themePath = Path::join($cssPath, $mainTheme.'_'.$class . '.css'); + $projectPath = Path::join($cssPath, $projectName.'_'.$class . '.css'); if ($mainTheme && file_exists($themePath)) { DeferedRequirements::loadCSS($mainTheme.'_'.$class . '.css'); } elseif (file_exists($projectPath)) { DeferedRequirements::loadCSS($projectName.'_'.$class . '.css'); } - $themePath = Path::join($dir, 'js', $mainTheme.'_'.$class . '.js'); - $projectPath = Path::join($dir, 'js', $projectName.'_'.$class . '.js'); + $themePath = Path::join($jsPath, $mainTheme.'_'.$class . '.js'); + $projectPath = Path::join($jsPath, $projectName.'_'.$class . '.js'); if ($mainTheme && file_exists($themePath)) { DeferedRequirements::loadJS($mainTheme.'_'.$class . '.js'); } elseif (file_exists($projectPath)) { diff --git a/app/templates/Includes/Footer.ss b/app/templates/Includes/Footer.ss index e004aa8..5306567 100644 --- a/app/templates/Includes/Footer.ss +++ b/app/templates/Includes/Footer.ss @@ -1,25 +1,27 @@ <% with $SiteConfig %> -
-

Contact Us

-
-
Address:
-
$Address
-
+
+
+

Contact Us

+
+
Address:
+
$Address
+
-
-
Phone:
-
$PhoneNumber
-
+
+
Phone:
+
$PhoneNumber
+
-
-
Email:
-
$PublicEmail
-
+
+
Email:
+
$PublicEmail
+
- <% include Objects\SocialLinks %> + <% include Objects\SocialLinks %> +
-