mirror of
https://github.com/tdurieux/anonymous_github.git
synced 2026-09-12 13:48:58 +02:00
Merge pull request #813 from tdurieux/fix/saved-options-and-folder-icons
fix: preserve saved auto-update settings and clarify file tree icons
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"core.min.js": "core.c5bd53363a.min.js",
|
||||
"vendor.min.js": "vendor.741a424da5.min.js",
|
||||
"vendor.min.js": "vendor.0f10f9accb.min.js",
|
||||
"mermaid.min.js": "mermaid.f848a72d16.min.js",
|
||||
"all.min.css": "all.076c089579.min.css",
|
||||
"all.min.css": "all.7ac8730b9a.min.css",
|
||||
"markdown.min.js": "markdown.ad7b1d71c3.min.js",
|
||||
"pdf.min.js": "pdf.eaa7573247.min.js",
|
||||
"notebook.min.js": "notebook.8844e2735f.min.js",
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+30
-24
@@ -1419,7 +1419,7 @@ a:hover {
|
||||
background: rgba(128, 128, 128, 0.15);
|
||||
color: var(--color);
|
||||
}
|
||||
.files .file.active > a .tree-icon-file { background: #5B7BA5; }
|
||||
.files .file.active > a .tree-icon-file { color: #5B7BA5; }
|
||||
.files .file.active > a .tree-count { color: var(--ink-muted); }
|
||||
|
||||
/* Tree icon shapes */
|
||||
@@ -1429,37 +1429,43 @@ a:hover {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Collapsed folder: outlined square */
|
||||
/* Compact folder outline with a tab; expansion adds a light tint. */
|
||||
.tree-icon-folder {
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
border-radius: 2px;
|
||||
background: transparent;
|
||||
border: 1.2px solid var(--ink-muted);
|
||||
opacity: 0.45;
|
||||
}
|
||||
/* Open folder: filled brown square */
|
||||
.files .folder.open > a .tree-icon-folder {
|
||||
background: #A07D2E;
|
||||
border-color: #A07D2E;
|
||||
width: 14px;
|
||||
height: 12px;
|
||||
color: var(--ink-muted);
|
||||
opacity: 0.75;
|
||||
}
|
||||
.tree-icon-folder svg {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
fill: currentColor;
|
||||
fill-opacity: 0;
|
||||
stroke: currentColor;
|
||||
stroke-width: 1.2;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
.files .folder.open > a .tree-icon-folder {
|
||||
color: #A07D2E;
|
||||
opacity: 0.9;
|
||||
}
|
||||
.files .folder.open > a .tree-icon-folder svg {
|
||||
fill-opacity: 0.12;
|
||||
}
|
||||
.dark-mode .files .folder.open > a .tree-icon-folder {
|
||||
background: #C9A03A;
|
||||
border-color: #C9A03A;
|
||||
color: #C9A03A;
|
||||
}
|
||||
|
||||
.tree-icon-file {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background: #5B7BA5;
|
||||
transform: rotate(45deg);
|
||||
border-radius: 1px;
|
||||
margin: 0 2px;
|
||||
opacity: 0.7;
|
||||
width: 16px;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
color: #5B7BA5;
|
||||
}
|
||||
.dark-mode .tree-icon-file {
|
||||
background: #7BA3D0;
|
||||
.dark-mode .tree-icon-file,
|
||||
.dark-mode .files .file.active > a .tree-icon-file {
|
||||
color: #7BA3D0;
|
||||
}
|
||||
|
||||
/* Expand/collapse triangle */
|
||||
|
||||
+16
-3
@@ -1006,6 +1006,7 @@ export const anonymizeController = function (state, http, html, params, location
|
||||
state._originalBranch = res.data.source.branch;
|
||||
state.options = Object.assign({}, state.options, res.data.options);
|
||||
state.conference = res.data.conference;
|
||||
state._originalConference = res.data.conference;
|
||||
state.repositoryID = res.data.source.repositoryID;
|
||||
state._originalRepositoryID = res.data.source.repositoryID;
|
||||
if (res.data.options.expirationDate) {
|
||||
@@ -1030,6 +1031,7 @@ export const anonymizeController = function (state, http, html, params, location
|
||||
state.source = res.data.source;
|
||||
state.options = Object.assign({}, state.options, res.data.options);
|
||||
state.conference = res.data.conference;
|
||||
state._originalConference = res.data.conference;
|
||||
if (res.data.options.expirationDate) {
|
||||
state.options.expirationDate = new Date(res.data.options.expirationDate);
|
||||
}
|
||||
@@ -1062,6 +1064,7 @@ export const anonymizeController = function (state, http, html, params, location
|
||||
state.source = res.data.source;
|
||||
state.options = Object.assign({}, state.options, res.data.options);
|
||||
state.conference = res.data.conference;
|
||||
state._originalConference = res.data.conference;
|
||||
if (res.data.options.expirationDate) {
|
||||
state.options.expirationDate = new Date(res.data.options.expirationDate);
|
||||
}
|
||||
@@ -1486,12 +1489,20 @@ export const anonymizeController = function (state, http, html, params, location
|
||||
|
||||
// ========== SHARED LOGIC ==========
|
||||
function getConference() {
|
||||
if (!state.conference) return;
|
||||
http.get("/api/conferences/" + state.conference).then(
|
||||
const conference = state.conference;
|
||||
state.conference_data = null;
|
||||
if (!conference) return;
|
||||
const preserveSavedOptions =
|
||||
state.isUpdate && conference === state._originalConference;
|
||||
http.get("/api/conferences/" + conference).then(
|
||||
(res) => {
|
||||
if (state.conference !== conference) return;
|
||||
state.conference_data = res.data;
|
||||
state.conference_data.startDate = new Date(state.conference_data.startDate);
|
||||
state.conference_data.endDate = new Date(state.conference_data.endDate);
|
||||
// Conference defaults must not overwrite an existing submission's
|
||||
// saved settings when its edit form loads (#791).
|
||||
if (preserveSavedOptions) return;
|
||||
state.options.expirationDate = new Date(state.conference_data.endDate);
|
||||
state.options.expirationMode = "remove";
|
||||
state.options.update = state.conference_data.options.update;
|
||||
@@ -1500,7 +1511,9 @@ export const anonymizeController = function (state, http, html, params, location
|
||||
state.options.notebook = state.conference_data.options.notebook;
|
||||
state.options.link = state.conference_data.options.link;
|
||||
},
|
||||
() => { state.conference_data = null; }
|
||||
() => {
|
||||
if (state.conference === conference) state.conference_data = null;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,8 @@ export default {
|
||||
const open = matching.value ? opens[path] !== false : !!opens[path];
|
||||
const truncated = folder && props.page?.options?.truncatedFolders?.includes(path.slice(1));
|
||||
const count = props.page?.fileCounts?.[path.slice(1)] || 0;
|
||||
const icon = h("span", { class: folder ? "tree-icon-folder" : "tree-icon-file" });
|
||||
const icon = h("span", { class: folder ? "tree-icon-folder" : "far fa-file tree-icon-file", "aria-hidden": "true" },
|
||||
folder ? h("svg", { viewBox: "0 0 14 12", focusable: "false" }, h("path", { d: "M1.5 10.5v-9h4l1.5 2h5.5v7z" })) : null);
|
||||
const label = h("span", { class: "tree-name" }, name);
|
||||
const onClick = event => {
|
||||
focus(event.currentTarget);
|
||||
|
||||
Vendored
+18
-18
File diff suppressed because one or more lines are too long
@@ -45,6 +45,55 @@ function explorer() {
|
||||
}
|
||||
|
||||
describe("frontend production regressions", function () {
|
||||
describe("conference defaults on edit (#791)", function () {
|
||||
const conferenceData = () => ({
|
||||
startDate: "2026-01-01", endDate: "2026-12-31",
|
||||
options: { update: true, image: true, pdf: true, notebook: true, link: true },
|
||||
});
|
||||
function anonymize(params = {}) {
|
||||
const h = harness();
|
||||
h.defs.anonymizeController(h.scope, h.http, {}, params, {}, () => {}, Object.assign(() => 0, { cancel() {} }));
|
||||
return h;
|
||||
}
|
||||
for (const id of ["repoId", "pullRequestId", "gistId"]) {
|
||||
it(`preserves saved options when reopening a conference-linked ${id}`, async function () {
|
||||
const h = anonymize({ [id]: "saved" });
|
||||
h.requests[0].resolve({ data: { options: { update: true } } }); await h.flush();
|
||||
h.requests.at(-1).resolve({ data: {
|
||||
source: { fullName: "owner/repo", repositoryFullName: "owner/repo", branch: "main", commit: "abcdef", gistId: "123", pullRequestId: 1 },
|
||||
conference: "conf",
|
||||
options: { terms: [], update: false, image: false, expirationMode: "remove", expirationDate: "2026-11-01" },
|
||||
} }); await h.flush();
|
||||
h.watches.conference();
|
||||
h.requests.at(-1).resolve({ data: conferenceData() }); await h.flush();
|
||||
expect(h.scope.options.update).to.equal(false);
|
||||
expect(h.scope.options.image).to.equal(false);
|
||||
expect(h.scope.options.expirationDate.toISOString()).to.equal("2026-11-01T00:00:00.000Z");
|
||||
expect(h.scope.conference_data).not.to.equal(null);
|
||||
if (id === "repoId") {
|
||||
h.scope.anonymizeRepo({ target: {} });
|
||||
expect(h.requests.at(-1).body.options.update).to.equal(false);
|
||||
expect(h.requests.at(-1).url).to.equal("/api/repo/saved");
|
||||
}
|
||||
});
|
||||
}
|
||||
it("applies defaults when selecting a different conference", async function () {
|
||||
const h = anonymize();
|
||||
h.scope.isUpdate = true; h.scope._originalConference = "old";
|
||||
h.scope.conference = "new"; h.watches.conference();
|
||||
h.requests.at(-1).resolve({ data: conferenceData() }); await h.flush();
|
||||
expect(h.scope.options.update).to.equal(true);
|
||||
expect(h.scope.options.expirationDate.toISOString()).to.equal("2026-12-31T00:00:00.000Z");
|
||||
});
|
||||
it("ignores defaults arriving after a conference is deselected", async function () {
|
||||
const h = anonymize(); h.scope.conference = "conf"; h.watches.conference();
|
||||
const pending = h.requests.at(-1);
|
||||
h.scope.conference = ""; h.watches.conference();
|
||||
pending.resolve({ data: conferenceData() }); await h.flush();
|
||||
expect(h.scope.options.update).to.equal(false);
|
||||
expect(h.scope.conference_data).to.equal(null);
|
||||
});
|
||||
});
|
||||
it("sanitizes Org output before trusting it", async function () {
|
||||
const h = explorer(); let untrusted;
|
||||
h.context.Org = { Parser: function () { this.parse = () => ({ convert: () => ({ toString: () => '<img onerror="probe()">' }) }); }, ConverterHTML: {} };
|
||||
|
||||
Reference in New Issue
Block a user