Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/assets/build/
/node_modules/
/.idea/
78 changes: 78 additions & 0 deletions assets/src/js/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
const postForm = null;
const singletonEnforcer = Symbol();

class PostForm {

constructor(enforcer) {
if (enforcer !== singletonEnforcer) {
throw new Error('Cannot construct new PostForm. Please use static instance');
}

this.init();
}

static get instance() {
if (!this[postForm]) {
this[postForm] = new PostForm(singletonEnforcer);
}
}

init() {
document.addEventListener('DOMContentLoaded', () => {
this.form = document.querySelector("#post_form");
this.form.addEventListener("submit", this.formSubmit, false);
}, false);
}

formSubmit = (e) => {
e.preventDefault();
window.tinyMCE.triggerSave();

this.btn = document.querySelector("#post_form button");
this.btn.setAttribute('disabled', true);
const formData = new FormData(e.target);
const formProps = Object.fromEntries(formData);

if (formProps.post_title && formProps.post_content) {
formData.append('action', 'propose_post_form');
formData.append('nonce', settings.nonce);
fetch(settings.url, {
method: 'POST',
body: formData,
})
.then(this.submitResolve)
.catch(this.submitReject)
} else {
this.addNotification(this.form, settings.msg, true);
}
}

submitResolve = (request) => {
request.json().then((response) =>{
if (response.success){
form.reset();
this.addNotification(this.form, response.data);
} else {
this.addNotification(this.form, response.data, true);
}
btn.removeAttribute('disabled');
});
}

submitReject = (error) => {
this.btn.removeAttribute('disabled');
this.addNotification(this.form, error.msg, true);
}

addNotification = (form, text, isError) => {
const ntf = document.createElement('p');
ntf.appendChild(document.createTextNode(text));
ntf.classList.add(isError ? 'el-post-form-error' : 'el-post-form-info');
form.appendChild(ntf);
setTimeout(() => {
ntf.remove();
}, 5000);
}
}

PostForm.instance;
62 changes: 62 additions & 0 deletions assets/src/sass/app.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
.el-post-form-widget {
font-size: 1rem;
line-height: 1.5;

.el-post-form-head, .el-post-form-desc {
text-align: center;
}

.el-post-form-label {
display: block;
margin-bottom: 1rem;

.el-post-form-label-text {
display: inline-block;
margin-bottom: .5rem;
}
}

.el-post-form-control {
display: block;
width: 100%;
padding: 12px 16px;
font-size: .875rem;
color: #212529;
background-color: #fff;
background-clip: padding-box;
border: 1px solid #ced4da;
appearance: none;
border-radius: 4px;
transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out;
:focus{
color: #212529;
background-color: #fff;
border-color: #86b7fe;
outline: 0;
box-shadow: 0 0 0 0.25rem rgb(13 110 253 / 25%);
}
}

.el-post-form-submit {
display: flex;
outline: none;
cursor: pointer;
line-height: 20px;
border-radius: 8px;
padding: 14px 24px;
margin-left: auto;
border: none;
transition: box-shadow 0.2s ease 0s, -ms-transform 0.1s ease 0s, -webkit-transform 0.1s ease 0s, transform 0.1s ease 0s;
background: linear-gradient(to right, rgb(230, 30, 77) 0%, rgb(227, 28, 95) 50%, rgb(215, 4, 102) 100%);
text-transform: uppercase;
color: #fff;
}

.el-post-form-error {
color: red;
}

.el-post-form-info {
color: blue;
}
}
172 changes: 172 additions & 0 deletions classes/post-form.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
<?php

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}

/**
* Class Post_Form
*/
class Post_Form {
/**
* Build template for client
*
* @param array{
* title: string,
* description: string,
* show_categories: string,
* not_registered: string,
* } $settings
*
* @since 1.0.0
* @access public
* @static
*
* @return string
*/
static function get_render_form( array $settings ): string {
$user = wp_get_current_user();
ob_start(); ?>
<section class="el-post-form-widget">
<h3 class="el-post-form-head"><?php echo esc_html($settings['title']); ?></h3>
<?php if ($user->exists()): ?>
<p class="el-post-form-desc"><?php echo esc_html($settings['description']); ?></p>
<form class="el-post-form" id="post_form">
<label class="el-post-form-label">
<span class="el-post-form-label-text">
<?php esc_html_e('Title', 'post-form-addon'); ?>
</span>
<input type="text" name="post_title" class="el-post-form-control" required>
</label>
<?php if ($settings['show_categories']):
$categories = get_categories(['hide_empty' => false]);
?>
<label class="el-post-form-label">
<span class="el-post-form-label-text">
<?php esc_html_e('Category', 'post-form-addon'); ?>
</span>
<select name="post_category" class="el-post-form-control">
<option selected disabled>
<?php esc_html_e('Select category', 'post-form-addon');?>
</option>
<?php foreach ($categories as $category): ?>
<option value="<?php echo esc_attr($category->term_id); ?>">
<?php echo esc_html($category->name);?>
</option>
<?php endforeach; ?>
</select>
</label>
<?php endif; ?>
<label class="el-post-form-label">
<span class="el-post-form-label-text">
<?php esc_html_e('Content', 'post-form-addon'); ?>
</span>
<?php wp_editor('', 'post_content', ['textarea_name' => 'post_content', 'teeny'=>false, 'media_buttons'=>false, 'quicktags' => false]); ?>
</label>
<button type="submit" class="el-post-form-submit">
<?php esc_html_e('Propose post', 'post-form-addon'); ?>
</button>
</form>
<?php else: ?>
<p class="el-post-form-desc"><?php echo $settings['not_registered'] ?></p>
<?php endif; ?>
</section>
<?php return ob_get_clean();
}

/**
* Build template for preview
*
* @since 1.0.0
* @access public
* @static
*
* @return string
*/
static function get_template_form(): string {
ob_start(); ?>
<section class="el-post-form-widget">
<h3 class="el-post-form-head">{{{ settings.title }}}</h3>
<p class="el-post-form-desc">{{{ settings.description }}}</p>
<form class="el-post-form" onsubmit="event.preventDefault();">
<label class="el-post-form-label">
<span class="el-post-form-label-text">
<?php esc_html_e('Title', 'post-form-addon'); ?>
</span>
<input type="text" name="post_title" class="el-post-form-control">
</label>
<# if ( settings.show_categories ) { #>
<label class="el-post-form-label">
<span class="el-post-form-label-text">
<?php esc_html_e('Category', 'post-form-addon'); ?>
</span>
<select name="post_category" class="el-post-form-control">
<option selected disabled>
<?php esc_html_e('Select category', 'post-form-addon');?>
</option>
<option value="0">
<?php esc_html_e('Category', 'post-form-addon');?>
</option>
</select>
</label>
<# } #>
<label class="el-post-form-label">
<span class="el-post-form-label-text">
<?php esc_html_e('Content', 'post-form-addon'); ?>
</span>

<textarea name="post_content" class="el-post-form-control" rows="25"></textarea>
</label>
<button type="submit" class="el-post-form-submit">
<?php esc_html_e('Propose post', 'post-form-addon'); ?>
</button>
</form>
</section>
<?php return ob_get_clean();
}

/**
* Create pending post from submitted data
*
* @since 1.0.0
* @access public
* @static
*
* @return void
*/
static function submit_form(): void {
$pass_check = wp_verify_nonce($_POST['nonce'], 'ajax-nonce') && $_POST['post_title'] && $_POST['post_content'];

if ($pass_check) {
$post_data = array(
'post_title' => sanitize_text_field( $_POST['post_title'] ),
'post_content' => $_POST['post_content'],
'post_status' => 'pending',
'post_author' => 1,
'post_category' => [$_POST['post_category']]
);

wp_insert_post( $post_data );
}
self::send_response($pass_check);
}

/**
* Send response for client
*
* @param bool $pass_check
*
* @since 1.0.0
* @access public
* @static
*
* @return void
*/
static function send_response( bool $pass_check ) {
if ( $pass_check ) {
wp_send_json_success( esc_html__( 'Thanks for proposing a new post!', 'post-form-addon' ) );
} else {
wp_send_json_error( esc_html__( 'Something went wrong! Try again later...', 'post-form-addon' ) );
}
}
}
30 changes: 30 additions & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const gulp = require('gulp')
const sass = require('gulp-sass')(require('sass'));
const concat = require('gulp-concat');
const uglify = require('gulp-uglify');
const cleanCss = require('gulp-clean-css');

gulp.task('sass', () => {
return gulp
.src('./assets/src/sass/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(concat('app.min.css'))
.pipe(cleanCss())
.pipe(gulp.dest('./assets/build/css'))
})

gulp.task('js', function () {
return gulp
.src('./assets/src/js/*.js')
.pipe(concat('app.min.js'))
.pipe(uglify())
.pipe(gulp.dest('./assets/build/js'));
});

gulp.task('watch', () => {
gulp.watch('./assets/src/sass/*.scss', gulp.series(['sass']));
gulp.watch('./assets/src/js/*.js', gulp.series(['js']));
});

gulp.task('build', gulp.parallel('sass', 'js'));

Loading