Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


Gadgetto last won the day on August 8

Gadgetto had the most liked content!

Community Reputation

176 Excellent

About Gadgetto

  • Rank
    Sr. Member
  • Birthday 10/05/1966

Contact Methods

  • Website URL

Profile Information

  • Gender
  • Location
    Mattersburg / Austria

Recent Profile Visitors

574 profile views
  1. @NorbertH I'll contact you via PM!
  2. @bernhard & @wbmnfktr thanks guys for recommending me!
  3. I have the same problem. Tried to make strings translatable in module.info.php, but I get an error "__" is not a function. Do you mean "___" ...
  4. Hmm.. this feels a bit like a hack for me. And it doesn't work for sub-menu entries.
  5. @bernhard do you mean we can have different menu structure for admins and clients? This would be great!
  6. @kongondo initially suggested that I could also use URL segments and therefore the discussion. I'll stay with URL params which is OK in backend.
  7. Thanks for your infos guys! I'm probably still much too deadlocked from my MODX time. ProcessWire just makes things different and that's good!
  8. I didn't think I'd need to add executeRefresh(), executeReset(), executeThis(), executeThat(), ... methods. This would fragmentize the source of a module a lot. I thought it works like in frontend, where I can enable URL segments and then the parts of URL paths like /mymodule/this/that/ are simply assigned to urlSegement(1) = "this" ,urlSegement(2) = "that". And the request wouldn't be routed to /mymodule/this/that/ but /mymodule/. From this point of view, I don't see any advantage for using url segments in process modules. It could also be that I still don't understand how URL segments are working!? (which is probably the case)
  9. Hi @draganI don't have an ___executeRefresh() method. And as I read in the old thread you posted, it strengthens my view that url segments are not ideal for my purpose.
  10. Yep, the button URL leads to a 404 Process returned no content. But it should resolve the execute method.
  11. Here is the init() and ___execute() part of ProcessSnipWire: (please have a look at the "Refresh" button down below - at the end of source code) /** * Initialize the module. * (Called before any execute functions) * */ public function init() { parent::init(); // Get SnipWire module config. // (Holds merged data from DB and default config. // This works because of using the ModuleConfig class) $this->snipwireConfig = $this->wire('modules')->get('SnipWire'); // Get activated $currencies from SnipWire module config $this->currencies = $this->snipwireConfig->currencies; $this->snipWireRootUrl = rtrim($this->wire('pages')->get('snipwire')->url, '/') . '/'; $this->currentUrl = rtrim($this->wire('input')->url, '/') . '/'; } /** * The SnipWire Dashboard page. * * @return page markup * */ public function ___execute() { $modules = $this->wire('modules'); $user = $this->wire('user'); $config = $this->wire('config'); $input = $this->wire('input'); $sniprest = $this->wire('sniprest'); $this->browserTitle($this->_('SnipWire Dashboard')); $this->headline($this->_('SnipWire Dashboard')); if (!$user->hasPermission('snipwire-dashboard')) { $this->error($this->_('You dont have permisson to use the SnipWire Dashboard - please contact your admin!')); return ''; } $this->_includeAssets( self::assetsIncludeDaterangePicker | self::assetsIncludeCurrencyPicker | self::assetsIncludeApexCharts ); $startDate = $this->_getStartDate(); $endDate = $this->_getEndDate(); $currency = $this->_getCurrency(); $action = $this->_getInputAction(); $forceRefresh = false; if ($action == 'refresh') { $this->message(SnipREST::getMessagesText('cache_refreshed')); $forceRefresh = true; } elseif ($action == 'reset') { $this->message($this->_('Store performance date range set to default.')); $this->_resetDateRange(); } $packages = $sniprest->getDashboardData( "$startDate 00:00:00", "$endDate 23:59:59", $currency, SnipREST::cacheExpireDefault, $forceRefresh ); $dashboard = $this->_prepareDashboardData($packages); unset($packages); if (!$dashboard) { $out = '<div class="dashboard-empty">' . $this->_('Dashboard data could not be fetched') . '</div>'; return $this->_wrapDashboardOutput($out); } $out = $this->_buildDashboardFilter($startDate, $endDate, $currency); $out .= $this->_renderPerformanceBoxes( $dashboard[SnipRest::resourcePathDataPerformance], $currency ); $chart = $this->_renderChart( $dashboard[SnipRest::resourcePathDataOrdersSales], $dashboard[SnipRest::resourcePathDataOrdersCount], $currency ); /** @var InputfieldForm $wrapper */ $wrapper = $modules->get('InputfieldForm'); /** @var InputfieldMarkup $f */ $f = $modules->get('InputfieldMarkup'); $f->label = $this->_('Performance Chart'); $f->icon = 'bar-chart'; $f->value = $chart; $f->columnWidth = 100; $f->collapsed = Inputfield::collapsedNever; $wrapper->add($f); $out .= $wrapper->render(); /** @var InputfieldForm $wrapper */ $wrapper = $modules->get('InputfieldForm'); /** @var InputfieldMarkup $f */ $f = $modules->get('InputfieldMarkup'); $f->label = $this->_('Top Customers'); $f->icon = self::iconCustomer; $f->value = $this->_renderTableTopCustomers($dashboard[SnipRest::resourcePathCustomers]); $f->columnWidth = 50; $f->collapsed = Inputfield::collapsedNever; $wrapper->add($f); /** @var InputfieldMarkup $f */ $f = $modules->get('InputfieldMarkup'); $f->label = $this->_('Top Products'); $f->icon = self::iconProduct; $f->value = $this->_renderTableTopProducts($dashboard[SnipRest::resourcePathProducts], $currency); $f->columnWidth = 50; $f->collapsed = Inputfield::collapsedNever; $wrapper->add($f); $out .= $wrapper->render(); /** @var InputfieldForm $wrapper */ $wrapper = $modules->get('InputfieldForm'); /** @var InputfieldMarkup $f */ $f = $modules->get('InputfieldMarkup'); $f->label = $this->_('Recent Orders'); $f->icon = self::iconOrder; $f->value = $this->_renderTableRecentOrders($dashboard[SnipRest::resourcePathOrders]); $f->columnWidth = 100; $f->collapsed = Inputfield::collapsedNever; $wrapper->add($f); $out .= $wrapper->render(); /** @var InputfieldButton $btn */ $btn = $modules->get('InputfieldButton'); $btn->id = 'refresh-data'; //$btn->href = $this->currentUrl . '?action=refresh'; $btn->href = $this->currentUrl . 'refresh'; // <--- https://processwire.moduledev/pw/setup/snipwire/refresh // and leads to "The process returned no content." $btn->value = $this->_('Refresh'); $btn->icon = 'refresh'; /* $btn->addActionLink( $this->currentUrl . '?action=refresh_all', 'Refresh Complete Snipcart Cache', 'refresh' ); */ $btn->showInHeader(); $out .= $btn->render(); return $this->_wrapDashboardOutput($out); }
  12. Can anyone tell me what's the deeper reason for putting custom ProcessModule menus under "Setup"? It kind of feels wrong... especially for full featured Apps like my upcoming SnipWire. Wouldn't it be better to have a dedicated "Extras" menu or something else? I know I can place the menu entry for my module wherever I like, but I think we need a better standard. How do you think about this?
  13. I think I already tried to use url segments but in execute() method I'll get "404" errors. So URL segments doesn't seem to be fully supported in ProcessModules.
  14. You are right, it's a single process. Hooking into any method will still be in the same process and the visitor will need to consume the request time. I'll need to "launch" a new (background) process which will do the heavy lifting.
  15. Thank your for the kind words! 🙂 I don't know if this will make it into the first release version but it seems to be a necessary step. LazyCron, on the other hand, does not seem to be well suited. This would cause delays for website visitors. I was thinking more of a separate worker process, or multiple parallel processes, running asynchronously and externally triggered by a cron job or by Javascript runner. I have already implemented something like this for a newsletter module for MODX.
  • Create New...