Skip to content
Snippets Groups Projects
Commit 8e239529 authored by Grzegorz Rola's avatar Grzegorz Rola
Browse files

feature(popup): popup

parent 23369db9
No related branches found
No related tags found
1 merge request!3feature(popup): popup
Showing with 55695 additions and 48 deletions
## [1.0.2] - 2021-08-12
### Added
- Popup
## [1.0.0] - 2021-08-05 ## [1.0.0] - 2021-08-05
### Added ### Added
- Init - Init
\ No newline at end of file
...@@ -4,10 +4,30 @@ Unit: [![coverage report](https://gitlab.com/wpdesk/library/wp-wpdesk-activation ...@@ -4,10 +4,30 @@ Unit: [![coverage report](https://gitlab.com/wpdesk/library/wp-wpdesk-activation
# wp-wpdesk-activation-reminder # wp-wpdesk-activation-reminder
## Developing
Before commit execute: `npm run prod` !
## Usage ## Usage
```bash ```bash
composer require --dev wpdesk/wp-wpdesk-activation-reminder composer require wpdesk/wp-wpdesk-activation-reminder
composer update composer update
``` ```
composer.json `extra` section in project must contain:
```
"activation-reminder" : {
"plugin-title" : "Flexible Shipping PRO",
"plugin-dir" : "flexible-shipping-pro",
"logo-url": "assets/images/logo-fs.svg",
"buy-plugin-url": "https://flexibleshipping.com/products/flexible-shipping-pro-woocommerce/"
}
```
where:
- `plugin-title` - plugin title displayed in activation reminder popup
- `plugin-dir` - plugin dir name - used to generate URLs for assets
- `logo-url` - logo path in plugin directory
- `buy-plugin-url` - URL to product page in shop
import React from "react";
import {Button, Col, Container, Modal, Row} from "react-bootstrap";
import Cookies from 'js-cookie';
/**
* ActivationReminder REACT class.
*/
export default class ActivationReminder extends React.Component {
/**
* @param {Object} props
*/
constructor( props ) {
super( props );
let cookie_name = props.cookie_name;
this.state = {
show: this.shouldShow( cookie_name ),
logo_url: props.logo_url,
plugin_dir: props.plugin_dir,
plugin_title: props.plugin_title,
cookie_name: cookie_name,
};
this.handleClose = this.handleClose.bind(this);
this.handleGetLicence = this.handleGetLicence.bind(this);
};
/**
*
*/
handleClose() {
this.setState( { show: false } );
}
/**
* @param {String} cookie_name
* @return {boolean}
*/
shouldShow( cookie_name ) {
let timestamp = Math.round(new Date() / 1000);
let cookie = Cookies.get( cookie_name );
if ( cookie === undefined ) {
Cookies.set( cookie_name, timestamp + 60 * 60 * 24 * 14, { expires: 730 } );
} else if ( cookie < timestamp ) {
Cookies.set( cookie_name, timestamp + 60 * 60 * 24 * 14, { expires: 730 } );
return true;
}
return false;
}
/**
*
*/
handleGetLicence() {
window.open( this.props.buy_plugin_url );
}
/**
* @returns {JSX.Element}
*/
render() {
let state = this.state;
return (
<Modal
size="lg"
show={state.show}
onHide={this.handleClose}
className={"wpdesk-activation-reminder-popup"}
centered
>
<Modal.Header closeButton></Modal.Header>
<Modal.Body>
<Container>
<img className={"logo"} src={this.state.logo_url} />
</Container>
<Container>
<Row className={"header"}>
<Col>
<h1>Activate {this.props.plugin_title} License</h1>
<h2>We've noticed that you haven't activated the license for the {this.props.plugin_title} plugin.</h2>
</Col>
</Row>
<Row className={"benefits"}>
<Col>
<strong>With a valid license you get:</strong>
<ul>
<li>premium support</li>
<li>new features</li>
<li>safety updates</li>
<li>plugin from a safe source, with verified code and without any malware</li>
</ul>
In addition you'll support WordPress and WooCommerce community.<br/>
<a target="_blank" href="https://wpde.sk/fs-license">Learn more about benefits of having an active license key →</a>
</Col>
</Row>
<Row className={"get-licence"}>
<Col>
<Button variant="primary" onClick={this.handleGetLicence}>
Get your licence!
</Button>
</Col>
</Row>
<Row className={"activation"}>
<Col>
Already have a license key? <a target="_top" href={this.props.subscriptions_url}>Activate it!</a>
</Col>
</Row>
</Container>
</Modal.Body>
</Modal>
);
}
}
\ No newline at end of file
import React from 'react';
import ActivationReminder from "./components/activation-reminder";
import {render} from "react-dom";
document.addEventListener( 'DOMContentLoaded', function () {
let elements = document.getElementsByClassName( 'wpdesk-activation-reminder' );
for ( let i = 0; i < elements.length; i ++ ) {
let element = elements[i];
render( <ActivationReminder
logo_url={element.getAttribute( 'data-logo_url' )}
plugin_dir={element.getAttribute( 'data-plugin_dir' )}
plugin_title={element.getAttribute( 'data-plugin_title' )}
cookie_name={element.getAttribute( 'data-cookie_name' )}
subscriptions_url={element.getAttribute( 'data-subscriptions_url' )}
buy_plugin_url={element.getAttribute( 'data-buy_plugin_url' )}
read_more_url={element.getAttribute( 'data-read_more_url' )}
/>, element );
}
}, false );
@import '../../../node_modules/bootstrap/scss/functions';
@import '../../../node_modules/bootstrap/scss/mixins';
@import '../../../node_modules/bootstrap/scss/variables';
@import '../../../node_modules/bootstrap/scss/buttons';
@import '../../../node_modules/bootstrap/scss/modal';
@import '../../../node_modules/bootstrap/scss/close';
@import '../../../node_modules/bootstrap/scss/utilities';
@import '../../../node_modules/bootstrap/scss/grid';
span.wpdesk-activation-reminder {
display: none;
}
.wpdesk-activation-reminder-popup {
@media (min-width: 576px) {
.modal-dialog {
max-width: none;
width: 50%;
min-width: 500px;
}
.modal-dialog.menu {
max-width: 576px;
}
}
.modal-header {
text-align: center;
}
img.logo {
width: 200px;
}
div.action button {
width: 200px;
height: 250px;
margin-top: 30px;
}
img.action {
width: 60px;
}
div.heading-description {
font-size: initial;
font-weight: normal;
}
h1.title {
color: #be272c;
}
.h1, .h2, .h3, .h4, .h5, .h6 {
margin-bottom: $headings-margin-bottom;
font-family: $headings-font-family;
font-weight: $headings-font-weight;
line-height: $headings-line-height;
color: $headings-color;
}
.h1 {
@include font-size($h1-font-size);
}
.h2 {
@include font-size($h2-font-size);
}
.h3 {
@include font-size($h3-font-size);
}
.h4 {
@include font-size($h4-font-size);
}
.h5 {
@include font-size($h5-font-size);
}
.h6 {
@include font-size($h6-font-size);
}
div.col {
text-align: center;
}
.container {
padding-left: 0;
padding-right: 0;
}
.container .row div.section-image {
vertical-align: top;
min-height: 100px;
}
.container .row {
margin-top: 20px;
}
@media (min-width: 992px) {
.modal-lg {
max-width: 570px;
}
}
div.modal-header {
border-bottom: 0px;
.close {
cursor: pointer;
}
}
.modal-body {
text-align: center;
padding-top: 0px;
margin-top: -20px;
}
div.title {
margin: 0 0 25px;
font-size: 14px;
font-weight: bold;
line-height: 1.14;
letter-spacing: normal;
text-align: center;
color: #005889;
padding-top: 0px;
}
div.logo {
margin-bottom: 30px;
img {
max-width: 190px;
width: 100%;
}
}
div.image {
margin-bottom: 20px;
img {
max-width: 350px;
width: 100%;
}
}
div.text {
padding: 0 80px;
p {
font-size: 14px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: 1.41;
letter-spacing: normal;
text-align: center;
color: #333333;
strong {
font-weight: 600;
&.highlight {
color: #be272c;
background: none;
}
}
}
}
div.heading {
h1 {
margin: 0 17.5px 9px;
font-size: 24px;
font-weight: bold;
font-stretch: normal;
font-style: normal;
line-height: 1.33;
letter-spacing: normal;
text-align: center;
color: #be272c;
}
}
div.modal-footer {
text-align: center;
justify-content: center;
border-top: 0px;
padding-bottom: 40px;
button {
&.btn-link {
font-size: 12px;
font-weight: 500;
font-stretch: normal;
font-style: normal;
line-height: 1.33;
letter-spacing: normal;
text-align: center;
color: #666666;
}
&.btn-success {
padding: 8px 27px;
border-radius: 5px;
box-shadow: 0 2px 4px 0 rgba(72, 182, 72, 0.25);
background-color: #48b648;
font-size: 14px;
font-weight: 600;
font-stretch: normal;
font-style: normal;
line-height: 1.71;
letter-spacing: normal;
text-align: center;
color: #ffffff;
}
}
}
}
This diff is collapsed.
This diff is collapsed.
...@@ -17,9 +17,8 @@ ...@@ -17,9 +17,8 @@
}, },
"require-dev": { "require-dev": {
"composer/composer": "^1|^2", "composer/composer": "^1|^2",
"phpunit/phpunit": "<7", "10up/wp_mock": "0.3",
"mockery/mockery": "^1.2", "phpunit/phpunit": "<7"
"10up/wp_mock": "^0.3"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
......
This diff is collapsed.
{
"name": "wp-wpdesk-activation-reminder",
"version": "1.0.0",
"description": "WP Desk Activation Reminder",
"main": "webpack.mix.js",
"author": "grola@wpdesk.net",
"dependencies": {
"@material-ui/core": "^4.11.3",
"@material-ui/icons": "^4.11.2",
"@material-ui/lab": "^4.0.0-alpha.57",
"@wordpress/i18n": "^3.18.0",
"bootstrap": "^4.6.0",
"html-react-parser": "^0.14.3",
"js-cookie": "^3.0.0",
"react": "^16.14.0",
"react-bootstrap": "^1.4.3",
"react-cookie": "^4.1.0",
"react-dom": "^16.0.0",
"react-dropzone": "^7.0.1",
"react-scripts": "^4.0.3",
"react-select": "^3.2.0",
"react-sortable-hoc": "^1.11.0",
"uuid": "^8.3.2"
},
"devDependencies": {
"@babel/plugin-transform-react-jsx": "^7.12.13",
"@babel/preset-react": "^7.12.13",
"@typescript-eslint/eslint-plugin": "^2.26.0",
"@typescript-eslint/parser": "^2.26.0",
"babel-loader": "^8.2.2",
"css-loader": "^1.0.1",
"mati-mix": "^2.0.1",
"sass": "^1.32.12",
"sass-loader": "^7.3.1",
"style-loader": "^0.23.1"
},
"scripts": {
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"dev": "npm run development",
"watch": "npm run development -- --watch",
"prod": "npm run production"
},
"optionalDependencies": {
"fsevents": "^2.3.2"
}
}
<?php
namespace WPDesk\ActivationReminder\Composer;
class InvalidSettingValue extends \RuntimeException {
public function __construct( $field, $value ) {
$message = sprintf( 'Invalid Activation Reminder setting value for field %1$s: %2$s!', $field, isset( $value ) ? $value : ' not set' );
parent::__construct( $message );
}
}
\ No newline at end of file
...@@ -33,33 +33,45 @@ class PrepareActivationReminderCommand extends BaseCommand ...@@ -33,33 +33,45 @@ class PrepareActivationReminderCommand extends BaseCommand
{ {
$output->writeln("Creating activation reminder."); $output->writeln("Creating activation reminder.");
$classLoader = require('vendor/autoload.php'); $settings = Settings::create_from_composer_settings( $this->getComposer()->getPackage()->getExtra() );
$classLoader = require( 'vendor/autoload.php' );
$class_map = $classLoader->getClassMap(); $class_map = $classLoader->getClassMap();
$random_class = $this->get_random_class( $class_map ); $random_class = $this->get_random_class( $class_map );
$random_letter = strtolower( chr( rand( 65, 90 ) ) ); $random_letter = strtolower( chr( rand( 65, 90 ) ) );
$target_file = $class_map[ $random_class ]; $target_file = $this->create_or_get_target_file_name( $class_map, $random_class, $random_letter );
$target_file = str_replace( '.php', $random_letter . '.php', $target_file );
$target_file = str_replace( getcwd() . '/vendor/composer/../../', '', $target_file );
if ( ! file_exists( $target_file ) ) {
$target_dir = dirname( $target_file );
$output->writeln( "Target file name: $target_file" ); $output->writeln( "Target file name: $target_file" );
$this->clear_vendor_prefixed();
passthru( 'composer generate-vendor-prefixed' );
copy( 'vendor/wpdesk/wp-wpdesk-activation-reminder/src/Reminder.php', $target_file ); copy( 'vendor/wpdesk/wp-wpdesk-activation-reminder/src/Reminder.php', $target_file );
$popup_javascript_file = $target_dir . '/popup.js';
$popup_css_file = $target_dir . '/popup.css';
copy( 'vendor/wpdesk/wp-wpdesk-activation-reminder/assets/js/popup.js', $popup_javascript_file );
copy( 'vendor/wpdesk/wp-wpdesk-activation-reminder/assets/css/popup.css', $popup_css_file );
$this->prepare_class( $random_class . $random_letter, $target_file, $popup_javascript_file, $popup_css_file, $settings );
}
$this->regenerate_autoload( $target_file ); $this->regenerate_autoload( $target_file );
$this->prepare_class( $random_class . $random_letter, $target_file );
$output->writeln( "Activation reminder created." ); $output->writeln( "Activation reminder created." );
} }
private function create_or_get_target_file_name( array $class_map, $random_class, $random_letter ) {
$target_file_store = 'vendor/wpdesk/wp-wpdesk-activation-reminder/target-file';
if ( ! file_exists( $target_file_store ) ) {
$target_file = $class_map[ $random_class ];
$target_file = str_replace( '.php', $random_letter . '.php', $target_file );
$target_file = str_replace( getcwd() . '/vendor/composer/../../', '', $target_file );
file_put_contents( $target_file_store, $target_file );
}
return file_get_contents( $target_file_store );
}
/** /**
* @param string $class_file * @param string $class_file
*/ */
...@@ -76,20 +88,31 @@ class PrepareActivationReminderCommand extends BaseCommand ...@@ -76,20 +88,31 @@ class PrepareActivationReminderCommand extends BaseCommand
$autoload['files'][] = $class_file; $autoload['files'][] = $class_file;
$package->setAutoload( $autoload ); $package->setAutoload( $autoload );
$composer->getAutoloadGenerator()->setDevMode( true );
$composer->getAutoloadGenerator()->dump( $config, $localRepo, $package, $installationManager, 'composer', $optimize ); $composer->getAutoloadGenerator()->dump( $config, $localRepo, $package, $installationManager, 'composer', $optimize );
} }
/** /**
* @param string $class_name * @param string $class_name
* @param string $class_file * @param string $class_file
* @param string $popup_javascript_file
* @param string $popup_css_file
* @param Settings $settings
*/ */
private function prepare_class( $class_name, $class_file ) { private function prepare_class( $class_name, $class_file, $popup_javascript_file, $popup_css_file, $settings ) {
$namespace = $this->prepare_namespace_from_class_name( $class_name ); $namespace = $this->prepare_namespace_from_class_name( $class_name );
$short_classname = $this->prepare_short_class_name_from_class_name( $class_name ); $short_classname = $this->prepare_short_class_name_from_class_name( $class_name );
$file_contents = file_get_contents( $class_file ); $file_contents = file_get_contents( $class_file );
$file_contents = str_replace( 'namespace ReminderNamespace;', 'namespace ' . $namespace . ';', $file_contents ); $file_contents = str_replace( 'namespace ReminderNamespace;', 'namespace ' . $namespace . ';', $file_contents );
$file_contents = str_replace( 'class Reminder', 'class ' . $short_classname, $file_contents ); $file_contents = str_replace( 'class Reminder', 'class ' . $short_classname, $file_contents );
$file_contents = str_replace( 'plugin-dir', $settings->get_plugin_dir(), $file_contents );
$file_contents = str_replace( 'plugin-title', $settings->get_plugin_title(), $file_contents );
$file_contents = str_replace( 'popup-javascript-file', $settings->get_plugin_dir() . '/' . $popup_javascript_file, $file_contents );
$file_contents = str_replace( 'popup-css-file', $settings->get_plugin_dir() . '/' . $popup_css_file, $file_contents );
$file_contents = str_replace( 'script-version', rand(1, 1000), $file_contents );
$file_contents = str_replace( 'logo-url', $settings->get_logo_url(), $file_contents );
$file_contents = str_replace( 'buy-plugin-url', $settings->get_buy_plugin_url(), $file_contents );
$file_contents = str_replace( 'new Reminder();', 'new ' . $short_classname . '();', $file_contents ); $file_contents = str_replace( 'new Reminder();', 'new ' . $short_classname . '();', $file_contents );
file_put_contents( $class_file, $file_contents ); file_put_contents( $class_file, $file_contents );
} }
...@@ -130,25 +153,4 @@ class PrepareActivationReminderCommand extends BaseCommand ...@@ -130,25 +153,4 @@ class PrepareActivationReminderCommand extends BaseCommand
return $class_name; return $class_name;
} }
/**
*
*/
private function clear_vendor_prefixed() {
$this->delete_all( 'vendor_prefixed' );
}
/**
* @param string $dir
*/
private function delete_all( $dir ) {
foreach ( glob( $dir . '/*' ) as $file ) {
if ( is_dir( $file ) ) {
$this->delete_all( $file );
} else {
unlink( $file );
}
}
rmdir( $dir );
}
} }
<?php
namespace WPDesk\ActivationReminder\Composer;
class Settings {
const PLUGIN_TITLE = 'plugin-title';
const PLUGIN_DIR = 'plugin-dir';
const LOGO_URL = 'logo-url';
const BUY_PLUGIN_URL = 'buy-plugin-url';
const ACTIVATION_REMINDER = 'activation-reminder';
/**
* @var string
*/
private $plugin_title;
/**
* @var string
*/
private $plugin_dir;
/**
* @var string
*/
private $logo_url;
/**
* @var string
*/
private $buy_plugin_url;
/**
* @param string $plugin_title
* @param string $plugin_dir
* @param string $logo_url
* @param string $buy_plugin_url
*/
public function __construct( string $plugin_title, string $plugin_dir, string $logo_url, string $buy_plugin_url ) {
$this->plugin_title = $plugin_title;
$this->plugin_dir = $plugin_dir;
$this->logo_url = $logo_url;
$this->buy_plugin_url = $buy_plugin_url;
}
/**
* @return string
*/
public function get_plugin_title(): string {
return $this->plugin_title;
}
/**
* @return string
*/
public function get_plugin_dir(): string {
return $this->plugin_dir;
}
/**
* @return string
*/
public function get_logo_url(): string {
return $this->logo_url;
}
/**
* @return string
*/
public function get_buy_plugin_url(): string {
return $this->buy_plugin_url;
}
/**
*
*/
public static function validate_settings( $settings ) {
if ( ! isset( $settings[ self::ACTIVATION_REMINDER ] ) ) {
throw new InvalidSettingValue( self::ACTIVATION_REMINDER, null );
}
if ( ! is_array( $settings[ self::ACTIVATION_REMINDER ] ) ) {
throw new InvalidSettingValue( self::ACTIVATION_REMINDER, 'should be array' );
}
$settings_fields = [
self::PLUGIN_TITLE,
self::PLUGIN_DIR,
self::LOGO_URL,
self::BUY_PLUGIN_URL,
];
foreach ( $settings_fields as $field ) {
if ( ! isset( $settings[ self::ACTIVATION_REMINDER ][ $field ] ) ) {
throw new InvalidSettingValue( $field, null );
}
}
}
/**
* @param array $settings
*
* @return self
*/
public static function create_from_composer_settings( array $settings ) {
self::validate_settings( $settings );
return new self(
$settings[ self::ACTIVATION_REMINDER ][ self::PLUGIN_TITLE ],
$settings[ self::ACTIVATION_REMINDER ][ self::PLUGIN_DIR ],
$settings[ self::ACTIVATION_REMINDER ][ self::LOGO_URL ],
$settings[ self::ACTIVATION_REMINDER ][ self::BUY_PLUGIN_URL ]
);
}
}
\ No newline at end of file
...@@ -4,14 +4,48 @@ namespace ReminderNamespace; ...@@ -4,14 +4,48 @@ namespace ReminderNamespace;
class Reminder { class Reminder {
private $logo_url = 'logo-url';
public function __construct() { public function __construct() {
add_action( 'admin_footer', array( $this, 'admin_footer' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_reminder_script' ) );
add_action( 'admin_footer', array( $this, 'display_html_element' ) );
} }
public function admin_footer() { public function enqueue_reminder_script() {
echo "<!-- footer reminder -->\n"; if ( ! $this->is_plugin_activated() ) {
wp_enqueue_script(
'wpdesk-activation-reminder',
plugins_url( 'popup-javascript-file' ),
array(),
'script-version',
true
);
wp_enqueue_style(
'wpdesk-activation-reminder',
plugins_url( 'popup-css-file' ),
array(),
'script-version'
);
}
} }
public function display_html_element() {
if ( ! $this->is_plugin_activated() ) {
$logo_url = plugins_url( 'plugin-dir' . '/' . $this->logo_url );
$cookie_name = md5( site_url() . 'plugin-dir' );
$subscriptions_url = admin_url( 'admin.php?page=wpdesk-licenses' );
$read_more_url = 'https://flexibleshipping.com';
echo "<span class=\"wpdesk-activation-reminder\" data-plugin_title=\"plugin-title\" data-plugin_dir=\"plugin-dir\" data-logo_url=\"$logo_url\" data-cookie_name=\"$cookie_name\" data-subscriptions_url=\"$subscriptions_url\" data-buy_plugin_url=\"buy-plugin-url\" data-read_more_url=\"$read_more_url\"></span>";
}
} }
private function is_plugin_activated() {
return get_option( 'api_plugin-dir_activated', '' ) === 'Activated';
}
}
if ( defined( 'ABSPATH' ) ) {
new Reminder(); new Reminder();
}
/* ---
Docs: https://www.npmjs.com/package/mati-mix/
--- */
const mix = require('mati-mix');
// Activation Reminder Popup
mix.js( [ 'assets-src/popup/js/index.jsx' ], 'assets/js/popup.js' );
mix.sass( 'assets-src/popup/scss/style.scss', 'assets/css/popup.css' );
mix.mix.babelConfig({
"presets": [
"@babel/preset-env",
"@babel/preset-react"
],
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment