Skip to content

Commit c94ffa6

Browse files
committed
perf(quick-actions): eliminate dublicate api calld for each envelope
Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>
1 parent b7399db commit c94ffa6

File tree

8 files changed

+70
-82
lines changed

8 files changed

+70
-82
lines changed

appinfo/routes.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -510,11 +510,6 @@
510510
'url' => '/api/textBlocks/{id}/shares',
511511
'verb' => 'GET',
512512
],
513-
[
514-
'name' => 'actionStep#findAllStepsForAction',
515-
'url' => '/api/action-step/{actionId}/steps',
516-
'verb' => 'GET'
517-
],
518513
],
519514
'resources' => [
520515
'accounts' => ['url' => '/api/accounts'],

lib/Controller/ActionStepController.php

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,6 @@ public function __construct(
3333
$this->uid = $userId;
3434
}
3535

36-
/**
37-
* @NoAdminRequired
38-
*
39-
* @return JsonResponse
40-
*/
41-
#[TrapError]
42-
public function findAllStepsForAction(int $actionId): JsonResponse {
43-
if ($this->uid === null) {
44-
return JsonResponse::error('User not found', Http::STATUS_UNAUTHORIZED);
45-
}
46-
$actionSteps = $this->quickActionsService->findAllActionSteps($actionId, $this->uid);
47-
48-
return JsonResponse::success($actionSteps);
49-
}
50-
5136
/**
5237
* @NoAdminRequired
5338
* @param string $name

lib/Db/Actions.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,22 @@
2222
class Actions extends Entity implements JsonSerializable {
2323
protected $name;
2424
protected $accountId;
25+
protected $actionSteps = [];
26+
protected $icon = '';
2527

2628
public function __construct() {
2729
$this->addType('name', 'string');
2830
$this->addType('accountId', 'integer');
31+
$this->addType('actionSteps', 'array');
32+
$this->addType('icon', 'string');
33+
}
34+
35+
public function setActionSteps(array $actionSteps): void {
36+
$this->actionSteps = $actionSteps;
37+
}
38+
39+
public function setIcon(string $icon): void {
40+
$this->icon = $icon;
2941
}
3042

3143
#[ReturnTypeWillChange]
@@ -34,6 +46,8 @@ public function jsonSerialize() {
3446
'id' => $this->getId(),
3547
'name' => $this->getName(),
3648
'accountId' => $this->getAccountId(),
49+
'actionSteps' => $this->actionSteps,
50+
'icon' => $this->icon,
3751

3852
];
3953
}

lib/Service/QuickActionsService.php

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,18 @@ public function __construct(
3535
private ActionStepMapper $actionStepMapper,
3636
) {
3737
}
38-
3938
/**
4039
* @param string $userId
4140
* @return Actions[]
4241
*/
4342
public function findAll(string $userId): array {
44-
return $this->actionsMapper->findAll($userId);
43+
$actions = $this->actionsMapper->findAll($userId);
44+
foreach ($actions as $action) {
45+
$actionSteps = $this->actionStepMapper->findAllStepsForOneAction($action->getId(), $userId);
46+
$action->setActionSteps($actionSteps);
47+
$action->setIcon($actionSteps[0]->getName());
48+
}
49+
return $actions;
4550
}
4651

4752
/**
@@ -74,14 +79,6 @@ public function delete(int $actionId, string $userId): void {
7479
$this->actionsMapper->delete($action);
7580
}
7681

77-
/**
78-
* @param string $userId
79-
* @return ActionStep[]
80-
*/
81-
public function findAllActionSteps(int $actionId, string $userId): array {
82-
return $this->actionStepMapper->findAllStepsForOneAction($actionId, $userId);
83-
}
84-
8582
/**
8683
* @throws DoesNotExistException
8784
*/

src/components/Envelope.vue

Lines changed: 24 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,6 @@ import NoTrashMailboxConfiguredError
433433
from '../errors/NoTrashMailboxConfiguredError.js'
434434
import logger from '../logger.js'
435435
import { buildRecipients as buildReplyRecipients } from '../ReplyBuilder.js'
436-
import { findAllStepsForAction } from '../service/QuickActionsService.js'
437436
import { FOLLOW_UP_TAG_LABEL } from '../store/constants.js'
438437
import useMainStore from '../store/mainStore.js'
439438
import { mailboxHasRights } from '../util/acl.js'
@@ -534,7 +533,6 @@ export default {
534533
customSnoozeDateTime: new Date(moment().add(2, 'hours').minute(0).second(0).valueOf()),
535534
overwriteOneLineMobile: false,
536535
hoveringAvatar: false,
537-
filteredQuickActions: [],
538536
quickActionLoading: false,
539537
}
540538
},
@@ -764,60 +762,50 @@ export default {
764762
},
765763
].filter(option => option.timestamp !== null)
766764
},
767-
},
768-
watch: {
769-
storeActions() {
770-
this.filterAndEnrichQuickActions()
771-
},
772-
},
773-
async mounted() {
774-
this.onWindowResize()
775-
window.addEventListener('resize', this.onWindowResize)
776-
if (this.filteredQuickActions.length === 0) {
777-
await this.filterAndEnrichQuickActions()
778-
}
779-
},
780-
methods: {
781-
translateTagDisplayName,
782-
setSelected(value) {
783-
if (this.selected !== value) {
784-
this.$emit('update:selected', value)
785-
}
786-
},
787-
formatted() {
788-
return shortRelativeDatetime(new Date(this.data.dateInt * 1000))
789-
},
790-
async filterAndEnrichQuickActions() {
791-
this.filteredQuickActions = []
765+
filteredQuickActions() {
766+
const filteredQuickActions = []
792767
const quickActions = this.mainStore.getQuickActions().filter(action => action.accountId === this.data.accountId)
793768
for (const action of quickActions) {
794-
const steps = await findAllStepsForAction(action.id)
795-
const check = steps.every(step => {
796-
if (['markAsSpam', 'applyTag', 'markAsImportant', 'markAsFavorite'].includes(step.type) && !this.hasWriteAcl) {
769+
const check = action.actionSteps.every(step => {
770+
if (['markAsSpam', 'applyTag', 'markAsImportant', 'markAsFavorite'].includes(step.name) && !this.hasWriteAcl) {
797771
return false
798772
}
799-
if (['markAsRead', 'markAsUnread'].includes(step.type) && !this.hasSeenAcl) {
773+
if (['markAsRead', 'markAsUnread'].includes(step.name) && !this.hasSeenAcl) {
800774
return false
801775
}
802-
if (['moveThread', 'deleteThread'].includes(step.type) && !this.hasDeleteAcl) {
776+
if (['moveThread', 'deleteThread'].includes(step.name) && !this.hasDeleteAcl) {
803777
return false
804778
}
805779
return true
806780
})
807781
if (check) {
808-
this.filteredQuickActions.push({
782+
filteredQuickActions.push({
809783
...action,
810-
steps,
811-
icon: steps[0]?.name,
812784
})
813785
}
814786
}
787+
return filteredQuickActions
788+
},
789+
},
790+
mounted() {
791+
this.onWindowResize()
792+
window.addEventListener('resize', this.onWindowResize)
793+
},
794+
methods: {
795+
translateTagDisplayName,
796+
setSelected(value) {
797+
if (this.selected !== value) {
798+
this.$emit('update:selected', value)
799+
}
800+
},
801+
formatted() {
802+
return shortRelativeDatetime(new Date(this.data.dateInt * 1000))
815803
},
816804
async executeQuickAction(action) {
817805
this.closeQuickActionsMenu()
818806
this.quickActionLoading = true
819807
try {
820-
for (const step of action.steps) {
808+
for (const step of action.actionSteps) {
821809
switch (step.name) {
822810
case 'markAsSpam':
823811
this.layoutMessageViewThreaded ? await this.onToggleJunkThread() : this.onToggleJunk()

src/components/quickActions/Settings.vue

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ import IconDelete from 'vue-material-design-icons/TrashCanOutline.vue'
130130
131131
import Action from './Action.vue'
132132
import logger from '../../logger.js'
133-
import { createActionStep, deleteActionStep, findAllStepsForAction, updateActionStep } from '../../service/QuickActionsService.js'
133+
import { createActionStep, deleteActionStep, updateActionStep } from '../../service/QuickActionsService.js'
134134
import useMainStore from '../../store/mainStore.js'
135135
136136
export default {
@@ -217,8 +217,8 @@ export default {
217217
this.localAction = { id: null, name: '' }
218218
this.actions = []
219219
} else {
220-
this.localAction = { ...action }
221-
this.actions = await findAllStepsForAction(action.id)
220+
this.localAction = { id: action.id, name: action.name, accountId: action.accountId }
221+
this.actions = action.actionSteps
222222
this.highestOrder = Math.max(...this.actions.map(a => a.order), 0)
223223
this.editMode = true
224224
}
@@ -247,7 +247,7 @@ export default {
247247
for (const [index, action] of this.actions.entries()) {
248248
if (action?.id !== null && action?.id !== undefined) {
249249
try {
250-
await updateActionStep(action.id, action.name, action.order, action?.tagId, action?.mailboxId)
250+
this.actions[index] = await updateActionStep(action.id, action.name, action.order, action?.tagId, action?.mailboxId)
251251
} catch (error) {
252252
logger.error('Could not update quick action step', {
253253
error,
@@ -260,10 +260,12 @@ export default {
260260
this.actions[index] = createdStep
261261
}
262262
}
263+
this.localAction = quickAction
263264
}
264265
showSuccess(t('mail', 'Quick action updated'))
265266
} else {
266267
let quickAction
268+
let createdSteps = []
267269
try {
268270
quickAction = await this.mainStore.createQuickAction(this.localAction.name, this.account.id)
269271
} catch (error) {
@@ -275,17 +277,23 @@ export default {
275277
}
276278
try {
277279
for (const action of this.actions) {
278-
await createActionStep(action.name, action.order, quickAction.id, action?.tagId, action?.mailboxId)
280+
const createdStep = await createActionStep(action.name, action.order, quickAction.id, action?.tagId, action?.mailboxId)
281+
if (createdStep) {
282+
createdSteps.push(createdStep)
283+
}
279284
}
285+
this.actions = createdSteps
280286
} catch (error) {
281287
logger.error('Could not add step to quick action', {
282288
error,
283289
})
284290
showError(t('mail', 'Failed to add steps to quick action'))
285291
this.closeEditModal()
286292
}
293+
this.localAction = quickAction
287294
showSuccess(t('mail', 'Quick action created'))
288295
}
296+
this.mainStore.patchActionStepsLocally(this.localAction.id, this.actions)
289297
this.closeEditModal()
290298
},
291299
addQuickAction(name) {
@@ -321,9 +329,13 @@ export default {
321329
this.actions = this.actions.map((action, index) => ({ ...action, order: index + 1 }))
322330
},
323331
async deleteAction(item) {
332+
this.actions = this.actions.filter(action => action.order !== item.order).map((action, index) => ({ ...action, order: index + 1 }))
333+
this.highestOrder = Math.max(...this.actions.map(a => a.order), 0)
324334
if (item.id) {
325335
try {
326336
await deleteActionStep(item.id)
337+
const actions = this.actions.filter(action => action.id)
338+
this.mainStore.patchActionStepsLocally(this.localAction.id, actions)
327339
} catch (error) {
328340
logger.error('Could not delete action step', {
329341
error,
@@ -332,8 +344,6 @@ export default {
332344
return
333345
}
334346
}
335-
this.actions = this.actions.filter(action => action.order !== item.order).map((action, index) => ({ ...action, order: index + 1 }))
336-
this.highestOrder = Math.max(...this.actions.map(a => a.order), 0)
337347
},
338348
},
339349
}

src/service/QuickActionsService.js

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,6 @@ export async function deleteQuickAction(id) {
4444
})
4545
}
4646

47-
export async function findAllStepsForAction(actionId) {
48-
const url = generateUrl('/apps/mail/api/action-step/{id}/steps', { id: actionId })
49-
return handleHttpAuthErrors(async () => {
50-
const response = await axios.get(url)
51-
return response.data.data
52-
})
53-
54-
}
55-
5647
export async function createActionStep(name, order, actionId, tagId = null, mailboxId = null) {
5748
const url = generateUrl('/apps/mail/api/action-step')
5849
return handleHttpAuthErrors(async () => {

src/store/mainStore/actions.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2378,6 +2378,14 @@ export default function mainStoreActions() {
23782378
Vue.set(this.quickActions, index, quickAction)
23792379
}
23802380
},
2381+
patchActionStepsLocally(id, steps) {
2382+
const index = this.quickActions.findIndex(s => s.id === id)
2383+
if (index !== -1) {
2384+
const updatedQuickAction = this.quickActions[index]
2385+
updatedQuickAction.actionSteps = steps
2386+
Vue.set(this.quickActions, index, updatedQuickAction)
2387+
}
2388+
},
23812389
deleteQuickActionLocally(id) {
23822390
const index = this.quickActions.findIndex(s => s.id === id)
23832391
if (index !== -1) {

0 commit comments

Comments
 (0)