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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
- Fix double report execution after wizard close
- Correct drilldown aggregation for numeric dimension indices
- Fix threshold copying when saving report as copy
- Restore Files action registration for the Vue-based Files app so "Show in Analytics" remains available on Nextcloud 31

## 5.8.0 - 2025-07-29
### Added
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"require": {
"php": "^8.0",
"php": "^8.2",
"phpoffice/phpspreadsheet": "^1.29.0"
}
}
187 changes: 172 additions & 15 deletions js/viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,36 +21,193 @@ if (!OCA.Analytics) {
*/
OCA.Analytics.Viewer = {

FILE_ACTION_ID: 'analytics',

ALLOWED_MIMES: ['text/csv'],

ICON_SVG: '<svg viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(0.10000000149011612, 0, 0, -0.10000000149011612, 0, 300.00000000000006)" fill="#000000" stroke="none"><path d="M 2930.352 2749.78 C 2925.702 2747.773 2308.418 2109.704 2291.364 2095.665 C 2239.121 2095.485 2427.326 2027.76 2436.627 2019.739 C 2447.479 2011.716 1958.671 850.86 1951.383 865.013 C 1914.03 937.553 1370.025 2453.28 1364.874 2460.434 C 1173.207 2726.635 1120.792 2701.436 927.421 2457.64 C 924.671 2454.172 231.036 953.16 167.473 810.777 C -10.81 409.706 52.158 256.599 169.46 235.745 C 292.679 213.839 298.237 317.452 571.515 886.725 L 1307.383 889.675 C 1331.731 892.11 1284.555 1137.002 1155.706 1181.052 C 1064.171 1235.418 750.443 1210.622 706.359 1219.215 C 701.983 1220.068 1121.635 2146.56 1121.635 2146.56 L 1517.579 1053.974 C 1687.297 605.131 1787.366 321.612 1802.871 299.549 C 1874.182 197.277 2040.375 219.336 2083.122 313.908 C 2137.95 435.208 2742.923 1901.25 2753.31 1895.603 C 2770.487 1886.264 2915.546 1824.41 2915.546 1824.41 C 2915.546 1824.41 2935.003 2749.78 2930.352 2749.78 Z"/></g></svg>',

registerFileActions: function () {
let mime_array = ['text/csv'];
let icon_url = OC.imagePath('analytics', 'app-dark');
OCA.Analytics.Viewer.registerNewFrontendAction();
//OCA.Analytics.Viewer.registerLegacyFileActions();
},

registerLegacyFileActions: function () {
if (typeof OCA === 'undefined' || typeof OCA.Files === 'undefined' || typeof OCA.Files.fileActions === 'undefined' || typeof OCA.Files.fileActions.registerAction !== 'function') {
return;
}

const iconUrl = OC.imagePath('analytics', 'app-dark');
const displayName = t('analytics', 'Show in Analytics');

for (let i = 0; i < mime_array.length; i++) {
let mime = mime_array[i];
for (let i = 0; i < OCA.Analytics.Viewer.ALLOWED_MIMES.length; i++) {
const mime = OCA.Analytics.Viewer.ALLOWED_MIMES[i];
OCA.Files.fileActions.registerAction({
name: 'analytics',
displayName: t('analytics', 'Show in Analytics'),
name: OCA.Analytics.Viewer.FILE_ACTION_ID,
displayName: displayName,
mime: mime,
permissions: OC.PERMISSION_READ,
icon: icon_url,
icon: iconUrl,
actionHandler: OCA.Analytics.Viewer.importFile
});
}
},

importFile: function (file, data) {
file = encodeURIComponent(file);
let dirLoad = data.dir.substr(1);
if (dirLoad !== '') {
dirLoad = dirLoad + '/';
registerNewFrontendAction: function (retries) {
if (typeof window === 'undefined') {
return;
}

const viewer = OCA.Analytics.Viewer;
const attemptsLeft = typeof retries === 'number' ? retries : 10;

const register = function () {
if (typeof window._nc_fileactions === 'undefined') {
window._nc_fileactions = [];
}

if (!Array.isArray(window._nc_fileactions)) {
return false;
}

if (window._nc_fileactions.some(function (action) {
return action && action.id === viewer.FILE_ACTION_ID;
})) {
return true;
}

const analyticsAction = {
id: viewer.FILE_ACTION_ID,
displayName: function () {
return t('analytics', 'Show in Analytics');
},
iconSvgInline: function () {
return viewer.ICON_SVG;
},
enabled: function (nodes) {
if (!Array.isArray(nodes) || nodes.length !== 1) {
return false;
}

const node = nodes[0];
if (!node) {
return false;
}

if (typeof node.type === 'string' && node.type !== 'file') {
return false;
}

const mimeCandidates = [];
if (typeof node.mime === 'string') {
mimeCandidates.push(node.mime.toLowerCase());
}
if (typeof node.mimetype === 'string') {
mimeCandidates.push(node.mimetype.toLowerCase());
}
if (node.attributes && typeof node.attributes === 'object') {
const attributeMime = node.attributes.mimetype || node.attributes.mime;
if (typeof attributeMime === 'string') {
mimeCandidates.push(attributeMime.toLowerCase());
}
}

const isMimeAllowed = mimeCandidates.some(function (value) {
return viewer.ALLOWED_MIMES.indexOf(value) !== -1;
});

if (!isMimeAllowed) {
return false;
}

if (typeof node.permissions === 'number' && typeof OC !== 'undefined' && typeof OC.PERMISSION_READ === 'number') {
return (node.permissions & OC.PERMISSION_READ) !== 0;
}

return true;
},
exec: function (node, view, dir) {
viewer.openInAnalytics(dir, node);
return null;
},
order: 110
};

window._nc_fileactions.push(analyticsAction);
return true;
};

const success = register();
if (!success && attemptsLeft > 0) {
window.setTimeout(function () {
viewer.registerNewFrontendAction(attemptsLeft - 1);
}, 500);
}
},

openInAnalytics: function (dir, nodeOrFile) {
let directory = '';
if (typeof dir === 'string') {
directory = dir;
}

if (directory && directory.charAt(0) === '/') {
directory = directory.substr(1);
}

if (!directory && nodeOrFile && typeof nodeOrFile === 'object') {
if (typeof nodeOrFile.dirname === 'string' && nodeOrFile.dirname !== '') {
directory = nodeOrFile.dirname;
} else if (typeof nodeOrFile.path === 'string') {
let path = nodeOrFile.path;
if (path.charAt(0) === '/') {
path = path.substr(1);
}
const lastSlash = path.lastIndexOf('/');
if (lastSlash !== -1) {
directory = path.substring(0, lastSlash);
}
}

if (directory && directory.charAt(0) === '/') {
directory = directory.substr(1);
}
}

if (directory && directory.slice(-1) !== '/') {
directory = directory + '/';
}

let fileName = '';
if (typeof nodeOrFile === 'string') {
fileName = nodeOrFile;
} else if (nodeOrFile && typeof nodeOrFile === 'object') {
if (typeof nodeOrFile.basename === 'string') {
fileName = nodeOrFile.basename;
} else if (typeof nodeOrFile.displayname === 'string') {
fileName = nodeOrFile.displayname;
} else if (typeof nodeOrFile.name === 'string') {
fileName = nodeOrFile.name;
}
}
window.location = OC.generateUrl('/apps/analytics/#/f/') + dirLoad + file;

const encodedFile = encodeURIComponent(fileName);
const targetUrl = OC.generateUrl('/apps/analytics/#/f/');
window.location = targetUrl + directory + encodedFile;
},

importFile: function (file, data) {
const dir = data && typeof data.dir === 'string' ? data.dir : '';
OCA.Analytics.Viewer.openInAnalytics(dir, file);
},
};

document.addEventListener('DOMContentLoaded', function () {
if (typeof OCA !== 'undefined' && typeof OCA.Files !== 'undefined' && typeof OCA.Files.fileActions !== 'undefined' && $('#header').hasClass('share-file') === false) {
OCA.Analytics.Viewer.registerFileActions();
if (typeof OCA !== 'undefined' && typeof OCA.Analytics !== 'undefined') {
const header = document.getElementById('header');
if (!(header && header.classList.contains('share-file'))) {
OCA.Analytics.Viewer.registerFileActions();
}
}
return true;
});
4 changes: 3 additions & 1 deletion lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use OCA\Analytics\Notification\Notifier;
use OCA\Analytics\Search\SearchProvider;
use OCA\Analytics\Listener\ReferenceListener;
use OCA\Analytics\Listener\LoadAdditionalScripts;
use OCA\Analytics\Reference\ReferenceProvider;
use OCA\Analytics\Capabilities;
use OCA\ShareReview\Sources\SourceEvent;
Expand All @@ -25,6 +26,7 @@
use OCP\AppFramework\Bootstrap\IRegistrationContext;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\User\Events\UserDeletedEvent;
use OCA\Files\Event\LoadAdditionalScriptsEvent;
use OCP\Collaboration\Reference\RenderReferenceEvent;
use Psr\Container\ContainerInterface;
use OCP\WorkflowEngine\Events\RegisterOperationsEvent;
Expand All @@ -45,7 +47,7 @@ public function register(IRegistrationContext $context): void {
$context->registerCapability(Capabilities::class);

// file actions are not working at the moment
// $context->registerEventListener(LoadAdditionalScriptsEvent::class, LoadAdditionalScripts::class);
$context->registerEventListener(LoadAdditionalScriptsEvent::class, LoadAdditionalScripts::class);
$context->registerEventListener(UserDeletedEvent::class, UserDeletedListener::class);
$context->registerEventListener(RegisterOperationsEvent::class, RegisterOperationsListener::class);
$context->registerEventListener(ContentProviderRegisterEvent::class, ContentProvider::class);
Expand Down