Use separate tag preview endpoint
parent
46eb0fd97a
commit
a0d757adfc
|
@ -30,6 +30,7 @@ return [
|
|||
['name' => 'api#day', 'url' => '/api/days/{id}', 'verb' => 'GET'],
|
||||
|
||||
['name' => 'api#tags', 'url' => '/api/tags', 'verb' => 'GET'],
|
||||
['name' => 'api#tagPreviews', 'url' => '/api/tag-previews', 'verb' => 'GET'],
|
||||
|
||||
['name' => 'api#albums', 'url' => '/api/albums', 'verb' => 'GET'],
|
||||
|
||||
|
|
|
@ -253,8 +253,40 @@ class ApiController extends Controller
|
|||
$folder,
|
||||
);
|
||||
|
||||
// Preload all tag previews
|
||||
$this->timelineQuery->getTagPreviews($list, $folder);
|
||||
return new JSONResponse($list, Http::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*
|
||||
* Get previews for a tag
|
||||
*/
|
||||
public function tagPreviews(): JSONResponse
|
||||
{
|
||||
$user = $this->userSession->getUser();
|
||||
if (null === $user) {
|
||||
return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED);
|
||||
}
|
||||
|
||||
// Check tags enabled for this user
|
||||
if (!$this->tagsIsEnabled()) {
|
||||
return new JSONResponse(['message' => 'Tags not enabled for user'], Http::STATUS_PRECONDITION_FAILED);
|
||||
}
|
||||
|
||||
// If this isn't the timeline folder then things aren't going to work
|
||||
$folder = $this->getRequestFolder();
|
||||
if (null === $folder) {
|
||||
return new JSONResponse([], Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Get the tag
|
||||
$tagName = $this->request->getParam('tag');
|
||||
|
||||
// Run actual query
|
||||
$list = $this->timelineQuery->getTagPreviews(
|
||||
$tagName,
|
||||
$folder,
|
||||
);
|
||||
|
||||
return new JSONResponse($list, Http::STATUS_OK);
|
||||
}
|
||||
|
|
|
@ -88,66 +88,46 @@ trait TimelineQueryTags
|
|||
return $tags;
|
||||
}
|
||||
|
||||
public function getTagPreviews(array &$tags, Folder &$folder)
|
||||
public function getTagPreviews(string $tagName, Folder &$folder)
|
||||
{
|
||||
// This is really horrible but will have to do for now
|
||||
$sql = '';
|
||||
foreach ($tags as &$tag) {
|
||||
if (!empty($sql)) {
|
||||
$sql .= ' UNION ALL ';
|
||||
}
|
||||
|
||||
$query = $this->connection->getQueryBuilder();
|
||||
|
||||
// SELECT all photos with this tag
|
||||
$query->select('f.fileid', 'f.etag', 'stom.systemtagid')->from(
|
||||
'systemtag_object_mapping',
|
||||
'stom'
|
||||
)->where(
|
||||
$query->expr()->eq('stom.objecttype', $query->createNamedParameter('files')),
|
||||
$query->expr()->eq('stom.systemtagid', $query->createNamedParameter($tag['id'])),
|
||||
);
|
||||
|
||||
// WHERE these items are memories indexed photos
|
||||
$query->innerJoin('stom', 'memories', 'm', $query->expr()->eq('m.fileid', 'stom.objectid'));
|
||||
|
||||
// WHERE these photos are in the user's requested folder recursively
|
||||
// See the function above for an explanation of this hack
|
||||
$this->addSubfolderJoinParams($query, $folder, false);
|
||||
$query->innerJoin('m', 'filecache', 'f', $query->expr()->andX(
|
||||
$query->expr()->eq('f.fileid', 'm.fileid'),
|
||||
$query->createFunction('EXISTS (SELECT 1 from *PREFIX*cte_folders WHERE *PREFIX*cte_folders.fileid = `f`.parent)')
|
||||
));
|
||||
|
||||
// MAX 4
|
||||
$query->setMaxResults(4);
|
||||
|
||||
// Replace parameters
|
||||
$thisSql = self::replaceQueryParams($query, $query->getSQL());
|
||||
|
||||
// Add clause
|
||||
$sql .= "({$thisSql})";
|
||||
$query = $this->connection->getQueryBuilder();
|
||||
$tagId = $this->getSystemTagId($query, $tagName);
|
||||
if (false === $tagId) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// SELECT all photos with this tag
|
||||
$query->select('f.fileid', 'f.etag', 'stom.systemtagid')->from(
|
||||
'systemtag_object_mapping',
|
||||
'stom'
|
||||
)->where(
|
||||
$query->expr()->eq('stom.objecttype', $query->createNamedParameter('files')),
|
||||
$query->expr()->eq('stom.systemtagid', $query->createNamedParameter($tagId)),
|
||||
);
|
||||
|
||||
// WHERE these items are memories indexed photos
|
||||
$query->innerJoin('stom', 'memories', 'm', $query->expr()->eq('m.fileid', 'stom.objectid'));
|
||||
|
||||
// WHERE these photos are in the user's requested folder recursively
|
||||
// See the function above for an explanation of this hack
|
||||
$this->addSubfolderJoinParams($query, $folder, false);
|
||||
$query->innerJoin('m', 'filecache', 'f', $query->expr()->andX(
|
||||
$query->expr()->eq('f.fileid', 'm.fileid'),
|
||||
$query->createFunction('EXISTS (SELECT 1 from *PREFIX*cte_folders WHERE *PREFIX*cte_folders.fileid = `f`.parent)')
|
||||
));
|
||||
|
||||
// MAX 4
|
||||
$query->setMaxResults(4);
|
||||
|
||||
// FETCH tag previews
|
||||
$cursor = $this->executeQueryWithCTEs($query, $sql);
|
||||
$cursor = $this->executeQueryWithCTEs($query);
|
||||
$ans = $cursor->fetchAll();
|
||||
|
||||
// Post-process
|
||||
$previewMap = [];
|
||||
foreach ($ans as &$row) {
|
||||
$row['fileid'] = (int) $row['fileid'];
|
||||
$key = (int) $row['systemtagid'];
|
||||
unset($row['systemtagid']);
|
||||
if (!isset($previewMap[$key])) {
|
||||
$previewMap[$key] = [];
|
||||
}
|
||||
$previewMap[$key][] = $row;
|
||||
}
|
||||
|
||||
// Add previews to tags
|
||||
foreach ($tags as &$tag) {
|
||||
$tag['previews'] = $previewMap[$tag['id']] ?? [];
|
||||
}
|
||||
return $ans;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,9 @@ import { generateUrl } from '@nextcloud/router'
|
|||
import { getPreviewUrl } from "../../services/FileUtils";
|
||||
import { getCurrentUser } from '@nextcloud/auth';
|
||||
|
||||
import { NcCounterBubble } from '@nextcloud/vue'
|
||||
import { NcCounterBubble } from '@nextcloud/vue';
|
||||
import axios from '@nextcloud/axios';
|
||||
import * as utils from "../../services/Utils";
|
||||
|
||||
import GlobalMixin from '../../mixins/GlobalMixin';
|
||||
import { constants } from '../../services/Utils';
|
||||
|
@ -112,7 +114,28 @@ export default class Tag extends Mixins(GlobalMixin) {
|
|||
}
|
||||
|
||||
// Look for previews
|
||||
if (!this.data.previews) return;
|
||||
if (!this.data.previews) {
|
||||
try {
|
||||
const todayDayId = utils.dateToDayId(new Date());
|
||||
const url = generateUrl(`/apps/memories/api/tag-previews?tag=${this.data.name}`);
|
||||
const cacheUrl = `${url}&today=${Math.floor(todayDayId / 10)}`;
|
||||
const cache = await utils.getCachedData(cacheUrl);
|
||||
if (cache) {
|
||||
this.data.previews = cache as any;
|
||||
} else {
|
||||
const res = await axios.get(url);
|
||||
this.data.previews = res.data;
|
||||
|
||||
// Cache only if >= 4 previews
|
||||
if (this.data.previews.length >= 4) {
|
||||
utils.cacheData(cacheUrl, res.data);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
this.error = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset flag
|
||||
this.data.previews.forEach((p) => p.flag = 0);
|
||||
|
|
Loading…
Reference in New Issue