Adding manage assignment from edit container panel. Fixes #501
This commit is contained in:
parent
094a0e2391
commit
8503e9c9c5
4 changed files with 147 additions and 41 deletions
|
@ -56,19 +56,25 @@ const assignManager = {
|
||||||
return this.area.remove([siteStoreKey]);
|
return this.area.remove([siteStoreKey]);
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteContainer(userContextId) {
|
async deleteContainer(userContextId) {
|
||||||
const removeKeys = [];
|
const sitesByContainer = await this.getByContainer(userContextId);
|
||||||
this.area.get().then((siteConfigs) => {
|
this.area.remove(Object.keys(sitesByContainer));
|
||||||
|
},
|
||||||
|
|
||||||
|
async getByContainer(userContextId) {
|
||||||
|
const sites = {};
|
||||||
|
const siteConfigs = await this.area.get();
|
||||||
Object.keys(siteConfigs).forEach((key) => {
|
Object.keys(siteConfigs).forEach((key) => {
|
||||||
// For some reason this is stored as string... lets check them both as that
|
// For some reason this is stored as string... lets check them both as that
|
||||||
if (String(siteConfigs[key].userContextId) === String(userContextId)) {
|
if (String(siteConfigs[key].userContextId) === String(userContextId)) {
|
||||||
removeKeys.push(key);
|
const site = siteConfigs[key];
|
||||||
|
// In hindsight we should have stored this
|
||||||
|
// TODO file a follow up to clean the storage onLoad
|
||||||
|
site.hostname = key.replace(/^siteContainerMap@@_/, "");
|
||||||
|
sites[key] = site;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.area.remove(removeKeys);
|
return sites;
|
||||||
}).catch((e) => {
|
|
||||||
throw e;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -151,12 +157,8 @@ const assignManager = {
|
||||||
// let actionName;
|
// let actionName;
|
||||||
let remove;
|
let remove;
|
||||||
if (info.menuItemId === this.MENU_ASSIGN_ID) {
|
if (info.menuItemId === this.MENU_ASSIGN_ID) {
|
||||||
//actionName = "added";
|
|
||||||
// storageAction = this._setAssignment(info.pageUrl, userContextId, setOrRemove);
|
|
||||||
remove = false;
|
remove = false;
|
||||||
} else {
|
} else {
|
||||||
// actionName = "removed";
|
|
||||||
//storageAction = this.storageArea.remove(info.pageUrl);
|
|
||||||
remove = true;
|
remove = true;
|
||||||
}
|
}
|
||||||
await this._setOrRemoveAssignment(info.pageUrl, userContextId, remove);
|
await this._setOrRemoveAssignment(info.pageUrl, userContextId, remove);
|
||||||
|
@ -227,6 +229,10 @@ const assignManager = {
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_getByContainer(userContextId) {
|
||||||
|
return this.storageArea.getByContainer(userContextId);
|
||||||
|
},
|
||||||
|
|
||||||
async calculateContextMenu(tab) {
|
async calculateContextMenu(tab) {
|
||||||
// There is a focus issue in this menu where if you change window with a context menu click
|
// There is a focus issue in this menu where if you change window with a context menu click
|
||||||
// you get the wrong menu display because of async
|
// you get the wrong menu display because of async
|
||||||
|
@ -429,11 +435,11 @@ const messageHandler = {
|
||||||
return assignManager._getAssignment(tab);
|
return assignManager._getAssignment(tab);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
case "getAssignmentObjectByContainer":
|
||||||
|
response = assignManager._getByContainer(m.message.userContextId);
|
||||||
|
break;
|
||||||
case "setOrRemoveAssignment":
|
case "setOrRemoveAssignment":
|
||||||
response = browser.tabs.get(m.tabId).then((tab) => {
|
response = assignManager._setOrRemoveAssignment(m.url, m.userContextId, m.value);
|
||||||
const userContextId = assignManager.getUserContextIdFromCookieStore(tab);
|
|
||||||
return assignManager._setOrRemoveAssignment(tab.url, userContextId, m.value);
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
case "exemptContainerAssignment":
|
case "exemptContainerAssignment":
|
||||||
response = assignManager._exemptTab(m);
|
response = assignManager._exemptTab(m);
|
||||||
|
|
|
@ -19,6 +19,13 @@ html {
|
||||||
box-sizing: inherit;
|
box-sizing: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
margin-block-end: 0;
|
||||||
|
margin-block-start: 0;
|
||||||
|
margin-inline-end: 0;
|
||||||
|
margin-inline-start: 0;
|
||||||
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
border: 0;
|
border: 0;
|
||||||
border-spacing: 0;
|
border-spacing: 0;
|
||||||
|
@ -581,6 +588,10 @@ span ~ .panel-header-text {
|
||||||
padding-block-start: 4px;
|
padding-block-start: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.container-info-list tbody {
|
||||||
|
display: contents;
|
||||||
|
}
|
||||||
|
|
||||||
.clickable {
|
.clickable {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
@ -631,6 +642,32 @@ span ~ .panel-header-text {
|
||||||
padding-inline-start: 16px;
|
padding-inline-start: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#edit-sites-assigned {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#edit-sites-assigned h3 {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: normal;
|
||||||
|
padding-block-end: 5px;
|
||||||
|
padding-inline-end: 16px;
|
||||||
|
padding-inline-start: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#edit-sites-assigned table td {
|
||||||
|
display: flex;
|
||||||
|
padding-inline-end: 16px;
|
||||||
|
padding-inline-start: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#edit-sites-assigned .delete-assignment {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#edit-sites-assigned tr:hover > td > .delete-assignment {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
.column-panel-content form span {
|
.column-panel-content form span {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
block-size: 44px;
|
block-size: 44px;
|
||||||
|
@ -679,6 +716,10 @@ span ~ .panel-header-text {
|
||||||
padding-inline-start: 0;
|
padding-inline-start: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.edit-container-panel fieldset:last-of-type {
|
||||||
|
margin-block-end: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.edit-container-panel input[type="text"] {
|
.edit-container-panel input[type="text"] {
|
||||||
block-size: 36px;
|
block-size: 36px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
|
|
|
@ -119,7 +119,9 @@ const Logic = {
|
||||||
},
|
},
|
||||||
|
|
||||||
addEnterHandler(element, handler) {
|
addEnterHandler(element, handler) {
|
||||||
element.addEventListener("click", handler);
|
element.addEventListener("click", (e) => {
|
||||||
|
handler(e);
|
||||||
|
});
|
||||||
element.addEventListener("keydown", (e) => {
|
element.addEventListener("keydown", (e) => {
|
||||||
if (e.keyCode === 13) {
|
if (e.keyCode === 13) {
|
||||||
handler(e);
|
handler(e);
|
||||||
|
@ -208,6 +210,11 @@ const Logic = {
|
||||||
return this._currentIdentity;
|
return this._currentIdentity;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
currentUserContextId() {
|
||||||
|
const identity = Logic.currentIdentity();
|
||||||
|
return Logic.userContextId(identity.cookieStoreId);
|
||||||
|
},
|
||||||
|
|
||||||
sendTelemetryPayload(message = {}) {
|
sendTelemetryPayload(message = {}) {
|
||||||
if (!message.event) {
|
if (!message.event) {
|
||||||
throw new Error("Missing event name for telemetry");
|
throw new Error("Missing event name for telemetry");
|
||||||
|
@ -234,10 +241,18 @@ const Logic = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
setOrRemoveAssignment(tab, value) {
|
getAssignmentObjectByContainer(userContextId) {
|
||||||
|
return browser.runtime.sendMessage({
|
||||||
|
method: "getAssignmentObjectByContainer",
|
||||||
|
message: {userContextId}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setOrRemoveAssignment(url, userContextId, value) {
|
||||||
return browser.runtime.sendMessage({
|
return browser.runtime.sendMessage({
|
||||||
method: "setOrRemoveAssignment",
|
method: "setOrRemoveAssignment",
|
||||||
tabId: tab.id,
|
url,
|
||||||
|
userContextId,
|
||||||
value
|
value
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -437,7 +452,8 @@ Logic.registerPanel(P_CONTAINERS_LIST, {
|
||||||
const currentTabElement = document.getElementById("current-tab");
|
const currentTabElement = document.getElementById("current-tab");
|
||||||
const assignmentCheckboxElement = document.getElementById("container-page-assigned");
|
const assignmentCheckboxElement = document.getElementById("container-page-assigned");
|
||||||
assignmentCheckboxElement.addEventListener("change", () => {
|
assignmentCheckboxElement.addEventListener("change", () => {
|
||||||
Logic.setOrRemoveAssignment(currentTab, !assignmentCheckboxElement.checked);
|
const userContextId = Logic.userContextId(currentTab.cookieStoreId);
|
||||||
|
Logic.setOrRemoveAssignment(currentTab.url, userContextId, !assignmentCheckboxElement.checked);
|
||||||
});
|
});
|
||||||
currentTabElement.hidden = !currentTab;
|
currentTabElement.hidden = !currentTab;
|
||||||
this.setupAssignmentCheckbox(false);
|
this.setupAssignmentCheckbox(false);
|
||||||
|
@ -561,7 +577,7 @@ Logic.registerPanel(P_CONTAINER_INFO, {
|
||||||
const identity = Logic.currentIdentity();
|
const identity = Logic.currentIdentity();
|
||||||
browser.runtime.sendMessage({
|
browser.runtime.sendMessage({
|
||||||
method: identity.hasHiddenTabs ? "showTabs" : "hideTabs",
|
method: identity.hasHiddenTabs ? "showTabs" : "hideTabs",
|
||||||
userContextId: Logic.userContextId(identity.cookieStoreId)
|
userContextId: Logic.currentUserContextId()
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
window.close();
|
window.close();
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
|
@ -633,7 +649,7 @@ Logic.registerPanel(P_CONTAINER_INFO, {
|
||||||
// Let's retrieve the list of tabs.
|
// Let's retrieve the list of tabs.
|
||||||
return browser.runtime.sendMessage({
|
return browser.runtime.sendMessage({
|
||||||
method: "getTabs",
|
method: "getTabs",
|
||||||
userContextId: Logic.userContextId(identity.cookieStoreId),
|
userContextId: Logic.currentUserContextId(),
|
||||||
}).then(this.buildInfoTable);
|
}).then(this.buildInfoTable);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -743,27 +759,19 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
|
||||||
this.initializeRadioButtons();
|
this.initializeRadioButtons();
|
||||||
|
|
||||||
Logic.addEnterHandler(document.querySelector("#edit-container-panel-back-arrow"), () => {
|
Logic.addEnterHandler(document.querySelector("#edit-container-panel-back-arrow"), () => {
|
||||||
Logic.showPreviousPanel();
|
this._submitForm();
|
||||||
});
|
});
|
||||||
|
|
||||||
Logic.addEnterHandler(document.querySelector("#edit-container-cancel-link"), () => {
|
|
||||||
Logic.showPreviousPanel();
|
|
||||||
});
|
|
||||||
|
|
||||||
this._editForm = document.getElementById("edit-container-panel-form");
|
this._editForm = document.getElementById("edit-container-panel-form");
|
||||||
const editLink = document.querySelector("#edit-container-ok-link");
|
|
||||||
Logic.addEnterHandler(editLink, this._submitForm.bind(this));
|
|
||||||
editLink.addEventListener("submit", this._submitForm.bind(this));
|
|
||||||
this._editForm.addEventListener("submit", this._submitForm.bind(this));
|
this._editForm.addEventListener("submit", this._submitForm.bind(this));
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_submitForm() {
|
_submitForm() {
|
||||||
const identity = Logic.currentIdentity();
|
|
||||||
const formValues = new FormData(this._editForm);
|
const formValues = new FormData(this._editForm);
|
||||||
return browser.runtime.sendMessage({
|
return browser.runtime.sendMessage({
|
||||||
method: "createOrUpdateContainer",
|
method: "createOrUpdateContainer",
|
||||||
message: {
|
message: {
|
||||||
userContextId: Logic.userContextId(identity.cookieStoreId) || false,
|
userContextId: Logic.currentUserContextId() || false,
|
||||||
params: {
|
params: {
|
||||||
name: document.getElementById("edit-container-panel-name-input").value || Logic.generateIdentityName(),
|
name: document.getElementById("edit-container-panel-name-input").value || Logic.generateIdentityName(),
|
||||||
icon: formValues.get("container-icon") || DEFAULT_ICON,
|
icon: formValues.get("container-icon") || DEFAULT_ICON,
|
||||||
|
@ -779,6 +787,44 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
showAssignedContainers(assignments) {
|
||||||
|
const assignmentPanel = document.getElementById("edit-sites-assigned");
|
||||||
|
const assignmentKeys = Object.keys(assignments);
|
||||||
|
assignmentPanel.hidden = !(assignmentKeys.length > 0);
|
||||||
|
if (assignments) {
|
||||||
|
const tableElement = assignmentPanel.querySelector("table > tbody");
|
||||||
|
/* Remove previous assignment list,
|
||||||
|
after removing one we rerender the list */
|
||||||
|
while (tableElement.firstChild) {
|
||||||
|
tableElement.firstChild.remove();
|
||||||
|
}
|
||||||
|
assignmentKeys.forEach((siteKey) => {
|
||||||
|
const site = assignments[siteKey];
|
||||||
|
const trElement = document.createElement("tr");
|
||||||
|
/* As we don't have the full or correct path the best we can assume is the path is HTTPS and then replace with a broken icon later if it doesn't load.
|
||||||
|
This is pending a better solution for favicons from web extensions */
|
||||||
|
const assumedUrl = `https://${site.hostname}`;
|
||||||
|
trElement.innerHTML = escaped`
|
||||||
|
<td><img class="icon" src="${assumedUrl}/favicon.ico"></td>
|
||||||
|
<td title="${site.hostname}" class="truncate-text">${site.hostname}
|
||||||
|
<img
|
||||||
|
class="pop-button-image delete-assignment"
|
||||||
|
src="/img/container-delete.svg"
|
||||||
|
/>
|
||||||
|
</td>`;
|
||||||
|
const deleteButton = trElement.querySelector(".delete-assignment");
|
||||||
|
Logic.addEnterHandler(deleteButton, () => {
|
||||||
|
const userContextId = Logic.currentUserContextId();
|
||||||
|
Logic.setOrRemoveAssignment(assumedUrl, userContextId, true);
|
||||||
|
delete assignments[siteKey];
|
||||||
|
this.showAssignedContainers(assignments);
|
||||||
|
});
|
||||||
|
trElement.classList.add("container-info-tab-row", "clickable");
|
||||||
|
tableElement.appendChild(trElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
initializeRadioButtons() {
|
initializeRadioButtons() {
|
||||||
const colorRadioTemplate = (containerColor) => {
|
const colorRadioTemplate = (containerColor) => {
|
||||||
return escaped`<input type="radio" value="${containerColor}" name="container-color" id="edit-container-panel-choose-color-${containerColor}" />
|
return escaped`<input type="radio" value="${containerColor}" name="container-color" id="edit-container-panel-choose-color-${containerColor}" />
|
||||||
|
@ -808,8 +854,13 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
|
||||||
},
|
},
|
||||||
|
|
||||||
// This method is called when the panel is shown.
|
// This method is called when the panel is shown.
|
||||||
prepare() {
|
async prepare() {
|
||||||
const identity = Logic.currentIdentity();
|
const identity = Logic.currentIdentity();
|
||||||
|
|
||||||
|
const userContextId = Logic.currentUserContextId();
|
||||||
|
const assignments = await Logic.getAssignmentObjectByContainer(userContextId);
|
||||||
|
this.showAssignedContainers(assignments);
|
||||||
|
|
||||||
document.querySelector("#edit-container-panel-name-input").value = identity.name || "";
|
document.querySelector("#edit-container-panel-name-input").value = identity.name || "";
|
||||||
[...document.querySelectorAll("[name='container-color']")].forEach(colorInput => {
|
[...document.querySelectorAll("[name='container-color']")].forEach(colorInput => {
|
||||||
colorInput.checked = colorInput.value === identity.color;
|
colorInput.checked = colorInput.value === identity.color;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||||
<title>Containers browserAction Popup</title>
|
<title>Containers browserAction Popup</title>
|
||||||
<link rel="stylesheet" href="/css/popup.css">
|
<link rel="stylesheet" href="/css/popup.css">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
@ -125,9 +126,16 @@
|
||||||
<legend>Choose an icon</legend>
|
<legend>Choose an icon</legend>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</form>
|
</form>
|
||||||
<div class="panel-footer">
|
<div id="edit-sites-assigned" class="scrollable" hidden>
|
||||||
<a href="#" class="button secondary expanded footer-button cancel-button" id="edit-container-cancel-link">Cancel</a>
|
<table id="container-assignement-table" class="container-info-list">
|
||||||
<a class="button primary expanded footer-button" id="edit-container-ok-link">OK</a>
|
<thead>
|
||||||
|
<th colspan="3">
|
||||||
|
<h3>Sites assigned to this container</h3>
|
||||||
|
</th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Reference in a new issue