Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenaka <diosmosis@users.noreply.github.com>2017-10-16 07:54:55 +0300
committerMatthieu Aubry <mattab@users.noreply.github.com>2017-10-16 07:54:55 +0300
commitd4e57274c765698e82e476de4ad6d1a81b65cc91 (patch)
tree3a36a9eb3d4e58d19123aa352908b60906c48115 /plugins/CoreConsole
parentc1422b533fef97b63b434befe57856ee348c1e46 (diff)
Convert period selector to angular & allow plugins to add periods to the frontend (#11873)
* Add generate:angular-component command to generate an angular component. * Do not modify Date prototype. * Move period selector code from calendar.js to new angular directive (just move, no refactoring). * Extract date picker code from period selector code and put into new directive. * Extract range picking code into separate component than period selector. * Extract single period calendar to separate component & extract period specific functionality to new extendable periods service. * Fixing regressions in period selector behavior. * Move bulk of period selector code from directive to controller, & fix variable name in date range picker template. * Fix issue w/ yesterday date value, remove need to give period selector directive translations and make sure periods can be extended in the frontend. * Make sure period selector still works outside of an angular routing context (ie, in embedded dashboard). * In period selector UI test, hide ajaxLoadingCalendar using CSS since it is now managed by angular. * Make sure selected period highlighting changes immediately after selecting, even if loading a new page. * Put period selector top level element ID & classes on correct elements to ensure certain styles work properly. * Make sure selected period text changes immediately after selecing period, even if loading a new page or changing the URL. * Make sure range start/end changes immediately when a period is selected & selected period date range stops being highlighted immediately when a range period is selected, even if loading a new page. * Updating expected screenshots. * Updating screenshots. * Assorted fixes for period selector refactor. - Filter out invalid period labels (can happen if INI config for allowed periods is incorrect). - When determining display text for range, don't try to format the startRangeDate/endRangeDate vars, they're both strings. - Use correct selector when closing period selector. * Set global piwik date/period values on location change, outside of period selector component. * Do not skip parsing date if it does not start with an int (since the JS can handle today/yesterday/now). * Assorted fixes for period selector refactor: - use $onChanges instead of watches in datepicker (watches get triggered every time, $onChanges doesn't) - don't use arrays for selected/highlighted dates (for some weird reason, changing one of these arrays results in angular thinking it changes 3 times instead of once) - don't redraw on triggered mouseover events (something triggers mouseover when a date is selected, probably jquery datepicker) - draw after a setTimeout when a date is selected so our drawing occurs after jquery datepicker draws * Achieving smoother rendering for period selector by removing click handlers jquery datepicker adds. Also fixed bug where selecting the current period type reset the view date for the date picker. * Bound range date in period selector by piwik min/max date, so inferred dates will always be within allowed pickable dates in picker. * Removing ES6 used by accident + fix for issue when switching from non-year to year period (ui-datepicker-current-day class does not get removed). * Fix for angularjs one way binding quirk: initial property value is set before $onInit not during construction. * Avoid an exception when a date input in the date range picker is empty. * Split up change/keyup event to solve strange race condition in IE 10 on browserstack. * Change period selector "click again" tooltip to "double click". * Remove tabindexes > 1 so period selector control can be tabbed through. * Show visual cue for invalid dates in date range picker. * Only hide period option tooltip if period is active period, not if period is selected period. * In period selector, disable apply button if range is invalid. Also fix case when \$.datepicker.parseDate returns null instead of throwing.
Diffstat (limited to 'plugins/CoreConsole')
-rw-r--r--plugins/CoreConsole/Commands/GenerateAngularComponent.php74
-rw-r--r--plugins/CoreConsole/Commands/GenerateAngularConstructBase.php72
-rw-r--r--plugins/CoreConsole/Commands/GenerateAngularDirective.php58
-rw-r--r--plugins/CoreConsole/Commands/GeneratePluginBase.php2
4 files changed, 150 insertions, 56 deletions
diff --git a/plugins/CoreConsole/Commands/GenerateAngularComponent.php b/plugins/CoreConsole/Commands/GenerateAngularComponent.php
new file mode 100644
index 0000000000..6342b78240
--- /dev/null
+++ b/plugins/CoreConsole/Commands/GenerateAngularComponent.php
@@ -0,0 +1,74 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+
+namespace Piwik\Plugins\CoreConsole\Commands;
+
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class GenerateAngularComponent extends GenerateAngularConstructBase
+{
+ protected function configure()
+ {
+ $this->setName('generate:angular-component')
+ ->setDescription('Generates a template for an AngularJS component')
+ ->addOption('pluginname', null, InputOption::VALUE_REQUIRED, 'The name of an existing plugin')
+ ->addOption('component', null, InputOption::VALUE_REQUIRED, 'The name of the component you want to create.');
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $pluginName = $this->getPluginName($input, $output);
+ $component = $this->getConstructName($input, $output, $optionName = 'component', $constructType = 'component');
+ $pluginPath = $this->getPluginPath($pluginName);
+
+ $componentLower = $this->getSnakeCaseName($component);
+
+ $targetDir = $pluginPath . '/angularjs/' . $componentLower;
+
+ if (is_dir($targetDir) || file_exists($targetDir)) {
+ throw new \Exception('The AngularJS component ' . $componentLower . ' already exists in plugin '
+ . $pluginName);
+ }
+
+ $exampleFolder = PIWIK_INCLUDE_PATH . '/plugins/ExamplePlugin';
+ $replace = array(
+ 'ExamplePlugin' => $pluginName,
+ 'example-component' => $componentLower,
+ 'componentClass' => lcfirst($component),
+ 'componentAs' => lcfirst($component),
+ 'Component' => $component,
+ );
+
+ $componentPath = '/angularjs/example-component';
+
+ $whitelistFiles = array(
+ '/angularjs',
+ $componentPath,
+ $componentPath . '/example-component.component.html',
+ $componentPath . '/example-component.component.js',
+ $componentPath . '/example-component.component.less',
+ );
+
+ $this->copyTemplateToPlugin($exampleFolder, $pluginName, $replace, $whitelistFiles);
+
+ $replacedBasePath = '/angularjs/' . $componentLower . '/' . $componentLower;
+ $js1 = $replacedBasePath . '.component.js';
+ $less1 = $replacedBasePath . '.component.less';
+
+ $this->writeSuccessMessage($output, array(
+ sprintf('AngularJS directive "%s" for plugin "%s" in "%s" generated', $component, $pluginName, $targetDir),
+ sprintf('In <comment>%1$s/%2$s.php</comment> you should now require the JS files', $pluginPath, $pluginName),
+ sprintf('<comment>%1$s%2$s</comment>', $pluginPath, $js1),
+ sprintf('and the less file <comment>%1$s%2$s</comment>.', $pluginPath, $less1),
+ 'If you are not familiar with this have a look at <comment>http://developer.piwik.org/guides/working-with-piwiks-ui</comment>'
+ ));
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreConsole/Commands/GenerateAngularConstructBase.php b/plugins/CoreConsole/Commands/GenerateAngularConstructBase.php
new file mode 100644
index 0000000000..41d8af385b
--- /dev/null
+++ b/plugins/CoreConsole/Commands/GenerateAngularConstructBase.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+
+namespace Piwik\Plugins\CoreConsole\Commands;
+
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+abstract class GenerateAngularConstructBase extends GeneratePluginBase
+{
+ /**
+ * Convert MyComponentName => my-component-name
+ * @param string $directiveCamelCase
+ * @return string
+ */
+ protected function getSnakeCaseName($camelCase)
+ {
+ return strtolower(preg_replace('/([a-zA-Z])(?=[A-Z])/', '$1-', $camelCase));
+ }
+
+ /**
+ * @param InputInterface $input
+ * @param OutputInterface $output
+ * @param string $optionName the name of the option to use.
+ * @param string $constructType 'directive', 'component', etc.
+ * @return string
+ * @throws \RuntimeException
+ */
+ protected function getConstructName(InputInterface $input, OutputInterface $output, $optionName, $constructType)
+ {
+ $testname = $input->getOption($optionName);
+
+ $validate = function ($testname) use ($constructType) {
+ if (empty($testname)) {
+ throw new \InvalidArgumentException("You have to enter a name for the $constructType");
+ }
+
+ if (!ctype_alnum($testname)) {
+ throw new \InvalidArgumentException("Only alphanumeric characters are allowed as a $constructType "
+ . "name. Use CamelCase if the name of your $constructType contains multiple words.");
+ }
+
+ return $testname;
+ };
+
+ if (empty($testname)) {
+ $dialog = $this->getHelperSet()->get('dialog');
+ $testname = $dialog->askAndValidate($output, "Enter the name of the $constructType you want to create: ",
+ $validate);
+ } else {
+ $validate($testname);
+ }
+
+ $testname = ucfirst($testname);
+
+ return $testname;
+ }
+
+ protected function getPluginName(InputInterface $input, OutputInterface $output)
+ {
+ $pluginNames = $this->getPluginNames();
+ $invalidName = 'You have to enter the name of an existing plugin';
+
+ return $this->askPluginNameAndValidate($input, $output, $pluginNames, $invalidName);
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreConsole/Commands/GenerateAngularDirective.php b/plugins/CoreConsole/Commands/GenerateAngularDirective.php
index afe0ce5581..27fb7a65e0 100644
--- a/plugins/CoreConsole/Commands/GenerateAngularDirective.php
+++ b/plugins/CoreConsole/Commands/GenerateAngularDirective.php
@@ -15,7 +15,7 @@ use Symfony\Component\Console\Output\OutputInterface;
/**
*/
-class GenerateAngularDirective extends GeneratePluginBase
+class GenerateAngularDirective extends GenerateAngularConstructBase
{
protected function configure()
{
@@ -28,10 +28,10 @@ class GenerateAngularDirective extends GeneratePluginBase
protected function execute(InputInterface $input, OutputInterface $output)
{
$pluginName = $this->getPluginName($input, $output);
- $directive = $this->getDirectiveName($input, $output);
+ $directive = $this->getConstructName($input, $output, $optionName = 'directive', $constructType = 'directive');
$pluginPath = $this->getPluginPath($pluginName);
- $directiveLower = $this->getDirectiveComponentName($directive);
+ $directiveLower = $this->getSnakeCaseName($directive);
$targetDir = $pluginPath . '/angularjs/' . $directiveLower;
@@ -75,56 +75,4 @@ class GenerateAngularDirective extends GeneratePluginBase
'If you are not familiar with this have a look at <comment>https://developer.piwik.org/guides/working-with-piwiks-ui</comment>'
));
}
-
- /**
- * Convert MyComponentName => my-component-name
- * @param string $directiveCamelCase
- * @return string
- */
- protected function getDirectiveComponentName($directiveCamelCase)
- {
- return strtolower(preg_replace('/([a-zA-Z])(?=[A-Z])/', '$1-', $directiveCamelCase));
- }
-
- /**
- * @param InputInterface $input
- * @param OutputInterface $output
- * @return string
- * @throws \RuntimeException
- */
- private function getDirectiveName(InputInterface $input, OutputInterface $output)
- {
- $testname = $input->getOption('directive');
-
- $validate = function ($testname) {
- if (empty($testname)) {
- throw new \InvalidArgumentException('You have to enter a name for the directive');
- }
-
- if (!ctype_alnum($testname)) {
- throw new \InvalidArgumentException('Only alphanumeric characters are allowed as a directive name. Use CamelCase if the name of your directive contains multiple words.');
- }
-
- return $testname;
- };
-
- if (empty($testname)) {
- $dialog = $this->getHelperSet()->get('dialog');
- $testname = $dialog->askAndValidate($output, 'Enter the name of the directive you want to create: ', $validate);
- } else {
- $validate($testname);
- }
-
- $testname = ucfirst($testname);
-
- return $testname;
- }
-
- protected function getPluginName(InputInterface $input, OutputInterface $output)
- {
- $pluginNames = $this->getPluginNames();
- $invalidName = 'You have to enter the name of an existing plugin';
-
- return $this->askPluginNameAndValidate($input, $output, $pluginNames, $invalidName);
- }
}
diff --git a/plugins/CoreConsole/Commands/GeneratePluginBase.php b/plugins/CoreConsole/Commands/GeneratePluginBase.php
index 1c49540d60..61db237479 100644
--- a/plugins/CoreConsole/Commands/GeneratePluginBase.php
+++ b/plugins/CoreConsole/Commands/GeneratePluginBase.php
@@ -348,7 +348,7 @@ abstract class GeneratePluginBase extends ConsoleCommand
/**
* @param InputInterface $input
* @param OutputInterface $output
- * @return array
+ * @return string
* @throws \RuntimeException
*/
protected function askPluginNameAndValidate(InputInterface $input, OutputInterface $output, $pluginNames, $invalidArgumentException)