mirror of
https://github.com/tdurieux/anonymous_github.git
synced 2026-09-13 14:18:57 +02:00
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",
|
"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",
|
"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",
|
"markdown.min.js": "markdown.ad7b1d71c3.min.js",
|
||||||
"pdf.min.js": "pdf.eaa7573247.min.js",
|
"pdf.min.js": "pdf.eaa7573247.min.js",
|
||||||
"notebook.min.js": "notebook.8844e2735f.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);
|
background: rgba(128, 128, 128, 0.15);
|
||||||
color: var(--color);
|
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); }
|
.files .file.active > a .tree-count { color: var(--ink-muted); }
|
||||||
|
|
||||||
/* Tree icon shapes */
|
/* Tree icon shapes */
|
||||||
@@ -1429,37 +1429,43 @@ a:hover {
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Collapsed folder: outlined square */
|
/* Compact folder outline with a tab; expansion adds a light tint. */
|
||||||
.tree-icon-folder {
|
.tree-icon-folder {
|
||||||
width: 9px;
|
width: 14px;
|
||||||
height: 9px;
|
height: 12px;
|
||||||
border-radius: 2px;
|
color: var(--ink-muted);
|
||||||
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;
|
|
||||||
opacity: 0.75;
|
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 {
|
.dark-mode .files .folder.open > a .tree-icon-folder {
|
||||||
background: #C9A03A;
|
color: #C9A03A;
|
||||||
border-color: #C9A03A;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tree-icon-file {
|
.tree-icon-file {
|
||||||
width: 6px;
|
width: 16px;
|
||||||
height: 6px;
|
font-size: 14px;
|
||||||
background: #5B7BA5;
|
text-align: center;
|
||||||
transform: rotate(45deg);
|
color: #5B7BA5;
|
||||||
border-radius: 1px;
|
|
||||||
margin: 0 2px;
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
}
|
||||||
.dark-mode .tree-icon-file {
|
.dark-mode .tree-icon-file,
|
||||||
background: #7BA3D0;
|
.dark-mode .files .file.active > a .tree-icon-file {
|
||||||
|
color: #7BA3D0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expand/collapse triangle */
|
/* 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._originalBranch = res.data.source.branch;
|
||||||
state.options = Object.assign({}, state.options, res.data.options);
|
state.options = Object.assign({}, state.options, res.data.options);
|
||||||
state.conference = res.data.conference;
|
state.conference = res.data.conference;
|
||||||
|
state._originalConference = res.data.conference;
|
||||||
state.repositoryID = res.data.source.repositoryID;
|
state.repositoryID = res.data.source.repositoryID;
|
||||||
state._originalRepositoryID = res.data.source.repositoryID;
|
state._originalRepositoryID = res.data.source.repositoryID;
|
||||||
if (res.data.options.expirationDate) {
|
if (res.data.options.expirationDate) {
|
||||||
@@ -1030,6 +1031,7 @@ export const anonymizeController = function (state, http, html, params, location
|
|||||||
state.source = res.data.source;
|
state.source = res.data.source;
|
||||||
state.options = Object.assign({}, state.options, res.data.options);
|
state.options = Object.assign({}, state.options, res.data.options);
|
||||||
state.conference = res.data.conference;
|
state.conference = res.data.conference;
|
||||||
|
state._originalConference = res.data.conference;
|
||||||
if (res.data.options.expirationDate) {
|
if (res.data.options.expirationDate) {
|
||||||
state.options.expirationDate = new Date(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.source = res.data.source;
|
||||||
state.options = Object.assign({}, state.options, res.data.options);
|
state.options = Object.assign({}, state.options, res.data.options);
|
||||||
state.conference = res.data.conference;
|
state.conference = res.data.conference;
|
||||||
|
state._originalConference = res.data.conference;
|
||||||
if (res.data.options.expirationDate) {
|
if (res.data.options.expirationDate) {
|
||||||
state.options.expirationDate = new Date(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 ==========
|
// ========== SHARED LOGIC ==========
|
||||||
function getConference() {
|
function getConference() {
|
||||||
if (!state.conference) return;
|
const conference = state.conference;
|
||||||
http.get("/api/conferences/" + state.conference).then(
|
state.conference_data = null;
|
||||||
|
if (!conference) return;
|
||||||
|
const preserveSavedOptions =
|
||||||
|
state.isUpdate && conference === state._originalConference;
|
||||||
|
http.get("/api/conferences/" + conference).then(
|
||||||
(res) => {
|
(res) => {
|
||||||
|
if (state.conference !== conference) return;
|
||||||
state.conference_data = res.data;
|
state.conference_data = res.data;
|
||||||
state.conference_data.startDate = new Date(state.conference_data.startDate);
|
state.conference_data.startDate = new Date(state.conference_data.startDate);
|
||||||
state.conference_data.endDate = new Date(state.conference_data.endDate);
|
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.expirationDate = new Date(state.conference_data.endDate);
|
||||||
state.options.expirationMode = "remove";
|
state.options.expirationMode = "remove";
|
||||||
state.options.update = state.conference_data.options.update;
|
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.notebook = state.conference_data.options.notebook;
|
||||||
state.options.link = state.conference_data.options.link;
|
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 open = matching.value ? opens[path] !== false : !!opens[path];
|
||||||
const truncated = folder && props.page?.options?.truncatedFolders?.includes(path.slice(1));
|
const truncated = folder && props.page?.options?.truncatedFolders?.includes(path.slice(1));
|
||||||
const count = props.page?.fileCounts?.[path.slice(1)] || 0;
|
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 label = h("span", { class: "tree-name" }, name);
|
||||||
const onClick = event => {
|
const onClick = event => {
|
||||||
focus(event.currentTarget);
|
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("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 () {
|
it("sanitizes Org output before trusting it", async function () {
|
||||||
const h = explorer(); let untrusted;
|
const h = explorer(); let untrusted;
|
||||||
h.context.Org = { Parser: function () { this.parse = () => ({ convert: () => ({ toString: () => '<img onerror="probe()">' }) }); }, ConverterHTML: {} };
|
h.context.Org = { Parser: function () { this.parse = () => ({ convert: () => ({ toString: () => '<img onerror="probe()">' }) }); }, ConverterHTML: {} };
|
||||||
|
|||||||
Reference in New Issue
Block a user