Skip to content

Commit ae45529

Browse files
committed
add deleteTerm
1 parent d3f8379 commit ae45529

File tree

14 files changed

+133
-32
lines changed

14 files changed

+133
-32
lines changed

special-pages/pages/history/app/components/Header.js

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -42,21 +42,7 @@ function Controls({ term, range }) {
4242
/**
4343
* Aria labels + title text is derived from the current result set.
4444
*/
45-
const ariaDisabled = useComputed(() => {
46-
const hasResults = results.value.items.length > 0;
47-
const hasTerm = term.value !== null && term.value.trim() !== '';
48-
const hasSelections = selected.value.size > 0;
49-
50-
// always disabled when there are no results
51-
if (!hasResults) return true;
52-
53-
// disabled if a search term is there, but no selections where made
54-
if (hasTerm && !hasSelections) return true;
55-
56-
// otherwise, it's not disabled
57-
return false;
58-
});
59-
45+
const ariaDisabled = useComputed(() => results.value.items.length === 0);
6046
const title = useComputed(() => (results.value.items.length === 0 ? t('delete_none') : ''));
6147

6248
/**
@@ -65,10 +51,9 @@ function Controls({ term, range }) {
6551
* and there are no selections
6652
*/
6753
const buttonTxt = useComputed(() => {
68-
const hasTerm = term.value !== null && term.value.trim() !== '';
6954
const hasSelections = selected.value.size > 0;
70-
const hasRange = range.value !== null;
71-
return hasTerm || hasSelections || hasRange ? t('delete_some') : t('delete_all');
55+
if (hasSelections) return t('delete_some');
56+
return t('delete_all');
7257
});
7358

7459
/**
@@ -79,12 +64,16 @@ function Controls({ term, range }) {
7964
* - or fallback to deleting all
8065
*/
8166
function onClick() {
67+
if (ariaDisabled.value === true) return;
8268
if (selected.value.size > 0) {
8369
return dispatch({ kind: 'delete-entries-by-index', value: [...selected.value] });
8470
}
8571
if (range.value !== null) {
8672
return dispatch({ kind: 'delete-range', value: range.value });
8773
}
74+
if (term.value !== null && term.value !== '') {
75+
return dispatch({ kind: 'delete-term', term: term.value });
76+
}
8877
dispatch({ kind: 'delete-all' });
8978
}
9079

special-pages/pages/history/app/components/SearchForm.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export function SearchForm({ term, domain }) {
3535
* @param {SubmitEvent} submitEvent
3636
*/
3737
function submit(submitEvent) {
38-
console.log('todo: handle form submit?', submitEvent);
38+
console.log('todo: handle a new form submit?', submitEvent);
3939
}
4040

4141
return (

special-pages/pages/history/app/global-state/HistoryServiceProvider.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const HistoryServiceContext = createContext({
1818
* @typedef {{kind: 'search-commit', params: URLSearchParams}
1919
* | {kind: 'delete-range'; value: string }
2020
* | {kind: 'delete-all'; }
21+
* | {kind: 'delete-term'; term: string }
2122
* | {kind: 'delete-entries-by-index'; value: number[] }
2223
* | {kind: 'open-url'; url: string, target: 'new-tab' | 'new-window' | 'same-tab' }
2324
* | {kind: 'show-entries-menu'; ids: string[]; indexes: number[] }
@@ -71,6 +72,11 @@ export function HistoryServiceProvider({ service, children }) {
7172
service.deleteRange('all').catch(console.error);
7273
break;
7374
}
75+
case 'delete-term': {
76+
// eslint-disable-next-line promise/prefer-await-to-then
77+
service.deleteTerm(action.term).catch(console.error);
78+
break;
79+
}
7480
case 'open-url': {
7581
service.openUrl(action.url, action.target);
7682
break;

special-pages/pages/history/app/history.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,27 @@ Response, note: always return the same query I sent:
122122
}
123123
```
124124

125+
### `deleteTerm`
126+
- Sent to delete a search term
127+
- Parameters: {@link "History Messages".DeleteTermParams}
128+
- If the user confirms, respond with `{ action: 'delete' }`
129+
- otherwise `{ action: 'none' }`
130+
- Response: {@link "History Messages".DeleteTermResponse}
131+
132+
**params**
133+
```json
134+
{
135+
"term": "youtube"
136+
}
137+
```
138+
139+
**response**
140+
```json
141+
{
142+
"action": "delete"
143+
}
144+
```
145+
125146
### `title_menu`
126147
{@link "History Messages".TitleMenuRequest}
127148

@@ -191,6 +212,7 @@ Sent when a right-click is issued on a section title (or when the three-dots but
191212

192213
### `entries_delete`
193214
{@link "History Messages".EntriesDeleteRequest}
215+
{@link "History Messages".EntriesDeleteRequest}
194216

195217
Sent when the delete key is pressed on an item, or a group of items
196218

special-pages/pages/history/app/history.service.js

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -262,12 +262,32 @@ export class HistoryService {
262262
}
263263

264264
/**
265-
* @param {string[]} ids
266-
* @param {number[]} indexes
265+
* @param {string} term
267266
*/
268-
_postDomainSearch(ids, indexes) {
269-
const target = this.query.data?.results[indexes[0]];
270-
console.log(target);
267+
deleteTerm(term) {
268+
console.log('📤 [deleteTerm]: ', JSON.stringify({ term }));
269+
return (
270+
this.history.messaging
271+
.request('deleteTerm', { term })
272+
// eslint-disable-next-line promise/prefer-await-to-then
273+
.then((resp) => {
274+
if (resp.action === 'delete') {
275+
this.query.update((_old) => {
276+
/** @type {QueryData} */
277+
const query = {
278+
lastQueryParams: null,
279+
info: {
280+
query: { term: '' },
281+
finished: true,
282+
},
283+
results: [],
284+
};
285+
return query;
286+
});
287+
}
288+
return resp;
289+
})
290+
);
271291
}
272292
}
273293

special-pages/pages/history/app/mocks/mock-transport.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,18 @@ export function mockTransport() {
126126
}
127127
return Promise.resolve({ action: 'none' });
128128
}
129+
case 'deleteTerm': {
130+
console.log('📤 [deleteTerm]: ', JSON.stringify(msg.params));
131+
// prettier-ignore
132+
const lines = [
133+
`deleteTerm: ${JSON.stringify(msg.params)}`,
134+
`To simulate deleting this term, press confirm`
135+
].join('\n',);
136+
if (confirm(lines)) {
137+
return Promise.resolve({ action: 'delete' });
138+
}
139+
return Promise.resolve({ action: 'none' });
140+
}
129141
case 'initialSetup': {
130142
/** @type {import('../../types/history.ts').InitialSetupResponse} */
131143
const initial = {

special-pages/pages/history/integration-tests/history-selections.spec.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,11 @@ test.describe('history selections', () => {
129129
await hp.openPage({});
130130
await hp.cannotDeleteAllWhenEmpty();
131131
});
132-
test('`deleteAll` button text changes when selections are made', async ({ page }, workerInfo) => {
132+
test('`deleteAll` button text changes to `delete` when selections are made', async ({ page }, workerInfo) => {
133133
const hp = HistoryTestPage.create(page, workerInfo).withEntries(2000);
134134
await hp.openPage({});
135135
await hp.selectsRowIndex(0);
136-
await hp.deleteAllButtonReflectsSelection();
136+
await hp.deletesSelection();
137137
});
138138
test('`delete` in header respects selection', async ({ page }, workerInfo) => {
139139
const hp = HistoryTestPage.create(page, workerInfo).withEntries(2000);
@@ -152,11 +152,11 @@ test.describe('history selections', () => {
152152
await hp.clicksDeleteInHeader({ action: 'delete' });
153153
await hp.didDeleteSelection([0, 1]);
154154
});
155-
test('`delete` in header is disabled for searches (no selections)', async ({ page }, workerInfo) => {
155+
test('`deleteAll` during search (no selections)', async ({ page }, workerInfo) => {
156156
const hp = HistoryTestPage.create(page, workerInfo).withEntries(2000);
157157
await hp.openPage({});
158158
await hp.types('example.com');
159-
await hp.deleteButtonIsDisabled();
159+
await hp.deletesAllForTerm('example.com');
160160
});
161161
test('removes all selections with ESC key', async ({ page }, workerInfo) => {
162162
const hp = HistoryTestPage.create(page, workerInfo).withEntries(2000);

special-pages/pages/history/integration-tests/history.page.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,15 @@ export class HistoryTestPage {
276276
await page.locator('header').getByRole('button', { name: 'Delete', exact: true }).click();
277277
}
278278

279+
/**
280+
* @param {import('../types/history.ts').DeleteRangeResponse} resp
281+
*/
282+
async clicksDeleteAllInHeader(resp) {
283+
const { page } = this;
284+
this._withDialogHandling(resp);
285+
await page.locator('header').getByRole('button', { name: 'Delete All', exact: true }).click();
286+
}
287+
279288
/**
280289
* @param {import('../types/history.ts').DeleteRangeResponse} resp
281290
*/
@@ -429,14 +438,20 @@ export class HistoryTestPage {
429438
await expect(page.getByRole('button', { name: 'Delete All', exact: true })).toHaveAttribute('aria-disabled', 'true');
430439
}
431440

432-
async deleteAllButtonReflectsSelection() {
441+
async deletesSelection() {
433442
const { page } = this;
434443
await page.locator('header').getByRole('button', { name: 'Delete', exact: true }).click();
435444
}
436445

437-
async deleteButtonIsDisabled() {
446+
async deletesAll() {
438447
const { page } = this;
439-
await expect(page.locator('header').getByRole('button', { name: 'Delete', exact: true })).toHaveAttribute('aria-disabled', 'true');
448+
await page.locator('header').getByRole('button', { name: 'Delete All', exact: true }).click();
449+
}
450+
451+
async deletesAllForTerm(term) {
452+
await this.deletesAll();
453+
const calls = await this.mocks.waitForCallCount({ method: 'deleteTerm', count: 1 });
454+
expect(calls[0].payload.params).toStrictEqual({ term });
440455
}
441456

442457
async pressesEscape() {

special-pages/pages/history/integration-tests/history.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ test.describe('history', () => {
120120
const hp = HistoryTestPage.create(page, workerInfo).withEntries(2000);
121121
await hp.openPage({});
122122
await hp.selectsToday();
123-
await hp.clicksDeleteInHeader({ action: 'delete' });
123+
await hp.clicksDeleteAllInHeader({ action: 'delete' });
124124
await hp.didDeleteRange('today');
125125
});
126126
test('3 dots menu on Section title', async ({ page }, workerInfo) => {
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"required": ["term"],
4+
"title": "Delete Term Params",
5+
"properties": {
6+
"term": {
7+
"type": "string"
8+
}
9+
}
10+
}
11+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"type": "object",
4+
"required": ["action"],
5+
"properties": {
6+
"action": {
7+
"$ref": "types/action-response.json"
8+
}
9+
}
10+
}
11+

special-pages/pages/history/types/history.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export interface HistoryMessages {
4949
notifications: OpenNotification | ReportInitExceptionNotification | ReportPageExceptionNotification;
5050
requests:
5151
| DeleteRangeRequest
52+
| DeleteTermRequest
5253
| EntriesDeleteRequest
5354
| EntriesMenuRequest
5455
| GetRangesRequest
@@ -104,6 +105,20 @@ export interface DeleteRangeParams {
104105
export interface DeleteRangeResponse {
105106
action: ActionResponse;
106107
}
108+
/**
109+
* Generated from @see "../messages/deleteTerm.request.json"
110+
*/
111+
export interface DeleteTermRequest {
112+
method: "deleteTerm";
113+
params: DeleteTermParams;
114+
result: DeleteTermResponse;
115+
}
116+
export interface DeleteTermParams {
117+
term: string;
118+
}
119+
export interface DeleteTermResponse {
120+
action: ActionResponse;
121+
}
107122
/**
108123
* Generated from @see "../messages/entries_delete.request.json"
109124
*/

0 commit comments

Comments
 (0)