43,861 changes: 2 additions & 43,859 deletions assets/js/build/dashboard.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion assets/js/build/dashboard.min.js

Large diffs are not rendered by default.

18,618 changes: 2 additions & 18,616 deletions assets/js/build/exclude.js

Large diffs are not rendered by default.

16,797 changes: 2 additions & 16,795 deletions assets/js/build/publish_now.js

Large diffs are not rendered by default.

11 changes: 8 additions & 3 deletions includes/admin/class-rop-admin.php
Expand Up @@ -300,8 +300,8 @@ public function enqueue_scripts() {
return;
}
wp_enqueue_media();
wp_register_script( $this->plugin_name . '-dashboard', ROP_LITE_URL . 'assets/js/build/dashboard' . ( ( ROP_DEBUG ) ? '' : '.min' ) . '.js', array(), ( ROP_DEBUG ) ? time() : $this->version, false );
wp_register_script( $this->plugin_name . '-exclude', ROP_LITE_URL . 'assets/js/build/exclude' . ( ( ROP_DEBUG ) ? '' : '.min' ) . '.js', array(), ( ROP_DEBUG ) ? time() : $this->version, false );
wp_register_script( $this->plugin_name . '-dashboard', ROP_LITE_URL . 'assets/js/build/dashboard.js', array(), ( ROP_DEBUG ) ? time() : $this->version, false );
wp_register_script( $this->plugin_name . '-exclude', ROP_LITE_URL . 'assets/js/build/exclude.js', array(), ( ROP_DEBUG ) ? time() : $this->version, false );

$array_nonce = array(
'root' => esc_url_raw( rest_url( '/tweet-old-post/v8/api/' ) ),
Expand Down Expand Up @@ -374,14 +374,19 @@ public function enqueue_scripts() {

if ( 'publish_now' === $page ) {
$array_nonce['publish_now'] = apply_filters( 'rop_publish_now_attributes', $array_nonce['publish_now'] );
wp_register_script( $this->plugin_name . '-publish_now', ROP_LITE_URL . 'assets/js/build/publish_now' . ( ( ROP_DEBUG ) ? '' : '.min' ) . '.js', array(), ( ROP_DEBUG ) ? time() : $this->version, false );
wp_register_script( $this->plugin_name . '-publish_now', ROP_LITE_URL . 'assets/js/build/publish_now.js', array(), ( ROP_DEBUG ) ? time() : $this->version, false );
}

wp_localize_script( $this->plugin_name . '-' . $page, 'ropApiSettings', $array_nonce );
wp_localize_script( $this->plugin_name . '-' . $page, 'ROP_ASSETS_URL', array( ROP_LITE_URL . 'assets/' ) );
wp_localize_script( $this->plugin_name . '-' . $page, 'ropAuthAppData', $rop_auth_app_data );
wp_enqueue_script( $this->plugin_name . '-' . $page );

// Deregister the LMS vue-libs script for the ROP dashboard and exclude the page.
if ( function_exists( 'learn_press_get_current_version' ) && wp_script_is( $this->plugin_name . '-' . $page ) ) {
wp_deregister_script( 'vue-libs' );
}

}

/**
Expand Down
6 changes: 5 additions & 1 deletion includes/class-rop-i18n.php
Expand Up @@ -72,13 +72,17 @@ public function load_service_locals( $services ) {
* @return array|mixed|string String localized
*/
public static function get_labels( $key = '' ) {
$tw_new_name = __( 'X (ex Twitter)', 'tweet-old-post' );
$labels = array(
'accounts' => array(
'menu_item' => __( 'Accounts', 'tweet-old-post' ),
'service_popup_title' => __( 'Service Credentials', 'tweet-old-post' ),
'show_advance_config' => __( 'Use your own keys', 'tweet-old-post' ),
'show_own_keys_config' => __( 'Use my own API keys', 'tweet-old-post' ),
'tw_app_signin_tooltip' => sprintf( __( 'Due to the %1$s changes in network limits, we cannot guarantee stable sharing using this mode. We recommend using your own API keys.', 'tweet-old-post' ), $tw_new_name ),
'tw_new_name' => $tw_new_name,
'fb_app_signin_btn' => __( 'Sign in to Facebook', 'tweet-old-post' ),
'tw_app_signin_btn' => __( 'Sign in to Twitter', 'tweet-old-post' ),
'tw_app_signin_btn' => __( 'Sign in to X', 'tweet-old-post' ),
'li_app_signin_btn' => __( 'Sign in to LinkedIn', 'tweet-old-post' ),
'tumblr_app_signin_btn' => __( 'Sign in to Tumblr', 'tweet-old-post' ),
'gmb_app_signin_btn' => __( 'Sign in to Google My Business', 'tweet-old-post' ),
Expand Down
2 changes: 1 addition & 1 deletion includes/class-rop.php
Expand Up @@ -68,7 +68,7 @@ class Rop {
public function __construct() {

$this->plugin_name = 'rop';
$this->version = '9.0.21';
$this->version = '9.0.22';

$this->load_dependencies();
$this->set_locale();
Expand Down
59,024 changes: 39,981 additions & 19,043 deletions package-lock.json

Large diffs are not rendered by default.

167 changes: 88 additions & 79 deletions package.json
@@ -1,81 +1,90 @@
{
"name": "tweet-old-post",
"version": "9.0.21",
"description": "Tweet Old Posts plugin for WordPress.",
"repository": {
"type": "git",
"url": "git+https://github.com/Codeinwp/tweet-old-post.git"
},
"keywords": [
"wordpress-plugin"
],
"category": "plugins",
"textdomain": "tweet-old-post",
"author": "ThemeIsle <friends@themeisle.com>",
"license": "GPL-2.0+",
"bugs": {
"url": "https://github.com/Codeinwp/tweet-old-post/issues"
},
"pot": {
"reportmsgidbugsto": "https://github.com/Codeinwp/tweet-old-post/issues",
"languageteam": "Themeisle Translate <friends@themeisle.com>",
"lasttranslator": "Themeisle Translate Team <friends@themeisle.com>"
},
"scripts": {
"dev": "cross-env WEBPACK_ENV=dev webpack --progress --colors --watch",
"build": "cross-env WEBPACK_ENV=production webpack",
"dist": "bash bin/dist.sh",
"release": "semantic-release --debug"
},
"devDependencies": {
"babel-core": "^6.26.0",
"babel-eslint": "^8.0.1",
"babel-loader": "^7.1.4",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.6.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-stage-2": "^6.24.1",
"babel-runtime": "^6.26.0",
"cross-env": "^5.1.6",
"css-loader": "^0.23.0",
"eslint": "^4.19.1",
"eslint-config-standard": "^10.2.1",
"eslint-loader": "^1.9.0",
"eslint-plugin-html": "^3.2.2",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-node": "^5.2.0",
"eslint-plugin-promise": "^3.5.0",
"eslint-plugin-standard": "^3.0.1",
"eslint-plugin-vue": "^4.4.0",
"file-loader": "^0.11.2",
"html-loader": "^0.5.1",
"style-loader": "^0.13.0",
"stylelint": "^8.2.0",
"stylelint-config-recommended": "^1.0.0",
"vue-hot-reload-api": "^2.1.1",
"vue-html-loader": "^1.0.0",
"vue-loader": "^7.5.3",
"webpack": "^3.12.0",
"semantic-release": "^17.4.3",
"@semantic-release/changelog": "^5.0.1",
"@semantic-release/exec": "^5.0.0",
"replace-in-file": "^6.2.0",
"grunt": "^1.4.0",
"grunt-version": "^2.0.0",
"grunt-wp-readme-to-markdown": "^2.0.1",
"conventional-changelog-simple-preset": "^1.0.15",
"@semantic-release/git": "^9.0.0"
},
"dependencies": {
"moment-duration-format": "^2.2.2",
"npm": "^6.1.0",
"vue": "^2.4.2",
"vue-clickaway": "^2.1.0",
"vue-js-toggle-button": "^1.3.3",
"vue-moment": "^3.2.0",
"vue-resource": "^1.3.4",
"vue2-timepicker": "^0.1.4",
"vuejs-logger": "1.3.4",
"vuex": "^2.4.0"
}
"name": "tweet-old-post",
"version": "9.0.22",
"description": "Tweet Old Posts plugin for WordPress.",
"repository": {
"type": "git",
"url": "git+https://github.com/Codeinwp/tweet-old-post.git"
},
"keywords": [
"wordpress-plugin"
],
"category": "plugins",
"textdomain": "tweet-old-post",
"author": "ThemeIsle <friends@themeisle.com>",
"license": "GPL-2.0+",
"bugs": {
"url": "https://github.com/Codeinwp/tweet-old-post/issues"
},
"pot": {
"reportmsgidbugsto": "https://github.com/Codeinwp/tweet-old-post/issues",
"languageteam": "Themeisle Translate <friends@themeisle.com>",
"lasttranslator": "Themeisle Translate Team <friends@themeisle.com>"
},
"scripts": {
"dev": "webpack --progress --watch --mode development",
"build": "webpack --mode production",
"build-dev": "webpack --mode development",
"dist": "bash bin/dist.sh",
"release": "semantic-release --debug",
"lint": "wp-scripts lint-js ./vue -c .eslintrc.js --ext .js,.vue",
"format": "wp-scripts lint-js ./vue -c .eslintrc.js --ext .js,.vue --fix",
"wp-env": "wp-env",
"test:e2e:playwright": "wp-scripts test-playwright --config tests/e2e/playwright.config.js",
"test:e2e:playwright:ui": "wp-scripts test-playwright --config tests/e2e/playwright.config.js --ui"
},
"devDependencies": {
"@babel/core": "^7.23.3",
"@babel/preset-env": "^7.23.3",
"@playwright/test": "^1.40.0",
"@semantic-release/changelog": "^5.0.1",
"@semantic-release/exec": "^5.0.0",
"@semantic-release/git": "^9.0.0",
"@wordpress/e2e-test-utils-playwright": "^0.14.0",
"@wordpress/env": "^8.12.0",
"@wordpress/scripts": "^26.17.0",
"babel-eslint": "^8.0.1",
"babel-loader": "^9.1.3",
"conventional-changelog-simple-preset": "^1.0.15",
"core-js": "^3.33.3",
"cross-env": "^5.1.6",
"css-loader": "^6.8.1",
"eslint-config-standard": "^17.1.0",
"eslint-plugin-html": "^7.1.0",
"eslint-plugin-import": "^2.29.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-standard": "^5.0.0",
"eslint-plugin-vue": "^9.18.1",
"file-loader": "^6.2.0",
"grunt": "^1.4.0",
"grunt-version": "^2.0.0",
"grunt-wp-readme-to-markdown": "^2.0.1",
"html-loader": "^4.2.0",
"replace-in-file": "^6.2.0",
"semantic-release": "^17.4.3",
"style-loader": "^0.13.2",
"stylelint": "^8.2.0",
"stylelint-config-recommended": "^1.0.0",
"terser-webpack-plugin": "^5.3.9",
"vue-hot-reload-api": "^2.3.4",
"vue-html-loader": "^1.2.4",
"vue-loader": "^15.11.1",
"webpack": "^5.89.0",
"webpack-cli": "^5.1.4"
},
"dependencies": {
"moment-duration-format": "^2.2.2",
"npm": "^6.1.0",
"sass": "^1.69.5",
"sass-loader": "^13.3.2",
"vue": "^2.7.15",
"vue-clickaway": "^2.1.0",
"vue-js-toggle-button": "^1.3.3",
"vue-moment": "^3.2.0",
"vue-resource": "^1.3.4",
"vue2-timepicker": "^0.1.4",
"vuejs-logger": "1.3.4",
"vuex": "^3.6.2"
}
}
12 changes: 11 additions & 1 deletion readme.txt
Expand Up @@ -2,7 +2,7 @@
Contributors: codeinwp,marius2012,marius_codeinwp,hardeepasrani,Madalin_Themeisle, rsocial, uriahs-victor
Tags: share to social media, auto publish, auto post, social media scheduling, social media auto posting, social media marketing, social media automation, social media sharing
Requires at least: 4.7
Tested up to: 6.3
Tested up to: 6.4
Requires PHP: 7.4
Stable tag: trunk

Expand Down Expand Up @@ -301,6 +301,16 @@ http://revive.social/plugins/revive-old-post

== Changelog ==

##### [Version 9.0.22](https://github.com/Codeinwp/tweet-old-post/compare/v9.0.21...v9.0.22) (2023-12-22)

### Fixes
- Changed the default usage of X (ex Twitter) to own API keys
- Updated the JS pipeline
- Fixed compatibility issue with the LearnPress plugin




##### [Version 9.0.21](https://github.com/Codeinwp/tweet-old-post/compare/v9.0.20...v9.0.21) (2023-09-27)

- Implemented post-sharing limit API to prevent sharing errors
Expand Down
18 changes: 18 additions & 0 deletions tests/e2e/README.md
@@ -0,0 +1,18 @@
# E2E Testing

## Config

The configuration is similar to Gutenberg Project. Check [this](https://github.com/WordPress/gutenberg/tree/trunk/test/e2e) repo for more details.

To start creating new tests you need to do the following:

1. Run `npm run wp-env start`. This will create a Docker test instance. The file `.wp-env.json` is used to override some settings. [Read more here](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-env/). [Changelog to check new features.](https://github.com/WordPress/gutenberg/blob/b9f2514f9e37099f6481046c4ba20fa46c2d7171/packages/env/CHANGELOG.md)
2. Run `npx install playwright`. This will the install the browser packages for Playwright to use it.
3. Run `npm run test:e2e:playwright:ui`. This will lunch Playwright in UI mode. _Recommended when developing_. You can use `npm run test:e2e:playwright` to run without UI.

## Useful Resources

- [Playwright Tests Docs](https://playwright.dev/docs/writing-tests)
- [WordPress E2E Repo](https://github.com/WordPress/wordpress-develop/tree/trunk/tests/e2e)
- [Gutenberg E2E Repo](https://github.com/WordPress/gutenberg/tree/trunk/test/e2e)
- [Otter E2E Repo](https://github.com/Codeinwp/otter-blocks/tree/master/src/blocks/test/e2e)
83 changes: 83 additions & 0 deletions tests/e2e/config/flasky-tests-reporter.js
@@ -0,0 +1,83 @@
/**
* A **flaky** test is defined as a test which passed after auto-retrying.
* - By default, all tests run once if they pass.
* - If a test fails, it will automatically re-run at most 2 times.
* - If it pass after retrying (below 2 times), then it's marked as **flaky**
* but displayed as **passed** in the original test suite.
* - If it fail all 3 times, then it's a **failed** test.
*/
/**
* External dependencies
*/
import fs from 'fs';
import filenamify from 'filenamify';

// Remove "steps" to prevent stringify circular structure.
function formatTestResult( testResult ) {
const result = { ...testResult, steps: undefined };
delete result.steps;
return result;
}

class FlakyTestsReporter {
failingTestCaseResults = new Map();

onBegin() {
try {
fs.mkdirSync( 'flaky-tests' );
} catch ( err ) {
if (
err instanceof Error &&
( err ).code === 'EEXIST'
) {
// Ignore the error if the directory already exists.
} else {
throw err;
}
}
}

onTestEnd( test, testCaseResult ) {
const testPath = test.location.file;
const testTitle = test.title;

switch ( test.outcome() ) {
case 'unexpected': {
if (!this.failingTestCaseResults.has(testTitle)) {
this.failingTestCaseResults.set(testTitle, []);
}
const failingResults = this.failingTestCaseResults.get(testTitle);
if (failingResults) {
failingResults.push(formatTestResult(testCaseResult));
}
break;
}
case 'flaky': {
fs.writeFileSync(
`flaky-tests/${ filenamify( testTitle ) }.json`,
JSON.stringify( {
version: 1,
runner: '@playwright/test',
title: testTitle,
path: testPath,
results: this.failingTestCaseResults.get( testTitle ),
} ),
'utf-8'
);
break;
}
default:
break;
}
}

onEnd() {
this.failingTestCaseResults.clear();
}

printsToStdio() {
return false;
}
}

module.exports = FlakyTestsReporter;
39 changes: 39 additions & 0 deletions tests/e2e/config/global-setup.js
@@ -0,0 +1,39 @@
/**
* External dependencies
*/
import { request } from '@playwright/test';

/**
* WordPress dependencies
*/
import { RequestUtils } from '@wordpress/e2e-test-utils-playwright';

async function globalSetup( config ) {
const { storageState, baseURL } = config.projects[ 0 ].use;
const storageStatePath =
typeof storageState === 'string' ? storageState : undefined;

const requestContext = await request.newContext( {
baseURL,
} );

const requestUtils = new RequestUtils( requestContext, {
storageStatePath,
} );

console.log(`----------> BaseURL: ${baseURL}`);

// Authenticate and save the storageState to disk.
await requestUtils.setupRest();

// Reset the test environment before running the tests.
await Promise.all( [
requestUtils.deleteAllPosts(),
requestUtils.deleteAllBlocks(),
requestUtils.resetPreferences(),
] );

await requestContext.dispose();
}

export default globalSetup;
31 changes: 31 additions & 0 deletions tests/e2e/playwright.config.js
@@ -0,0 +1,31 @@
/**
* External dependencies
*/
import os from 'os';
import { fileURLToPath } from 'url';
import { defineConfig, devices } from '@playwright/test';

/**
* WordPress dependencies
*/
const baseConfig = require( '@wordpress/scripts/config/playwright.config' );

const config = defineConfig( {
...baseConfig,
reporter: process.env.CI
? [ [ 'github' ], [ './config/flaky-tests-reporter.js' ] ]
: 'list',
workers: 1,
globalSetup: fileURLToPath(
new URL( './config/global-setup.js', 'file:' + __filename ).href
),
projects: [
{
name: 'chromium',
use: { ...devices[ 'Desktop Chrome' ] },
grepInvert: /-chromium/,
},
],
} );

export default config;
23 changes: 23 additions & 0 deletions tests/e2e/specs/dashboard/accounts.spec.js
@@ -0,0 +1,23 @@
/**
* WordPress dependencies
*/
import { test, expect } from '@wordpress/e2e-test-utils-playwright';

test.describe( 'Accounts', () => {

test.beforeEach( async ( { page, admin } ) => {
await admin.visitAdminPage( '/admin.php?page=TweetOldPost' );

// Wait for the accounts tab to load.
await page.waitForSelector( '.tab-view[type="accounts"]' );
} );

test( 'Social Accounts', async ( { admin, page }) => {
await expect( page.getByRole('button', { name: 'Facebook' }) ).toBeVisible();
await expect( page.getByRole('button', { name: 'Twitter' }) ).toBeVisible();
await expect( page.getByRole('button', { name: 'LinkedIn' }) ).toBeVisible();
await expect( page.getByRole('button', { name: 'Tumblr' }) ).toBeVisible();
await expect( page.getByRole('button', { name: 'GMB' }) ).toBeVisible();
await expect( page.getByRole('button', { name: 'Vk' }) ).toBeVisible();
} );
} );
36 changes: 36 additions & 0 deletions tests/e2e/specs/dashboard/general-settings.spec.js
@@ -0,0 +1,36 @@
/**
* WordPress dependencies
*/
import { test, expect } from '@wordpress/e2e-test-utils-playwright';

test.describe( 'Accounts', () => {

test.beforeEach( async ( { page, admin } ) => {
await admin.visitAdminPage( '/admin.php?page=TweetOldPost' );

// Wait for the accounts tab to load.
await page.waitForSelector( '.tab-view[type="accounts"]' );

await page.getByText('General Settings').click();
} );

test( 'Can change inputs', async ( { page }) => {

/**
* Check Minimum Interval Between Shares input field.
*/
await page.waitForSelector( '#default_interval' );
await page.fill( '#default_interval', '5' );

await expect( page.getByText('Minimum Interval Between') ).toBeVisible();
await expect( page.$eval('#default_interval', el => el.value) ).resolves.toBe('5');

/**
* Check Share More Than Once toggle.
*/
await page.locator('#share_more_than_once').first().uncheck();

await expect( page.getByText('Share More Than Once?') ).toBeVisible();
await expect( page.locator('#share_more_than_once').first().isChecked() ).resolves.toBe(false);
} );
} );
4 changes: 2 additions & 2 deletions tweet-old-post.php
Expand Up @@ -16,7 +16,7 @@
* Plugin Name: Revive Old Posts
* Plugin URI: https://revive.social/
* Description: WordPress plugin that helps you to keeps your old posts alive by sharing them and driving more traffic to them from twitter/facebook or linkedin. It also helps you to promote your content. You can set time and no of posts to share to drive more traffic.For questions, comments, or feature requests, <a href="http://revive.social/support/?utm_source=plugindesc&utm_medium=announce&utm_campaign=top">contact </a> us!
* Version: 9.0.21
* Version: 9.0.22
* Author: revive.social
* Author URI: https://revive.social/
* Requires at least: 4.7
Expand Down Expand Up @@ -162,7 +162,7 @@ function run_rop() {
define( 'ROP_CRON_ALTERNATIVE', $use_remote_cron );

define( 'ROP_PRO_URL', 'http://revive.social/plugins/revive-old-post/' );
define( 'ROP_LITE_VERSION', '9.0.21' );
define( 'ROP_LITE_VERSION', '9.0.22' );
define( 'ROP_LITE_BASE_FILE', __FILE__ );
$debug = false;
if ( function_exists( 'wp_get_environment_type' ) ) {
Expand Down
3 changes: 3 additions & 0 deletions vue/src/models/rop_store.js
Expand Up @@ -28,6 +28,9 @@ Vue.use(Vuex);
Vue.use(VueResource);
Vue.use(VueLogger, logOptions);


// In the futures, this should be replaced with Pina library.
// For new features that do not need the existing store data, use the new Pina.
export default new Vuex.Store({
state: {
page: {
Expand Down
266 changes: 164 additions & 102 deletions vue/src/vue-elements/account-schedule.vue
@@ -1,89 +1,147 @@
<template>
<div :class="'rop-control-container-'+ ( license > 1 && license !== 7 ) + ' rop-schedule-tab-container'">
<div :class="'rop-control-container-'+ ( license > 1 && license !== 7 ) + ' rop-schedule-tab-container'">
<div class="columns py-2 rop-control">
<div class="column col-6 col-sm-12 vertical-align">
<b>{{ labels.schedule_type_title }}</b>
<p class="text-gray">
{{ labels.schedule_type_desc }}
</p>
</div>
<div class="column col-6 col-sm-12 vertical-align">
<div class="form-group">
<select
v-model="schedule.type"
class="form-select"
>
<option value="recurring">
{{ labels.schedule_type_option_rec }}
</option>
<option value="fixed">
{{ labels.schedule_type_option_fix }}
</option>
</select>
</div>
</div>
</div>

<div class="columns py-2 rop-control">
<div class="column col-6 col-sm-12 vertical-align">
<b>{{labels.schedule_type_title}}</b>
<p class="text-gray">{{labels.schedule_type_desc}}</p>
</div>
<div class="column col-6 col-sm-12 vertical-align">
<div class="form-group">
<select class="form-select" v-model="schedule.type">
<option value="recurring">{{labels.schedule_type_option_rec}}</option>
<option value="fixed">{{labels.schedule_type_option_fix}}</option>
</select>
</div>
</div>
</div>
<!-- Fixed Schedule Days -->
<div
v-if="schedule.type === 'fixed'"
class="columns py-2 rop-control"
>
<div class="column col-6 col-sm-12 vertical-align">
<b>{{ labels.schedule_fixed_days_title }}</b>
<p class="text-gray">
{{ labels.schedule_fixed_days_desc }}
</p>
</div>
<div class="column col-6 col-sm-12 vertical-align">
<div class="form-group input-group">
<button-checkbox
v-for="( data, label ) in daysObject"
:key="label"
:value="data.value"
:label="label"
:checked="data.checked"
@add-day="addDay"
@rmv-day="rmvDay"
/>
</div>
</div>
</div>

<!-- Fixed Schedule Days -->
<div class="columns py-2 rop-control" v-if="schedule.type === 'fixed'">
<div class="column col-6 col-sm-12 vertical-align">
<b>{{labels.schedule_fixed_days_title}}</b>
<p class="text-gray">{{labels.schedule_fixed_days_desc}}</p>
</div>
<div class="column col-6 col-sm-12 vertical-align">
<div class="form-group input-group">
<button-checkbox v-for="( data, label ) in daysObject" :key="label" :value="data.value"
:label="label" :checked="data.checked" @add-day="addDay" @rmv-day="rmvDay"
></button-checkbox>
</div>
</div>
</div>
<!-- Fixed Schedule time -->
<div
v-if="schedule.type === 'fixed'"
class="columns py-2 rop-control"
>
<div class="column col-6 col-sm-12 vertical-align">
<b>{{ labels.schedule_fixed_time_title }}</b>
<p class="text-gray">
{{ labels.schedule_fixed_time_desc }}
</p>
</div>
<div class="column col-6 col-sm-12 vertical-align">
<div class="form-group">
<div
v-for="( time, index ) in schedule.interval_f.time"
:key="index"
class="input-group"
>
<vue-timepicker
:minute-interval="generalSettings.minute_interval"
class="timepicker-style-fix"
:value="getTime( index )"
hide-clear-button
@change="syncTime( $event, index )"
/>
<button
v-if="schedule.interval_f.time.length > 1"
class="btn btn-danger input-group-btn"
@click="rmvTime( index )"
>
<i class="fa fa-fw fa-minus" />
</button>
<button
v-if="index == schedule.interval_f.time.length - 1"
class="btn btn-success input-group-btn"
@click="addTime()"
>
<i class="fa fa-fw fa-plus" />
</button>
</div>
</div>
</div>
</div>

<!-- Fixed Schedule time -->
<div class="columns py-2 rop-control" v-if="schedule.type === 'fixed'">
<div class="column col-6 col-sm-12 vertical-align">
<b>{{labels.schedule_fixed_time_title}}</b>
<p class="text-gray">{{labels.schedule_fixed_time_desc}}</p>
</div>
<div class="column col-6 col-sm-12 vertical-align">
<div class="form-group">
<div class="input-group" v-for="( time, index ) in schedule.interval_f.time">
<vue-timepicker :minute-interval="generalSettings.minute_interval" class="timepicker-style-fix" :value="getTime( index )"
@change="syncTime( $event, index )" hide-clear-button
></vue-timepicker>
<button class="btn btn-danger input-group-btn" v-if="schedule.interval_f.time.length > 1"
@click="rmvTime( index )">
<i class="fa fa-fw fa-minus"></i>
</button>
<button class="btn btn-success input-group-btn"
v-if="index == schedule.interval_f.time.length - 1" @click="addTime()"
>
<i class="fa fa-fw fa-plus"></i>
</button>
</div>
</div>
</div>
</div>
<!-- Current time -->
<div
v-if="schedule.type === 'fixed'"
class="column col-6 col-sm-12 vertical-align float-right"
>
<div
v-if="formatedDate"
class="toast rop-current-time text-center"
>
{{ labels.time_now }}: {{ formatedDate }}
</div>
</div>

<!-- Current time -->
<div class="column col-6 col-sm-12 vertical-align float-right" v-if="schedule.type === 'fixed'">
<div class="toast rop-current-time text-center" v-if="formatedDate">
{{labels.time_now}}: {{ formatedDate }}
</div>
</div>
<div
v-else
class="columns py-2 rop-control"
>
<div class="column col-6 col-sm-12 vertical-align">
<b>{{ labels.schedule_rec_title }}</b>
<p class="text-gray">
{{ labels.schedule_rec_desc }}
</p>
</div>
<div class="column col-6 col-sm-12 vertical-align">
<div class="form-group">
<counter-input
id="interval_r"
:value.sync="schedule.interval_r"
:min-val="generalSettings.min_interval"
:step-val="generalSettings.step_interval"
/>
</div>
</div>
</div>

<div class="columns py-2 rop-control" v-else>
<div class="column col-6 col-sm-12 vertical-align">
<b>{{labels.schedule_rec_title}}</b>
<p class="text-gray">{{labels.schedule_rec_desc}}</p>
</div>
<div class="column col-6 col-sm-12 vertical-align">
<div class="form-group">
<counter-input id="interval_r" :value.sync="schedule.interval_r" :min-val="generalSettings.min_interval" :step-val="generalSettings.step_interval"></counter-input>
</div>
</div>
</div>

<!-- Upsell -->
<div class="columns py-2" v-if="license < 2 || license === 7">
<div class="column text-center">
<p class="upsell"><i class="fa fa-lock"></i> {{labels.schedule_upsell}}</p>
</div>
</div>
<span class="divider"></span>
</div>
<!-- Upsell -->
<div
v-if="license < 2 || license === 7"
class="columns py-2"
>
<div class="column text-center">
<p class="upsell">
<i class="fa fa-lock" /> {{ labels.schedule_upsell }}
</p>
</div>
</div>
<span class="divider" />
</div>
</template>

<script>
Expand All @@ -92,8 +150,13 @@
import CounterInput from './reusables/counter-input.vue'
import moment from 'moment'
module.exports = {
name: 'account-schedule',
export default {
name: 'AccountSchedule',
components: {
ButtonCheckbox,
CounterInput,
VueTimepicker
},
props: ['account_id', 'license'],
data: function () {
return {
Expand Down Expand Up @@ -219,44 +282,43 @@
this.schedule.interval_f.week_days.splice(index, 1)
}
},
},
components: {
ButtonCheckbox,
CounterInput,
VueTimepicker
}
}
</script>
<style scoped>
<style lang="scss" scoped>
.rop-control-container-false {
cursor:not-allowed !important;
}
#rop_core .panel-body .text-gray {
margin: 0;
line-height: normal;
}
#rop_core {
.panel-body .text-gray {
margin: 0;
line-height: normal;
}
.input-group .input-group-addon {
padding: 3px 5px;
}
}
b {
margin-bottom: 5px;
display: block;
}
#rop_core .input-group .input-group-addon {
padding: 3px 5px;
}
.time-picker {
margin-bottom: 10px;
}
@media ( max-width: 600px ) {
#rop_core .panel-body .text-gray {
margin-bottom: 10px;
}
#rop_core {
.panel-body .text-gray {
margin-bottom: 10px;
}
#rop_core .text-right {
text-align: left;
}
.text-right {
text-align: left;
}
}
}
</style>
197 changes: 121 additions & 76 deletions vue/src/vue-elements/accounts-selector-panel.vue
@@ -1,58 +1,107 @@
<template>
<div class="tab-view">
<div class="panel-body">
<div class="d-inline-block mt-2 column col-12">
<p class="text-gray"><i class="fa fa-info-circle"></i> <span v-html="labels.accounts_selector"></span>
</p>
</div>
<empty-active-accounts v-if="accountsCount === 0"></empty-active-accounts>
<div class="container" v-if="accountsCount > 0">
<div class="columns">
<div class="column col-3 col-sm-12 col-md-12 col-xl-3 col-lg-3 col-xs-12 col-rop-selector-accounts">
<span class="divider"></span>
<div v-for="( account, id ) in active_accounts">
<div class="rop-selector-account-container" :class="{active: selected_account===id}"
@click="setActiveAccount(id)">
<div class="tile tile-centered rop-account">
<div class="tile-icon">
<div class="icon_box"
:class=" (account.img ? 'has_image' : 'no-image' ) + ' ' +account.service ">
<img class="service_account_image" :src="account.img"
v-if="account.img"/>
<i class="fa " :class="getIcon(account)" aria-hidden="true"></i>
</div>
</div>
<div class="tile-content">
<p class="rop-account-name">{{account.user}}</p>
<strong class="rop-service-name">{{account.service}}</strong>
</div>
</div>
</div>
<span class="divider"></span>
</div>
</div>
<div class="column col-9 col-sm-12 col-md-12 col-xl-9 col-lg-9 col-xs-12"
:class="'rop-tab-state-'+is_loading">
<component :is="type" :account_id="selected_account" :license="license"></component>
</div>
</div>
</div>
</div>
<div class="panel-footer" v-if="accountsCount > 0">
<div class="panel-actions text-right" v-if="allow_footer">
<button class="btn btn-secondary" @click="resetAccountData()"><i class="fa fa-ban"
v-if="!this.is_loading"></i> <i
class="fa fa-spinner fa-spin" v-else></i> {{labels.reset_selector_btn}} {{component_label}}
{{labels.for}}
<b>{{active_account_name}}</b>
</button>
<button class="btn btn-primary" @click="saveAccountData()"><i class="fa fa-check"
v-if="!this.is_loading"></i> <i
class="fa fa-spinner fa-spin" v-else></i> {{labels.save_selector_btn}} {{component_label}}
</button>
</div>
</div>
</div>
<div class="tab-view">
<div class="panel-body">
<div class="d-inline-block mt-2 column col-12">
<p class="text-gray">
<i class="fa fa-info-circle" /> <span v-html="labels.accounts_selector" />
</p>
</div>
<empty-active-accounts v-if="accountsCount === 0" />
<div
v-if="accountsCount > 0"
class="container"
>
<div class="columns">
<div class="column col-3 col-sm-12 col-md-12 col-xl-3 col-lg-3 col-xs-12 col-rop-selector-accounts">
<span class="divider" />
<div
v-for="( account, id ) in active_accounts"
:key="id"
>
<div
class="rop-selector-account-container"
:class="{active: selected_account===id}"
@click="setActiveAccount(id)"
>
<div class="tile tile-centered rop-account">
<div class="tile-icon">
<div
class="icon_box"
:class=" (account.img ? 'has_image' : 'no-image' ) + ' ' +account.service "
>
<img
v-if="account.img"
class="service_account_image"
:src="account.img"
>
<i
class="fa "
:class="getIcon(account)"
aria-hidden="true"
/>
</div>
</div>
<div class="tile-content">
<p class="rop-account-name">
{{ account.user }}
</p>
<strong class="rop-service-name">{{ account.service }}</strong>
</div>
</div>
</div>
<span class="divider" />
</div>
</div>
<div
class="column col-9 col-sm-12 col-md-12 col-xl-9 col-lg-9 col-xs-12"
:class="'rop-tab-state-'+is_loading"
>
<component
:is="type"
:account_id="selected_account"
:license="license"
/>
</div>
</div>
</div>
</div>
<div
v-if="accountsCount > 0"
class="panel-footer"
>
<div
v-if="allow_footer"
class="panel-actions text-right"
>
<button
class="btn btn-secondary"
@click="resetAccountData()"
>
<i
v-if="!is_loading"
class="fa fa-ban"
/> <i
v-else
class="fa fa-spinner fa-spin"
/> {{ labels.reset_selector_btn }} {{ component_label }}
{{ labels.for }}
<b>{{ active_account_name }}</b>
</button>
<button
class="btn btn-primary"
@click="saveAccountData()"
>
<i
v-if="!is_loading"
class="fa fa-check"
/> <i
v-else
class="fa fa-spinner fa-spin"
/> {{ labels.save_selector_btn }} {{ component_label }}
</button>
</div>
</div>
</div>
</template>

<script>
Expand All @@ -61,8 +110,21 @@
import AccountSchedule from './account-schedule.vue'
import MultipleSelect from './reusables/multiple-select.vue'
module.exports = {
name: 'account-selector-view',
export default {
name: 'AccountSelectorView',
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
},
components: {
'empty-active-accounts': EmptyActiveAccounts,
'post-format': PostFormat,
'schedule': AccountSchedule,
'MultipleSelect': MultipleSelect
},
props: {
type: {
default: function () {
Expand All @@ -86,17 +148,6 @@
is_loading: false
}
},
mounted: function () {
this.setupData();
// this.refresh_language_taxonomies();
},
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
},
computed: {
active_data: function () {
if (this.type === 'post-format') {
Expand Down Expand Up @@ -141,15 +192,15 @@
//this.get_lang();
}
},
mounted: function () {
this.setupData();
},
methods: {
postTypes() {
// console.log('post types:', this.$store.state.generalSettings.available_post_types);
return this.$store.state.generalSettings.available_post_types;
},
refresh_language_taxonomies(lang){
this.$store.dispatch('fetchAJAXPromise', {req: 'get_taxonomies', data: {post_types: this.postTypes(), language_code: lang}});
},
get_lang(){
console.log("Inside Get lang");
console.log("LANG: ", document.querySelector('#wpml-language-selector').value);
Expand Down Expand Up @@ -284,12 +335,6 @@
this.checkActiveData();
this.$store.state.dom_updated = false;
}
},
components: {
'empty-active-accounts': EmptyActiveAccounts,
'post-format': PostFormat,
'schedule': AccountSchedule,
'MultipleSelect': MultipleSelect
}
}
</script>
Expand Down
173 changes: 111 additions & 62 deletions vue/src/vue-elements/accounts-tab-panel.vue
@@ -1,55 +1,102 @@
<template>
<div class="tab-view">
<div class="panel-body">
<div class="toast toast-warning" v-html="labels.twitter_warning" v-if="twitter_warning">

</div>
<div class="container">
<div class="columns" :class="'rop-tab-state-'+is_loading">
<div class="column col-sm-12 col-md-12 col-lg-12 text-left rop-available-accounts mt-2">
<vue_spinner :preloader_message="labels.preloader_message_accounts" ref="Preloader" v-if="is_preloading === 0"></vue_spinner>
<div class="empty mb-2" v-if="accountsCount === 0 && is_preloading > 0">
<div class="empty-icon">
<i class="fa fa-3x fa-user-circle-o"></i>
</div>
<p class="empty-title h5">{{labels.no_accounts}}</p>
<p class="empty-subtitle">{{labels.no_accounts_desc}}</p>
</div>
<div class="account-container" v-for="( account, id ) in accounts" v-if="is_preloading > 0">
<service-user-tile :account_data="account" :account_id="id"></service-user-tile>
<span class="divider"></span>
</div>
<div class="add-accounts" v-if="is_preloading > 0" id="rop-add-account-button">
<add-account-tile></add-account-tile>
<span class="divider"></span>
</div>
</div>
</div>
<div class="tab-view">
<div class="panel-body">
<div
v-if="twitter_warning"
class="toast toast-warning"
v-html="labels.twitter_warning"
/>
<div class="container">
<div
class="columns"
:class="'rop-tab-state-'+is_loading"
>
<div class="column col-sm-12 col-md-12 col-lg-12 text-left rop-available-accounts mt-2">
<vue_spinner
v-if="is_preloading === 0"
ref="Preloader"
:preloader_message="labels.preloader_message_accounts"
/>
<div
v-if="accountsCount === 0 && is_preloading > 0"
class="empty mb-2"
>
<div class="empty-icon">
<i class="fa fa-3x fa-user-circle-o" />
</div>
<p class="empty-title h5">
{{ labels.no_accounts }}
</p>
<p class="empty-subtitle">
{{ labels.no_accounts_desc }}
</p>
</div>
<div class="panel-footer" v-if="is_preloading > 0">
<div class="columns my-2" v-if="checkLicense && pro_installed">
<div class="column col-12">
<i class="fa fa-info-circle "></i> <span v-html="labels.activate_license"></span>
</div>
</div>
<div class="columns my-2" v-if="(checkLicense && accountsCount === 2) && !pro_installed">
<div class="column col-12">
<p class="upsell">
<i class="fa fa-info-circle "></i> <span v-html="labels.upsell_accounts"></span>
</p>
</div>
</div>
<div class="column col-12 text-right">
<button class="btn btn-secondary" @click="resetAccountData()">
<i class="fa fa-ban" v-if="!this.is_loading"></i>
<i class="fa fa-spinner fa-spin" v-else></i>
{{labels.remove_all_cta}}
</button>
</div>
<template v-if="is_preloading > 0">
<div
v-for="( account, id ) in accounts"
:key="id"

class="account-container"
>
<service-user-tile
:account_data="account"
:account_id="id"
/>
<span class="divider" />
</div>
</template>
<div
v-if="is_preloading > 0"
id="rop-add-account-button"
class="add-accounts"
>
<add-account-tile />
<span class="divider" />
</div>
</div>
</div>

</div>
<div
v-if="is_preloading > 0"
class="panel-footer"
>
<div
v-if="checkLicense && pro_installed"
class="columns my-2"
>
<div class="column col-12">
<i class="fa fa-info-circle " /> <span v-html="labels.activate_license" />
</div>
</div>
<div
v-if="(checkLicense && accountsCount === 2) && !pro_installed"
class="columns my-2"
>
<div class="column col-12">
<p class="upsell">
<i class="fa fa-info-circle " /> <span v-html="labels.upsell_accounts" />
</p>
</div>
</div>
<div class="column col-12 text-right">
<button
class="btn btn-secondary"
@click="resetAccountData()"
>
<i
v-if="!is_loading"
class="fa fa-ban"
/>
<i
v-else
class="fa fa-spinner fa-spin"
/>
{{ labels.remove_all_cta }}
</button>
</div>
</div>
</div>
</div>
</template>

<script>
Expand All @@ -58,8 +105,14 @@
import AddAccountTile from './reusables/add-account-tile.vue'
import vue_spinner from './reusables/vue-spinner.vue'
module.exports = {
name: 'account-view',
export default {
name: 'AccountView',
components: {
SignInBtn,
ServiceUserTile,
AddAccountTile,
'vue_spinner': vue_spinner
},
data: function () {
return {
addAccountActive: false,
Expand All @@ -68,13 +121,7 @@
twitter_warning: false,
labels: this.$store.state.labels.accounts,
upsell_link: ropApiSettings.upsell_link,
pro_installed: ropApiSettings.pro_installed,
is_preloading: this.$store.state.hide_preloading
}
},
mounted: function () {
if (0 === this.is_preloading) {
this.page_loader_module_display();
pro_installed: ropApiSettings.pro_installed
}
},
computed: {
Expand Down Expand Up @@ -114,6 +161,14 @@
checkLicense: function () {
return (this.$store.state.licence < 1);
},
is_preloading: function () {
return this.$store.state.hide_preloading;
}
},
mounted: function () {
if (0 === this.is_preloading) {
this.page_loader_module_display();
}
},
methods: {
Expand Down Expand Up @@ -147,12 +202,6 @@
Vue.$log.error('Got nothing from server. Prompt user to check internet connection and try again', error)
})
}
},
components: {
SignInBtn,
ServiceUserTile,
AddAccountTile,
'vue_spinner': vue_spinner
}
}
</script>
Expand Down
317 changes: 202 additions & 115 deletions vue/src/vue-elements/exclude-posts-page.vue
@@ -1,110 +1,197 @@
<template>
<div id="rop_core" class="columns ">
<div id="rop-sidebar-selector" class="column col-3 col-xl-5 col-lg-5 col-md-6 col-sm-6 col-xs-12 pull-right">
<div class="columns py-2" :class="'rop-control-container-'+isPro">
<div class="column col-12 col-sm-12 vertical-align rop-control">
<b>{{labels.post_types_title}}</b>
<p class="text-gray"> {{labels.filter_by_post_types_desc}}</p>
</div>
<div class="column col-12 col-sm-12 vertical-align text-left rop-control">
<multiple-select :options="postTypes" :disabled="isPro"
:selected="generalSettings.selected_post_types"
:changed-selection="updatedPostTypes"></multiple-select>
</div>
</div>

<span class="divider"></span>
<div class="columns py-2" v-if="!isPro">
<div class="column text-center">
<p class="upsell"><i class="fa fa-lock"></i> {{labels.post_types_upsell}}</p>
</div>
</div>
<div class="columns py-2">
<div class="column col-12 col-sm-12 vertical-align">
<b>{{labels.taxonomies_title}}</b>
<p class="text-gray"> {{labels.filter_by_taxonomies_desc}}</p>
</div>
<div class="column col-12 col-sm-12 vertical-align text-left">
<div class="input-group">
<multiple-select :options="taxonomies"
:selected="generalSettings.selected_taxonomies"
:changed-selection="updatedTaxonomies"
></multiple-select>

</div>
</div>

</div>
<upsell-sidebar></upsell-sidebar>
<div
id="rop_core"
class="columns "
>
<div
id="rop-sidebar-selector"
class="column col-3 col-xl-5 col-lg-5 col-md-6 col-sm-6 col-xs-12 pull-right"
>
<div
class="columns py-2"
:class="'rop-control-container-'+isPro"
>
<div class="column col-12 col-sm-12 vertical-align rop-control">
<b>{{ labels.post_types_title }}</b>
<p class="text-gray">
{{ labels.filter_by_post_types_desc }}
</p>
</div>
<div class="column col-12 col-sm-12 vertical-align text-left rop-control">
<multiple-select
:options="postTypes"
:disabled="isPro"
:selected="generalSettings.selected_post_types"
:changed-selection="updatedPostTypes"
/>
</div>
</div>

<span class="divider" />
<div
v-if="!isPro"
class="columns py-2"
>
<div class="column text-center">
<p class="upsell">
<i class="fa fa-lock" /> {{ labels.post_types_upsell }}
</p>
</div>
</div>
<div class="columns py-2">
<div class="column col-12 col-sm-12 vertical-align">
<b>{{ labels.taxonomies_title }}</b>
<p class="text-gray">
{{ labels.filter_by_taxonomies_desc }}
</p>
</div>
<div class="column col-12 col-sm-12 vertical-align text-left">
<div class="input-group">
<multiple-select
:options="taxonomies"
:selected="generalSettings.selected_taxonomies"
:changed-selection="updatedTaxonomies"
/>
</div>
</div>
</div>
<upsell-sidebar />
</div>
<div
id="rop-posts-listing"
class="column col-9 col-xl-7 col-lg-7 col-md-6 col-sm-6 col-xs-12 col- pull-left"
>
<div class="columns py-2">
<div class="column col-12 col-sm-12 vertical-align">
<div class="input-group has-icon-right">
<input
v-model="searchQuery"
class="form-input"
type="text"
:placeholder="labels.search_posts_to_exclude"
>
<i
v-if="is_loading"
class="form-icon loading"
/>
</div>
</div>
<div id="rop-posts-listing" class="column col-9 col-xl-7 col-lg-7 col-md-6 col-sm-6 col-xs-12 col- pull-left">
<div class="columns py-2">
<div class="column col-12 col-sm-12 vertical-align">
<div class="input-group has-icon-right">
<input class="form-input" type="text" v-model="searchQuery"
:placeholder="labels.search_posts_to_exclude"/>
<i class="form-icon loading" v-if="is_loading"></i>
</div>
</div>
<div class="column col-12 col-sm-12 mt-2">
<div class="form-group pull-right" v-if="searchQuery != '' && ! show_excluded">
<button class="btn btn-primary" @click="excludePostsBatch">
<i class="fa fa-save " v-if="!this.is_loading"></i>
<i class="fa fa-spinner fa-spin" v-else></i>
{{labels.exclude_matching}} "{{searchQuery}}"
<div class="column col-12 col-sm-12 mt-2">
<div
v-if="searchQuery != '' && ! show_excluded"
class="form-group pull-right"
>
<button
class="btn btn-primary"
@click="excludePostsBatch"
>
<i
v-if="!is_loading"
class="fa fa-save "
/>
<i
v-else
class="fa fa-spinner fa-spin"
/>
{{ labels.exclude_matching }} "{{ searchQuery }}"
</button>
</div>
<div class="form-group pull-right ">
<label class="form-switch">
<input
v-model="show_excluded"
type="checkbox"
@change="excludePostsChange"
>
<i class="form-icon" />{{ labels.search_posts_show_excluded }}
</label>
</div>

<p
v-if="apply_limit_exclude"
class="text-primary rop-post-type-badge"
v-html="labels.post_types_exclude_limit"
/>
</div>
<div
v-if="postsAvailable"
class="column col-12 px-2"
>
<div v-if="postsAvailable.length === 0 && !is_loading">
{{ labels.no_posts_found }}
</div>
<div v-else>
<table
v-if=" ! is_loading"
id="rop-posts-table"
class="table table-striped table-hover"
>
<tr
v-for="(post,index ) in postsAvailable"
:key="index"
class="rop-post-item"
>
<td :class="'rop-post-' + post.selected">
{{ post.name }}
<template>
<tooltip
placement="top-right"
mode="hover"
:is_show="apply_limit_exclude"
>
<div slot="outlet">
<button
class="btn btn-error rop-exclude-post"
@click="excludeSinglePost(post.value,post.selected)"
>
<i
v-if="!is_loading_single"
class="fa"
:class="'fa-' + (post.selected ? 'plus' : 'remove') "
/>
<i
v-else
class="fa fa-spinner fa-spin"
/>
<span v-html=" ( post.selected ? labels.include_single_post : labels.exclude_single_post) " />
</button>
</div>
<div class="form-group pull-right ">
<label class="form-switch">
<input type="checkbox" v-model="show_excluded" @change="excludePostsChange">
<i class="form-icon"></i>{{labels.search_posts_show_excluded}}
</label>
</div>

<p class="text-primary rop-post-type-badge" v-if="apply_limit_exclude" v-html="labels.post_types_exclude_limit"></p>
</div>
<div class="column col-12 px-2" v-if="postsAvailable">
<div v-if="postsAvailable.length === 0 && !is_loading">
{{labels.no_posts_found}}
</div>
<div v-else>
<table id="rop-posts-table" class="table table-striped table-hover" v-if=" ! is_loading">
<tr v-for="(post,index ) in postsAvailable" class="rop-post-item">
<td :class="'rop-post-' + post.selected">{{post.name}}
<template>
<tooltip placement="top-right" mode="hover" :is_show="apply_limit_exclude">
<div slot="outlet">
<button class="btn btn-error rop-exclude-post"
@click="excludeSinglePost(post.value,post.selected)">
<i class="fa" :class="'fa-' + (post.selected ? 'plus' : 'remove') "
v-if="!is_loading_single"></i>
<i class="fa fa-spinner fa-spin" v-else></i>
<span v-html=" ( post.selected ? labels.include_single_post : labels.exclude_single_post) "> </span>
</button>
</div>
<div slot="tooltip" v-html="labels.post_types_exclude_limit_tooltip"></div>
</tooltip>
</template>
</td>
</tr>
<tr v-if="has_pages">
<td class="rop-load-more-posts">
<button class="btn btn-error"
@click="loadMorePosts()">
<i class="fa fa-newspaper-o " v-if="!is_loading_single"></i>
<i class="fa fa-spinner fa-spin" v-else></i>
{{labels.load_more_posts}}
</button>
</td>
</tr>
</table>
<div class="loading loading-lg" v-else></div>
</div>
</div>
</div>
</div>
<div
slot="tooltip"
v-html="labels.post_types_exclude_limit_tooltip"
/>
</tooltip>
</template>
</td>
</tr>
<tr v-if="has_pages">
<td class="rop-load-more-posts">
<button
class="btn btn-error"
@click="loadMorePosts()"
>
<i
v-if="!is_loading_single"
class="fa fa-newspaper-o "
/>
<i
v-else
class="fa fa-spinner fa-spin"
/>
{{ labels.load_more_posts }}
</button>
</td>
</tr>
</table>
<div
v-else
class="loading loading-lg"
/>
</div>
</div>

</div>
</div>
</div>
</template>

<script>
Expand All @@ -116,8 +203,11 @@
// Vue.use(Tooltip);
module.exports = {
name: 'exclude-posts-page',
export default {
name: 'ExcludePostsPage',
components: {
MultipleSelect, UpsellSidebar, Tooltip
},
data: function () {
return {
searchQuery: '',
Expand All @@ -135,14 +225,6 @@
apply_limit_exclude: false
}
},
watch: {
searchQuery: function ( val ) {
this.searchUpdate( val );
},
postsAvailable: function ( val ) {
this.has_pages = ( this.postsAvailable.length % 100 === 0 );
},
},
computed: {
generalSettings: function () {
return this.$store.state.generalSettings
Expand Down Expand Up @@ -173,6 +255,14 @@
}
},
watch: {
searchQuery: function ( val ) {
this.searchUpdate( val );
},
postsAvailable: function ( val ) {
this.has_pages = ( this.postsAvailable.length % 100 === 0 );
},
},
mounted: function () {
this.$log.info( 'In General Settings state ' );
this.getGeneralSettings();
Expand Down Expand Up @@ -382,9 +472,6 @@
Vue.$log.error( 'Got nothing from server. Prompt user to check internet connection and try again', error )
} )
}
},
components: {
MultipleSelect, UpsellSidebar, Tooltip
}
}
</script>
Expand Down
103 changes: 66 additions & 37 deletions vue/src/vue-elements/logs-tab-panel.vue
@@ -1,45 +1,74 @@
<template>
<div class="tab-view">
<div class="panel-body">
<div class=" columns mt-2" v-if="logs_no > 0">
<div class="column col-12 text-right ">
<button class="btn btn-secondary " @click="getLogs(true)">
<i class="fa fa-remove" v-if="!is_loading"></i>
<i class="fa fa-spinner fa-spin" v-else></i>
{{labels.clear_btn}}
</button>
</div>
</div>
<div class="columns">
<div class="empty column col-12" v-if="is_loading">
<div class="empty-icon">
<i class="fa fa-3x fa-spinner fa-spin"></i>
</div>
</div>
<div class="empty column col-12" v-else-if="logs_no === 0">
<div class="empty-icon">
<i class="fa fa-3x fa-info-circle"></i>
</div>
<p class="empty-title h5">{{labels.no_logs}}</p>
</div>
<div class="tab-view">
<div class="panel-body">
<div
v-if="logs_no > 0"
class=" columns mt-2"
>
<div class="column col-12 text-right ">
<button
class="btn btn-secondary "
@click="getLogs(true)"
>
<i
v-if="!is_loading"
class="fa fa-remove"
/>
<i
v-else
class="fa fa-spinner fa-spin"
/>
{{ labels.clear_btn }}
</button>
</div>
</div>
<div class="columns">
<div
v-if="is_loading"
class="empty column col-12"
>
<div class="empty-icon">
<i class="fa fa-3x fa-spinner fa-spin" />
</div>
</div>
<div
v-else-if="logs_no === 0"
class="empty column col-12"
>
<div class="empty-icon">
<i class="fa fa-3x fa-info-circle" />
</div>
<p class="empty-title h5">
{{ labels.no_logs }}
</p>
</div>

<div class="column col-12 mt-2" v-for=" (data, index) in logs " v-else-if="logs_no > 0">
<div class="toast log-toast" :class="'toast-' + data.type">
<small class="pull-right text-right">{{formatDate ( data.time ) }}</small>
<p>{{data.message}}</p>
</div>
</div>
</div>
</div>
</div>
<template v-else-if="logs_no > 0">
<div
v-for=" (data, index) in logs "
:key="index"
class="column col-12 mt-2"
>
<div
class="toast log-toast"
:class="'toast-' + data.type"
>
<small class="pull-right text-right">{{ formatDate ( data.time ) }}</small>
<p>{{ data.message }}</p>
</div>
</div>
</template>
</div>
</div>
</div>
</template>

<script>
import moment from 'moment'
module.exports = {
name: 'logs-view',
export default {
name: 'LogsView',
props: ['model'],
data: function () {
return {
Expand All @@ -48,9 +77,6 @@
upsell_link: ropApiSettings.upsell_link,
}
},
mounted: function () {
this.getLogs();
},
computed: {
logs: function () {
return this.$store.state.page.logs
Expand All @@ -64,6 +90,9 @@
this.getLogs();
}
},
mounted: function () {
this.getLogs();
},
methods: {
getLogs(force) {
if (this.is_loading) {
Expand Down
311 changes: 207 additions & 104 deletions vue/src/vue-elements/main-page-panel.vue
@@ -1,88 +1,194 @@
<template>
<div>
<div class="columns panel-header">
<div class="column header-logo vertical-align" v-if="is_preloading_over > 0">
<div>
<img :src="plugin_logo" class="plugin-logo avatar avatar-lg"/>
<h1 class="plugin-title d-inline-block">Revive Old Posts</h1><span class="powered d-inline-block"> {{labels.by}} <a
href="https://revive.social" target="_blank"><b>Revive.Social</b></a> <a href="https://www.youtube.com/playlist?list=PLAsG7vAH40Q512C8d_0lBpVZusUQqUxuH" target="_blank" id="rop_vid_tuts"><span>START HERE <i class="fa fa-play-circle" aria-hidden="true"></i></span></a></span>

</div>
</div>
<toast/>
<div v-if=" is_rest_api_error " class="toast toast-error rop-api-not-available" v-html="labels.api_not_available">
</div>
<div v-if=" is_fb_domain_notice " class="toast toast-primary">
<button class="btn btn-clear float-right" @click="close_fb_domain_notice()"></button>
<div v-html="labels.rop_facebook_domain_toast"></div>
</div>
<div class="sidebar sidebar-top card rop-container-start">

<!-- Next post count down -->
<countdown :current_time="current_time"/>
<!-- -->

<button class="btn btn-sm" :class="btn_class"
:data-tooltip="labels.active_account_warning"
@click="togglePosting()" :disabled="!haveAccountsActive">
<i class="fa fa-play" v-if="!is_loading && !start_status"></i>
<i class="fa fa-stop" v-else-if="!is_loading && start_status"></i>
<i class="fa fa-spinner fa-spin" v-else></i>
{{( start_status ? labels.stop : labels.start )}} {{labels.sharing}}
</button>
</div>
<div>
<div class="columns panel-header">
<div
v-if="is_preloading_over > 0"
class="column header-logo vertical-align"
>
<div>
<img
:src="plugin_logo"
class="plugin-logo avatar avatar-lg"
>
<h1 class="plugin-title d-inline-block">
Revive Old Posts
</h1>
<span class="powered d-inline-block">
{{ labels.by }}
<a
href="https://revive.social"
target="_blank"
>
<b>Revive.Social</b>
</a>
<a
id="rop_vid_tuts"
href="https://www.youtube.com/playlist?list=PLAsG7vAH40Q512C8d_0lBpVZusUQqUxuH"
target="_blank"
>
<span>
START HERE
<i
class="fa fa-play-circle"
aria-hidden="true"
/>
</span>
</a>
</span>
</div>
</div>
<toast />
<div
v-if=" is_rest_api_error "
class="toast toast-error rop-api-not-available"
v-html="labels.api_not_available"
/>
<div
v-if=" is_fb_domain_notice "
class="toast toast-primary"
>
<button
class="btn btn-clear float-right"
@click="close_fb_domain_notice()"
/>
<div v-html="labels.rop_facebook_domain_toast" />
</div>
<div class="sidebar sidebar-top card rop-container-start">
<!-- Next post count down -->
<countdown :current_time="current_time" />
<!-- -->

<div class="columns">
<div class="panel column col-xs-12 col-sm-12 col-md-12 col-lg-12 col-xl-12">
<div class="panel-nav" style="padding: 8px;" v-if="is_preloading_over > 0">
<ul class="tab ">
<li class="tab-item c-hand" v-for="tab in displayTabs"
:class="{ active: tab.isActive }" v-bind:id="tab.name.replace(' ', '').toLowerCase()">
<a :class=" ( tab.slug === 'logs' && logs_no > 0 ) ? ' badge-logs badge' : '' "
:data-badge="logs_no"
@click="switchTab( tab.slug )">{{ tab.name }}</a>
</li>
</ul>
</div>
<component :is="page.template" :type="page.view"></component>
</div>

<div class="sidebar column col-3 col-xs-12 col-sm-12 col-md-12 col-lg-12"
:class="'rop-license-plan-'+license" v-if="is_preloading_over > 0">
<button
class="btn btn-sm"
:class="btn_class"
:data-tooltip="labels.active_account_warning"
:disabled="!haveAccountsActive"
@click="togglePosting()"
>
<i
v-if="!is_loading && !start_status"
class="fa fa-play"
/>
<i
v-else-if="!is_loading && start_status"
class="fa fa-stop"
/>
<i
v-else
class="fa fa-spinner fa-spin"
/>
{{ ( start_status ? labels.stop : labels.start ) }} {{ labels.sharing }}
</button>
</div>
</div>

<div class="card rop-container-start">
<button id="rop_start_stop_btn" class="btn" :class="btn_class"
:data-tooltip="labels.active_account_warning"
@click="togglePosting()" :disabled="!haveAccountsActive">
<i class="fa fa-play" v-if="!is_loading && !start_status"></i>
<i class="fa fa-stop" v-else-if="!is_loading && start_status"></i>
<i class="fa fa-spinner fa-spin" v-else></i>
{{labels.click}} {{labels.to}} {{( start_status ? labels.stop : labels.start )}} {{labels.sharing}}
</button>
<div class="columns">
<div class="panel column col-xs-12 col-sm-12 col-md-12 col-lg-12 col-xl-12">
<div
v-if="is_preloading_over > 0"
class="panel-nav"
style="padding: 8px;"
>
<ul class="tab ">
<li
v-for="tab in displayTabs"
:id="tab.name.replace(' ', '').toLowerCase()"
:key="tab.slug"
class="tab-item c-hand"
:class="{ active: tab.isActive }"
>
<a
:class=" ( tab.slug === 'logs' && logs_no > 0 ) ? ' badge-logs badge' : '' "
:data-badge="logs_no"
@click="switchTab( tab.slug )"
>{{ tab.name }}</a>
</li>
</ul>
</div>
<component
:is="page.template"
:type="page.view"
/>
</div>

<div class="sharing-box" :class="status_color_class">{{ status_label_display }}</div>
<div
v-if="is_preloading_over > 0"
class="sidebar column col-3 col-xs-12 col-sm-12 col-md-12 col-lg-12"
:class="'rop-license-plan-'+license"
>
<div class="card rop-container-start">
<button
id="rop_start_stop_btn"
class="btn"
:class="btn_class"
:data-tooltip="labels.active_account_warning"
:disabled="!haveAccountsActive"
@click="togglePosting()"
>
<i
v-if="!is_loading && !start_status"
class="fa fa-play"
/>
<i
v-else-if="!is_loading && start_status"
class="fa fa-stop"
/>
<i
v-else
class="fa fa-spinner fa-spin"
/>
{{ labels.click }} {{ labels.to }} {{ ( start_status ? labels.stop : labels.start ) }} {{ labels.sharing }}
</button>

<countdown :current_time="current_time"/>
<div
class="sharing-box"
:class="status_color_class"
>
{{ status_label_display }}
</div>

<div id="staging-status" v-if="staging" v-html="labels.staging_status">
</div>
<div v-if="!haveAccounts" class="rop-spacer"></div>
<div v-if="haveAccounts">
<upsell-sidebar></upsell-sidebar>
</div>
<a v-if="license >= 1" href="https://revive.social/pro-support/" target="_blank" class="btn rop-sidebar-action-btns">{{labels.rop_support}}</a>
<a v-if="license < 1" href="https://revive.social/support/" target="_blank" class="btn rop-sidebar-action-btns">{{labels.rop_support}}</a>
<a v-if="haveAccounts" href="https://docs.revive.social/" target="_blank"
class="btn rop-sidebar-action-btns">{{labels.rop_docs}}</a>
<a v-if="haveAccounts"
href="https://wordpress.org/support/plugin/tweet-old-post/reviews/?rate=5#new-post"
target="_blank" class="btn rop-sidebar-action-btns">{{labels.review_it}}</a>
</div>
<countdown :current_time="current_time" />

</div>
<div
v-if="staging"
id="staging-status"
v-html="labels.staging_status"
/>
<div
v-if="!haveAccounts"
class="rop-spacer"
/>
<div v-if="haveAccounts">
<upsell-sidebar />
</div>
<a
v-if="license >= 1"
href="https://revive.social/pro-support/"
target="_blank"
class="btn rop-sidebar-action-btns"
>{{ labels.rop_support }}</a>
<a
v-if="license < 1"
href="https://revive.social/support/"
target="_blank"
class="btn rop-sidebar-action-btns"
>{{ labels.rop_support }}</a>
<a
v-if="haveAccounts"
href="https://docs.revive.social/"
target="_blank"
class="btn rop-sidebar-action-btns"
>{{ labels.rop_docs }}</a>
<a
v-if="haveAccounts"
href="https://wordpress.org/support/plugin/tweet-old-post/reviews/?rate=5#new-post"
target="_blank"
class="btn rop-sidebar-action-btns"
>{{ labels.review_it }}</a>
</div>
</div>
</div>
</div>
</template>

<script>
Expand All @@ -97,8 +203,32 @@
import moment from 'moment'
import upsellSidebar from './upsell-sidebar.vue'
module.exports = {
name: 'main-page-panel',
export default {
name: 'MainPagePanel',
components: {
'accounts': AccountsTab,
'settings': SettingsTab,
'accounts-selector': AccountsSelectorTab,
'queue': QueueTab,
'logs': LogsTab,
'upsell-sidebar': upsellSidebar,
'toast': Toast,
'countdown': CountDown
},
data: function () {
return {
to_pro_upsell: ROP_ASSETS_URL + 'img/to_pro.png',
to_business_upsell: ROP_ASSETS_URL + 'img/to_business.png',
plugin_logo: ROP_ASSETS_URL + 'img/logo_rop.png',
license: this.$store.state.licence,
labels: this.$store.state.labels.general,
upsell_link: ropApiSettings.upsell_link,
staging: ropApiSettings.staging,
is_loading: false,
is_loading_logs: false,
status_is_error_display: false
}
},
computed: {
is_preloading_over: function () {
return this.$store.state.hide_preloading;
Expand Down Expand Up @@ -180,9 +310,6 @@
}
return labels.status + ': ' + status_label_display;
},
status_is_error_display: function () {
return this.status_is_error_display;
},
/**
* Check if we have accounts connected.
*
Expand Down Expand Up @@ -227,20 +354,6 @@
created() {
this.$root.$refs.main_page = this;
},
data: function () {
return {
to_pro_upsell: ROP_ASSETS_URL + 'img/to_pro.png',
to_business_upsell: ROP_ASSETS_URL + 'img/to_business.png',
plugin_logo: ROP_ASSETS_URL + 'img/logo_rop.png',
license: this.$store.state.licence,
labels: this.$store.state.labels.general,
upsell_link: ropApiSettings.upsell_link,
staging: ropApiSettings.staging,
is_loading: false,
is_loading_logs: false,
status_is_error_display: false
}
},
methods: {
/**
*
Expand Down Expand Up @@ -341,16 +454,6 @@
this.is_loading_logs = false;
})
}
},
components: {
'accounts': AccountsTab,
'settings': SettingsTab,
'accounts-selector': AccountsSelectorTab,
'queue': QueueTab,
'logs': LogsTab,
'upsell-sidebar': upsellSidebar,
'toast': Toast,
'countdown': CountDown
}
}
</script>
Expand Down
1,093 changes: 690 additions & 403 deletions vue/src/vue-elements/post-format.vue

Large diffs are not rendered by default.

112 changes: 78 additions & 34 deletions vue/src/vue-elements/pro/publish-now.vue
@@ -1,36 +1,79 @@
<template>
<div class="rop-control-container">
<p v-if="Object.keys(accounts).length < 1">{{labels.add_account_to_use_instant_share}}</p>
<!-- Share on publish/update -->
<fieldset v-if="Object.keys(accounts).length > 0">
<label class="form-checkbox">
<input type="checkbox" :checked="share_on_update_by_default" v-on:click="toggle_accounts = !toggle_accounts" name="publish_now" value="1"/>
<span v-html=" labels.share_on_update"></span>
</label>

<div class="form-group rop-publish-now-accounts-wrapper" v-if="toggle_accounts" v-for="(account, key) in accounts" :id="key" v-bind:key="key">
<label class="form-checkbox rop-publish-now-account" :id="key">
<input type="checkbox" :checked="share_on_update_by_default && !choose_accounts_manually" :value="key" v-on:click="toggleServices($event, key)" name="publish_now_accounts[]" class="rop-account-names"/>
<i class=" fa " :class="getServiceClass(account.service)"></i> {{account.user}}
</label>
<span v-on:click="togglefields(key)" :id="key" class="rop-edit-custom-instant-share-message-text">{{ showField[key] ? 'done' : 'edit message' }}</span>
<p v-show="showField[key]" class="rop-custom-instant-share-message-text">Custom share message:</p>
<textarea v-show="showField[key]" :name="key" :disabled="!isPro" class="rop-custom-instant-share-message-area"></textarea>
<p v-if="!isPro && showField[key]" v-html="labels.custom_instant_share_messages_upsell" class="custom-instant-share-upsell"></p>
</div>
</fieldset>

</div>
<div class="rop-control-container">
<p v-if="Object.keys(accounts).length < 1">
{{ labels.add_account_to_use_instant_share }}
</p>
<!-- Share on publish/update -->
<fieldset v-if="Object.keys(accounts).length > 0">
<label class="form-checkbox">
<input
type="checkbox"
:checked="share_on_update_by_default"
name="publish_now"
value="1"
@click="toggle_accounts = !toggle_accounts"
>
<span v-html=" labels.share_on_update" />
</label>
<template v-if="toggle_accounts">
<div
v-for="(account, key) in accounts"
:id="key"
:key="key"
class="form-group rop-publish-now-accounts-wrapper"
>
<label
:id="key"
class="form-checkbox rop-publish-now-account"
>
<input
type="checkbox"
:checked="share_on_update_by_default && !choose_accounts_manually"
:value="key"
name="publish_now_accounts[]"
class="rop-account-names"
@click="toggleServices($event, key)"
>
<i
class=" fa "
:class="getServiceClass(account.service)"
/> {{ account.user }}
</label>
<span
:id="key"
class="rop-edit-custom-instant-share-message-text"
@click="togglefields(key)"
>{{ showField[key] ? 'done' : 'edit message' }}</span>
<p
v-show="showField[key]"
class="rop-custom-instant-share-message-text"
>
Custom share message:
</p>
<textarea
v-show="showField[key]"
:name="key"
:disabled="!isPro"
class="rop-custom-instant-share-message-area"
/>
<p
v-if="!isPro && showField[key]"
class="custom-instant-share-upsell"
v-html="labels.custom_instant_share_messages_upsell"
/>
</div>
</template>
</fieldset>
</div>
</template>

<script>
import ButtonCheckbox from '../reusables/button-checkbox.vue'
module.exports = {
name: 'publish-now',
created() {
},
computed: {
export default {
name: 'PublishNow',
components: {
ButtonCheckbox
},
data: function () {
var fields = {};
Expand All @@ -50,8 +93,14 @@
toggle_accounts: this.$store.state.publish_now.instant_share_by_default,
}
},
components: {
ButtonCheckbox
computed: {
},
computed: {
isPro: function () {
return (this.license > 0);
},
},
created() {
},
methods: {
getServiceClass: function (service) {
Expand Down Expand Up @@ -81,11 +130,6 @@
return self.showField[value] = ! self.showField[value];
},
},
computed: {
isPro: function () {
return (this.license > 0);
},
}
}
</script>
Expand Down
159 changes: 103 additions & 56 deletions vue/src/vue-elements/queue-tab-panel.vue
@@ -1,57 +1,114 @@
<template>
<div class="tab-view rop-queue-tab-container">
<div class="panel-body" :class="'rop-tab-state-'+is_loading">
<div class="columns" v-if="! start_status">
<div class="column col-12 text-center empty-container">
<div class="empty-icon">
<i class="fa fa-3x fa-info-circle"></i>
</div>
<p class="empty-title h5">{{labels.sharing_not_started}}</p>
<p class="empty-subtitle">{{labels.sharing_not_started_desc}}</p>
</div>
</div>
<div class="tab-view rop-queue-tab-container">
<div
class="panel-body"
:class="'rop-tab-state-'+is_loading"
>
<div
v-if="! start_status"
class="columns"
>
<div class="column col-12 text-center empty-container">
<div class="empty-icon">
<i class="fa fa-3x fa-info-circle" />
</div>
<p class="empty-title h5">
{{ labels.sharing_not_started }}
</p>
<p class="empty-subtitle">
{{ labels.sharing_not_started_desc }}
</p>
</div>
</div>

<div v-else-if="start_status && queueCount > 0 ">
<div v-else-if="start_status && queueCount > 0 ">
<div
v-if="! is_business_and_higher"
class="columns py-2"
>
<div class="column text-center">
<p class="upsell">
<i class="fa fa-lock" /> <span v-html="labels.business_or_higher_only" />
</p>
</div>
</div>

<div class="columns py-2" v-if="! is_business_and_higher">
<div class="column text-center">
<p class="upsell"><i class="fa fa-lock"></i> <span v-html="labels.business_or_higher_only"></span></p>
</div>
</div>

<!-- When sharing is started but we have the business plan. -->
<div class="d-inline-block mt-2 column col-12">
<p class="text-gray info-paragraph"><i class="fa fa-info-circle"></i> {{labels.queue_desc}}</p>
</div>
</div>
<div class="empty" v-else-if="start_status && queueCount === 0">
<div class="empty-icon">
<i class="fa fa-3x fa-info-circle"></i>
</div>
<p class="empty-title h5">{{labels.no_posts}}</p>
<p class="empty-subtitle" v-html="labels.no_posts_desc"></p>
</div>
<div class="columns" v-if="start_status && queueCount > 0">
<div class="column col-12 text-left" v-for=" (data, index) in queue ">
<queue-card :card_data="data.post_data" :id="index" :enabled="is_business_and_higher"/>
</div>
</div>
</div>
<div class="panel-footer text-rightcade" v-if="start_status">
<button class="btn btn-secondary" @click="refreshQueue(true)">
<i class="fa fa-refresh" v-if="!is_loading"></i>
<i class="fa fa-spinner fa-spin" v-else></i>
{{labels.refresh_btn}}
</button>
</div>
</div>
<!-- When sharing is started but we have the business plan. -->
<div class="d-inline-block mt-2 column col-12">
<p class="text-gray info-paragraph">
<i class="fa fa-info-circle" /> {{ labels.queue_desc }}
</p>
</div>
</div>
<div
v-else-if="start_status && queueCount === 0"
class="empty"
>
<div class="empty-icon">
<i class="fa fa-3x fa-info-circle" />
</div>
<p class="empty-title h5">
{{ labels.no_posts }}
</p>
<p
class="empty-subtitle"
v-html="labels.no_posts_desc"
/>
</div>
<div
v-if="start_status && queueCount > 0"
class="columns"
>
<div
v-for=" (data, index) in queue "
:key="index"
class="column col-12 text-left"
>
<queue-card
:id="index"
:card_data="data.post_data"
:enabled="is_business_and_higher"
/>
</div>
</div>
</div>
<div
v-if="start_status"
class="panel-footer text-rightcade"
>
<button
class="btn btn-secondary"
@click="refreshQueue(true)"
>
<i
v-if="!is_loading"
class="fa fa-refresh"
/>
<i
v-else
class="fa fa-spinner fa-spin"
/>
{{ labels.refresh_btn }}
</button>
</div>
</div>
</template>

<script>
import QueueCard from './reusables/queue-card.vue'
module.exports = {
name: 'queue-view',
export default {
name: 'QueueView',
components: {
QueueCard
},
data: function () {
return {
is_loading: false,
labels: this.$store.state.labels.queue,
upsell_link: ropApiSettings.upsell_link,
}
},
computed: {
queueCount: function () {
return Object.keys(this.$store.state.queue).length
Expand All @@ -66,13 +123,6 @@
return (this.$store.state.licence > 1 && this.$store.state.licence !== 7)
},
},
data: function () {
return {
is_loading: false,
labels: this.$store.state.labels.queue,
upsell_link: ropApiSettings.upsell_link,
}
},
watch: {
start_status: function (new_val) {
this.refreshQueue();
Expand All @@ -99,9 +149,6 @@
Vue.$log.error('Got nothing from server. Prompt user to check internet connection and try again', error)
})
}
},
components: {
QueueCard
}
}
</script>
33 changes: 18 additions & 15 deletions vue/src/vue-elements/reusables/add-account-tile.vue
@@ -1,22 +1,28 @@
<template>
<div>
<div class="tile-content">
</div>
<div class="rop-add-account">
<button class="btn btn-secondary" v-if="!this.add_more_clicked && this.added_networks >= 2" @click="addMore()">
<i class="fa fa-plus"></i>{{labels.add_all_cta}}
</button>
<div>
<div class="tile-content" />
<div class="rop-add-account">
<button
v-if="!add_more_clicked && added_networks >= 2"
class="btn btn-secondary"
@click="addMore()"
>
<i class="fa fa-plus" />{{ labels.add_all_cta }}
</button>

<sign-in-btn v-if="this.add_more_clicked || this.added_networks < 2"></sign-in-btn>
</div>
</div>
<sign-in-btn v-if="add_more_clicked || added_networks < 2" />
</div>
</div>
</template>

<script>
import SignInBtn from '../sign-in-btn.vue';
module.exports = {
name: "add-account-tile",
export default {
name: "AddAccountTile",
components: {
SignInBtn,
},
data: function () {
return {
addAccountActive: false,
Expand All @@ -28,9 +34,6 @@
},
computed: {
},
components: {
SignInBtn,
},
methods: {
addMore: function () {
this.add_more_clicked = true;
Expand Down
12 changes: 9 additions & 3 deletions vue/src/vue-elements/reusables/button-checkbox.vue
@@ -1,10 +1,16 @@
<template>
<button class="btn input-group-addon column" :class="is_active" @click="toggleThis()" >{{label}}</button>
<button
class="btn input-group-addon column"
:class="is_active"
@click="toggleThis()"
>
{{ label }}
</button>
</template>

<script>
module.exports = {
name: 'button-checkbox',
export default {
name: 'ButtonCheckbox',
props: {
value: {
default: '0',
Expand Down
18 changes: 11 additions & 7 deletions vue/src/vue-elements/reusables/countdown.vue
@@ -1,18 +1,22 @@
<template>
<div class="toast rop-next-share-time" v-if="isOn && accounts_no > 0">
<span v-if="diff_seconds>0"> <b><i
class="fa fa-fast-forward"></i> {{labels.next_share}}</b> {{labels.in}}</span>
<small v-if="timediff !== ''">{{timediff}}</small>
</div>
<div
v-if="isOn && accounts_no > 0"
class="toast rop-next-share-time"
>
<span v-if="diff_seconds>0"> <b><i
class="fa fa-fast-forward"
/> {{ labels.next_share }}</b> {{ labels.in }}</span>
<small v-if="timediff !== ''">{{ timediff }}</small>
</div>
</template>

<script>
import moment from 'moment'
import 'moment-duration-format';
module.exports = {
name: 'cowntdown',
export default {
name: 'Cowntdown',
props: ['current_time'],
data() {
return {
Expand Down
38 changes: 29 additions & 9 deletions vue/src/vue-elements/reusables/counter-input.vue
@@ -1,18 +1,38 @@
<template>
<div class="input-group rop-counter-group">
<input class="form-input rop-counter" type="text" v-model="inputValueC" :id="id" :disabled="is_disabled">
<button class="btn input-group-btn increment-btn up" @mousedown="isPressed('up')" @mouseup="isReleased('up')" :disabled="is_disabled"><i
class="fa fa-fw fa-caret-up"></i></button>
<button class="btn input-group-btn increment-btn down" @mousedown="isPressed('down')"
@mouseup="isReleased('down')" :disabled="is_disabled"><i class="fa fa-fw fa-caret-down"></i></button>
</div>
<div class="input-group rop-counter-group">
<input
:id="id"
v-model="inputValueC"
class="form-input rop-counter"
type="text"
:disabled="is_disabled"
>
<button
class="btn input-group-btn increment-btn up"
:disabled="is_disabled"
@mousedown="isPressed('up')"
@mouseup="isReleased('up')"
>
<i
class="fa fa-fw fa-caret-up"
/>
</button>
<button
class="btn input-group-btn increment-btn down"
:disabled="is_disabled"
@mousedown="isPressed('down')"
@mouseup="isReleased('down')"
>
<i class="fa fa-fw fa-caret-down" />
</button>
</div>
</template>

<script>
let intervalID = null
module.exports = {
name: 'counter-input',
export default {
name: 'CounterInput',
props: {
id: {
default: ''
Expand Down
30 changes: 20 additions & 10 deletions vue/src/vue-elements/reusables/empty-active-accounts.vue
@@ -1,16 +1,26 @@
<template>
<div class="empty">
<div class="empty-icon">
<i class="fa fa-3x fa-user-circle-o"></i>
</div>
<p class="empty-title h5">{{labels.no_active_accounts}}</p>
<p class="empty-subtitle" v-html="labels.no_active_accounts_desc"></p>
<button class="btn btn-primary" @click="goToAccounts()">{{labels.go_to_accounts_btn}}</button>
</div>
<div class="empty">
<div class="empty-icon">
<i class="fa fa-3x fa-user-circle-o" />
</div>
<p class="empty-title h5">
{{ labels.no_active_accounts }}
</p>
<p
class="empty-subtitle"
v-html="labels.no_active_accounts_desc"
/>
<button
class="btn btn-primary"
@click="goToAccounts()"
>
{{ labels.go_to_accounts_btn }}
</button>
</div>
</template>
<script>
module.exports = {
name: 'empty-active-accounts',
export default {
name: 'EmptyActiveAccounts',
data: function () {
return {
labels: this.$store.state.labels.accounts,
Expand Down
240 changes: 141 additions & 99 deletions vue/src/vue-elements/reusables/multiple-select.vue
@@ -1,44 +1,86 @@
<template>
<div class="form-autocomplete" style="width: 100%;" v-on-clickaway="closeDropdown">
<!-- autocomplete input container -->
<div class="form-autocomplete-input form-input" :class="is_focused">
<div
v-on-clickaway="closeDropdown"
class="form-autocomplete"
style="width: 100%;"
>
<!-- autocomplete input container -->
<div
class="form-autocomplete-input form-input"
:class="is_focused"
>
<!-- autocomplete chips -->
<label
v-for="( option, index ) in selected"
:key="index"
class="chip"
>
{{ option.name }}
<a
href="#"
class="btn btn-clear"
aria-label="Close"
role="button"
@click.prevent="removeSelected(index)"
/>
</label>

<!-- autocomplete chips -->
<label class="chip" v-for="( option, index ) in selected">
{{option.name}}
<a href="#" class="btn btn-clear" aria-label="Close" @click.prevent="removeSelected(index)"
role="button"></a>
</label>

<!-- autocomplete real input box -->
<input style="height: 1.0rem;" class="form-input" type="text" ref="search" v-model="search"
:placeholder="autocomplete_placeholder" @click="magic_flag = true" @focus="magic_flag = true"
@keyup="magic_flag = true" @keydown.8="popLast()" @keydown.38="highlightItem(true)"
@keydown.40="highlightItem()" :disabled="is_disabled">
</div>
<!-- autocomplete real input box -->
<input
ref="search"
v-model="search"
style="height: 1.0rem;"
class="form-input"
type="text"
:placeholder="autocomplete_placeholder"
:disabled="is_disabled"
@click="magic_flag = true"
@focus="magic_flag = true"
@keyup="magic_flag = true"
@keydown.8="popLast()"
@keydown.38="highlightItem(true)"
@keydown.40="highlightItem()"
>
</div>

<!-- autocomplete suggestion list -->
<ul class="menu" ref="autocomplete_results" :class="is_visible"
style="overflow-y: scroll; max-height: 120px">
<!-- menu list chips -->
<li class="menu-item" v-for="( option, index ) in options" v-if="filterSearch(option)">
<a href="#" @click.prevent="addToSelected(index)" @keydown.38="highlightItem(true)"
@keydown.40="highlightItem()">
<div class="tile tile-centered">
<div class="tile-content" v-html="markMatch(option.name, search)"></div>
</div>
</a>
</li>
<li v-if="has_results">
<a href="#">
<div class="tile tile-centered">
<div class="tile-content"><i>{{labels.multiselect_not_found}}"{{search}}" ...</i></div>
</div>
</a>
</li>
</ul>
</div>

<!-- autocomplete suggestion list -->
<ul
ref="autocomplete_results"
class="menu"
:class="is_visible"
style="overflow-y: scroll; max-height: 120px"
>
<!-- menu list chips -->
<li
v-for="( option, index ) in options"
:key="index"
class="menu-item"
>
<template v-if="filterSearch(option)">
<a
href="#"
@click.prevent="addToSelected(index)"
@keydown.38="highlightItem(true)"
@keydown.40="highlightItem()"
>
<div class="tile tile-centered">
<div
class="tile-content"
v-html="markMatch(option.name, search)"
/>
</div>
</a>
</template>
</li>
<li v-if="has_results">
<a href="#">
<div class="tile tile-centered">
<div class="tile-content"><i>{{ labels.multiselect_not_found }}"{{ search }}" ...</i></div>
</div>
</a>
</li>
</ul>
</div>
</template>

<script>
Expand All @@ -54,8 +96,8 @@
return false
}
module.exports = {
name: 'multiple-select',
export default {
name: 'MultipleSelect',
mixins: [clickaway],
props: {
options: {
Expand Down Expand Up @@ -97,57 +139,6 @@
type: Boolean
}
},
mounted() {
for (let selection of this.selected) {
if (selection.selected) {
let index = 0
for (let option of this.options) {
if (option.value === selection.value) {
this.options[index].selected = selection.selected
}
index++
}
}
}
},
updated(){
for (let selection of this.selected) {
if (selection.selected) {
let index = 0
for (let option of this.options) {
if (option.value === selection.value) {
this.options[index].selected = selection.selected
}
index++
}
}
}
},
created() {
let selected_items_no = 0;
for (let selection of this.selected) {
if (selection.selected) {
let index = 0;
for (let option of this.options) {
if (option.value === selection.value) {
this.options[index].selected = selection.selected;
selected_items_no++
}
index++
}
}
}
this.rand = Math.round(Math.random() * 1000);
let index = 0
for (let option of this.options) {
this.options[index].selected = false;
index++
}
},
data: function () {
return {
search: '',
Expand All @@ -159,14 +150,6 @@
rand: 0
}
},
watch: {
search: function (val) {
this.$emit('update', val)
},
selected: function (val) {
this.$emit( 'display-limiter-notice', this.selected.length)
}
},
computed: {
is_focused: function () {
return {
Expand Down Expand Up @@ -211,6 +194,65 @@
return true
}
},
watch: {
search: function (val) {
this.$emit('update', val)
},
selected: function (val) {
this.$emit( 'display-limiter-notice', this.selected.length)
}
},
mounted() {
for (let selection of this.selected) {
if (selection.selected) {
let index = 0
for (let option of this.options) {
if (option.value === selection.value) {
this.options[index].selected = selection.selected
}
index++
}
}
}
},
updated(){
for (let selection of this.selected) {
if (selection.selected) {
let index = 0
for (let option of this.options) {
if (option.value === selection.value) {
this.options[index].selected = selection.selected
}
index++
}
}
}
},
created() {
let selected_items_no = 0;
for (let selection of this.selected) {
if (selection.selected) {
let index = 0;
for (let option of this.options) {
if (option.value === selection.value) {
this.options[index].selected = selection.selected;
selected_items_no++
}
index++
}
}
}
this.rand = Math.round(Math.random() * 1000);
let index = 0
for (let option of this.options) {
this.options[index].selected = false;
index++
}
},
methods: {
closeDropdown: function () {
this.magic_flag = false
Expand Down
63 changes: 37 additions & 26 deletions vue/src/vue-elements/reusables/popover.vue
@@ -1,15 +1,26 @@
<template>
<div class="wpr-tooltip">
<div class="outlet" @mouseover="autoShowWithMode" @mouseleave="autoHideWithMode" @click="autoShowWithMode">
<slot name="outlet"></slot>
</div>
<div class="wpr-tooltip" :style="tooltipStyle">
<div class="inner">
<slot name="tooltip"></slot>
</div>
<div class="wpr-arrow" :style="arrowStyle"></div>
</div>
<div class="wpr-tooltip">
<div
class="outlet"
@mouseover="autoShowWithMode"
@mouseleave="autoHideWithMode"
@click="autoShowWithMode"
>
<slot name="outlet" />
</div>
<div
class="wpr-tooltip"
:style="tooltipStyle"
>
<div class="inner">
<slot name="tooltip" />
</div>
<div
class="wpr-arrow"
:style="arrowStyle"
/>
</div>
</div>
</template>

<script>
Expand All @@ -19,13 +30,6 @@
export default {
name: 'Tooltip',
data() {
return {
arrowStyle: {},
isShowing: false
}
},
props: {
// hover|click|manual
mode: {
Expand Down Expand Up @@ -73,6 +77,13 @@
default: EMPTY_FN
}
},
data() {
return {
arrowStyle: {},
isShowing: false
}
},
computed: {
tooltipStyle() {
let s = {}
Expand Down Expand Up @@ -109,6 +120,15 @@
console.log( 'the is show value : ' + the_value );
}
},
mounted() {
if ( this.mode === 'manual' && this.value ) {
this.show()
}
document.addEventListener( 'click', this.autoHideWithMode, false )
},
destroyed() {
document.removeEventListener( 'click', this.autoHideWithMode, false )
},
methods: {
updateArrowStyle() {
let s = {}
Expand Down Expand Up @@ -298,15 +318,6 @@
this.$emit( 'input', false )
}
}
},
mounted() {
if ( this.mode === 'manual' && this.value ) {
this.show()
}
document.addEventListener( 'click', this.autoHideWithMode, false )
},
destroyed() {
document.removeEventListener( 'click', this.autoHideWithMode, false )
}
}
</script>
Expand Down