diff --git a/addon/bootstrap.js b/addon/bootstrap.js index e5944cd1..9e872868 100644 --- a/addon/bootstrap.js +++ b/addon/bootstrap.js @@ -37,7 +37,8 @@ async function startup({ id, version, resourceURI, rootURI }, reason) { ctx._globalThis = ctx; Services.scriptloader.loadSubScript( - `${rootURI}/chrome/content/scripts/__addonRef__.js`, + // `${rootURI}/chrome/content/scripts/__addonRef__.js`, + `${rootURI}/chrome/content/scripts/index.js`, ctx, ); Zotero.__addonInstance__.hooks.onStartup(); diff --git a/addon/chrome/content/citationEditor.xhtml b/addon/chrome/content/citationEditor.xhtml index daea2d50..30739cc8 100644 --- a/addon/chrome/content/citationEditor.xhtml +++ b/addon/chrome/content/citationEditor.xhtml @@ -1,21 +1,26 @@ - + + - + + + + + + + + - - + + + + + + + - - - + \ No newline at end of file diff --git a/addon/chrome/content/skin/default/editor.css b/addon/chrome/content/skin/default/editor.css index 2763655b..ec2ed17e 100644 --- a/addon/chrome/content/skin/default/editor.css +++ b/addon/chrome/content/skin/default/editor.css @@ -1,6 +1,7 @@ window#citation-editor { height: 500px; - width: 400px; + /* width: 400px; */ + width: 200px; padding: 1em; } diff --git a/scripts/build.mjs b/scripts/build.mjs index cff69a61..2c97f5e7 100644 --- a/scripts/build.mjs +++ b/scripts/build.mjs @@ -179,15 +179,19 @@ function prepareUpdateJson() { } export const esbuildOptions = { - entryPoints: ["src/index.ts"], + entryPoints: ["src/index.ts", "src/dialogs/editor/index.tsx"], define: { __env__: `"${env.NODE_ENV}"`, }, bundle: true, target: "firefox115", - outfile: path.join( + // outfile: path.join( + // buildDir, + // `addon/chrome/content/scripts/${config.addonRef}.js`, + // ), + outdir: path.join( buildDir, - `addon/chrome/content/scripts/${config.addonRef}.js`, + `addon/chrome/content/scripts`, ), // Don't turn minify on minify: env.NODE_ENV === "production", diff --git a/src/cita/itemWrapper.ts b/src/cita/itemWrapper.ts index aff2ebc7..94138d57 100644 --- a/src/cita/itemWrapper.ts +++ b/src/cita/itemWrapper.ts @@ -215,7 +215,7 @@ export default class ItemWrapper { if (save) this.saveHandler(); } - isValidField(fieldName: string) { + isValidField(fieldName: string): boolean{ return Zotero.ItemFields.isValidForType( Zotero.ItemFields.getID(fieldName), this.item.itemTypeID, diff --git a/src/cita/sourceItemWrapper.ts b/src/cita/sourceItemWrapper.ts index a5dcdd47..e1b0d967 100644 --- a/src/cita/sourceItemWrapper.ts +++ b/src/cita/sourceItemWrapper.ts @@ -440,12 +440,12 @@ class SourceItemWrapper extends ItemWrapper { // this.updateCitationLabels(); //deprecated } - getCitedPIDs(type: PIDType, options: { clean?: boolean }) { + getCitedPIDs(type: PIDType, options: { clean?: boolean, skipCitation?: Citation }) { const citedPIDs = this.citations.reduce( (citedPIDs: string[], citation: Citation) => { - // if (citation !== options.skipCitation) { + if (options.skipCitation == undefined || citation !== options.skipCitation) { // todo: check if I correctly updated this - if (citation !== undefined) { + // if (citation !== undefined) { const pid = citation.target.getPID(type, options.clean); if (pid && !citedPIDs.includes(pid)) { citedPIDs.push(pid); @@ -464,6 +464,7 @@ class SourceItemWrapper extends ItemWrapper { options: { alert: boolean; parentWindow?: Window; + skipCitation?: Citation; }, ) { const cleanPID = Wikicite.cleanPID(type, value); @@ -474,7 +475,7 @@ class SourceItemWrapper extends ItemWrapper { conflict = "citing"; } else { const cleanCitedPIDs = this.getCitedPIDs(type, { - clean: true, + clean: true, skipCitation: options.skipCitation }); if (cleanCitedPIDs.includes(cleanPID)) { conflict = "cited"; diff --git a/src/cita/zoteroOverlay.tsx b/src/cita/zoteroOverlay.tsx index eec11674..4e053e91 100644 --- a/src/cita/zoteroOverlay.tsx +++ b/src/cita/zoteroOverlay.tsx @@ -1,6 +1,7 @@ import Wikicite, { debug } from "./wikicite"; import Citations from "./citations"; import CitationsBoxContainer from "../containers/citationsBoxContainer"; +import CitationEditor from "../dialogs/editor/CitationEditor"; import Crossref from "./crossref"; import Extraction from "./extract"; // import LCN from './localCitationNetwork'; @@ -1208,6 +1209,60 @@ class ZoteroOverlay { ); return menuFunc; } + + /******************************************/ + // Dialog boxes (popups) + /******************************************/ + + citationEditor() { + const itemBox = new (window.customElements.get("item-box")!)(); + const dialogData: { [key: string | number]: any } = { + inputValue: "test", + checkboxValue: true, + loadCallback: (window: Window) => { + ztoolkit.log(dialogData, "Dialog Opened!"); + ztoolkit.log("Dialog Window - ", window); + window.document + .getElementById("citation-editor-div")! + .appendChild(itemBox); + }, + unloadCallback: () => { + ztoolkit.log(dialogData, "Dialog closed!"); + }, + }; + const citationEditor = new ztoolkit.Dialog(2, 1) + .addCell(0, 0, { + tag: "h1", + namespace: "html", + properties: { innerHTML: "Citation Editor" }, + }) + .addCell(1, 0, { + id: "citation-editor-div", + tag: "div", + namespace: "html", + }) + .addButton("Save") + .addButton("Cancel"); + + // document.getElementById("citation-editor")!.appendChild(itemBox); + + // const citationEditorRoot = createRoot( + // document.getElementById("citation-editor")!, + // ); + + // citationEditorRoot.render( + // Wikicite.getString(name)} + // onCancel={onCancel} + // onSave={onSave} + // />, + // ); + + citationEditor.setDialogData(dialogData).open("Citation Editor"); + } } export default ZoteroOverlay; diff --git a/src/components/itemPane/citationsBox.tsx b/src/components/itemPane/citationsBox.tsx index ec448ee2..21979b1c 100644 --- a/src/components/itemPane/citationsBox.tsx +++ b/src/components/itemPane/citationsBox.tsx @@ -8,6 +8,7 @@ import Citation from "../../cita/citation"; import SourceItemWrapper from "../../cita/sourceItemWrapper"; import WikidataButton from "./wikidataButton"; import ZoteroButton from "./zoteroButton"; +import { config } from "../../../package.json"; function CitationsBox(props: { editable: boolean; @@ -15,7 +16,6 @@ function CitationsBox(props: { sourceItem: SourceItemWrapper; onItemPopup: (event: React.MouseEvent) => void; onCitationPopup: (event: React.MouseEvent, index: number) => void; - // Button: any; }) { const [citations, setCitations] = useState([] as Citation[]); const [pidTypes, setPidTypes] = useState([] as PIDType[]); @@ -82,22 +82,21 @@ function CitationsBox(props: { * @returns {Zotero.Item} - Edited cited item. */ function openEditor(citation: Citation) { - // const args = { - // citation: citation, - // Wikicite: Wikicite, - // }; - // const retVals: { [key: string]: any } = {}; - // fix - // window.openDialog( - // "chrome://cita/content/citationEditor.xul", - // "", - // "chrome,dialog=no,modal,centerscreen,resizable=yes", - // args, - // retVals, - // ); - window.alert("citation editor not implemented yet"); - // return retVals.item; - return undefined; + // Zotero[config.addonInstance].data.zoteroOverlay.citationEditor(); + + const args = { + citation: citation, + Wikicite: Wikicite, + }; + const retVals: { [key: string]: any } = {}; + window.openDialog( + `chrome://${config.addonRef}/content/citationEditor.xhtml`, + "", + "chrome,dialog=no,modal,centerscreen,resizable=yes", + args, + retVals, + ); + return retVals.item; } function handleCitationAdd() { diff --git a/src/dialogs/editor/CitationEditor.tsx b/src/dialogs/editor/CitationEditor.tsx index 07ae1f40..4b6a5bd3 100644 --- a/src/dialogs/editor/CitationEditor.tsx +++ b/src/dialogs/editor/CitationEditor.tsx @@ -1,13 +1,22 @@ -import React, { useEffect, useState } from "react"; import PIDRow from "../../components/pidRow"; -import PropTypes from "prop-types"; +import * as React from "react"; +import { useEffect, useState } from "react"; +import * as PropTypes from "prop-types"; +import ItemWrapper from "../../cita/itemWrapper"; const visibleBaseFieldNames = ["title", "publicationTitle", "date"]; // Fixme: as a Citation Editor (not a target item editor) // consider providing at least some read only information about the citation // such as label of the source item, OCIs, and Zotero link status -const CitationEditor = (props: any) => { +const CitationEditor = (props: { + checkCitationPID: (type: string, value: string) => boolean; + item: ItemWrapper; + itemBox: any; + getString: (name: string) => string; + onCancel: () => void; + onSave: () => void; +}) => { const [pidTypes, setPidTypes] = useState(props.item.getPIDTypes()); useEffect(() => { @@ -23,30 +32,38 @@ const CitationEditor = (props: any) => { // if item's saveTx overwritten with itembox.refresh, // sometimes itembox gets stucked in a loop // overwrite _focusNextField as a workaround - props.itemBox._focusNextField = () => {}; + try { + props.itemBox._focusNextField = () => {}; - // const disableButton = props.itemBox.disableButton.bind(props.itemBox); - // props.itemBox.disableButton = function(button) { - // if ( - // button.value === '+' && - // this._dynamicFields.getElementsByAttribute('value', '+').length === 1 - // ) return; - // disableButton(button); - // } - props.itemBox.mode = "edit"; + // const disableButton = props.itemBox.disableButton.bind(props.itemBox); + // props.itemBox.disableButton = function(button) { + // if ( + // button.value === '+' && + // this._dynamicFields.getElementsByAttribute('value', '+').length === 1 + // ) return; + // disableButton(button); + // } + props.itemBox.mode = "edit"; - // itembox sometimes fails to update if saveOnEdit is set to false - // make sure item's saveTx is overwritten to prevent actual item saving - props.itemBox.saveOnEdit = true; - setHiddenFields(props.item.item.itemTypeID); - props.itemBox.item = props.item.item; + // itembox sometimes fails to update if saveOnEdit is set to false + // make sure item's saveTx is overwritten to prevent actual item saving + props.itemBox.saveOnEdit = true; + setHiddenFields(props.item.item.itemTypeID); + props.itemBox.item = props.item.item; - // props.itemBox.item.saveTx = function() { - // if (!props.itemBox.item._refreshed) { - // props.itemBox.refresh(); - // } - // } - props.itemBox.addHandler("itemtypechange", onItemTypeChange); + // props.itemBox.item.saveTx = function() { + // if (!props.itemBox.item._refreshed) { + // props.itemBox.refresh(); + // } + // } + props.itemBox.addHandler("itemtypechange", onItemTypeChange); + props.itemBox.open = true; + // props.itemBox.toggleAttribute("open", false); + // props.itemBox.toggleAttribute("open", true); + // alert("done rendering"); + } catch (error: any) { + alert(error); + } }, []); function onItemTypeChange() { @@ -55,7 +72,7 @@ const CitationEditor = (props: any) => { props.itemBox.refresh(); } - function setHiddenFields(itemTypeID: string) { + function setHiddenFields(itemTypeID: number) { const visibleFieldIDs = visibleBaseFieldNames.map((fieldName) => Zotero.ItemFields.getFieldIDFromTypeAndBase(itemTypeID, fieldName), ); @@ -70,9 +87,9 @@ const CitationEditor = (props: any) => { return ( // TS gives an error about using orient here //
-
+
    - {pidTypes.map((pidType: string) => ( + {pidTypes.map((pidType: PIDType) => ( {
@@ -97,8 +114,8 @@ const CitationEditor = (props: any) => { CitationEditor.propTypes = { checkCitationPID: PropTypes.func, - item: PropTypes.object, // ItemWrapper - itemBox: PropTypes.object, // zoteroitembox + item: PropTypes.instanceOf(ItemWrapper), + itemBox: PropTypes.object, // item-box, getString: PropTypes.func, onCancel: PropTypes.func, onSave: PropTypes.func, diff --git a/src/dialogs/editor/index.tsx b/src/dialogs/editor/index.tsx index ea07f42b..884076b2 100644 --- a/src/dialogs/editor/index.tsx +++ b/src/dialogs/editor/index.tsx @@ -1,17 +1,21 @@ import CitationEditor from "./CitationEditor"; import ItemWrapper from "../../cita/itemWrapper"; -import React from "react"; -import ReactDOM from "react-dom"; +import * as React from "react"; +import { createRoot } from "react-dom/client"; +import Citation from "../../cita/citation"; -declare const Components: any; +// const citation: Citation = (window as any).arguments[0][0]; +// const Wikicite: any = (window as any).arguments[0][1]; +// const retVals: { item: Zotero.Item } = (window as any).arguments[1]; -// import Services into the new window -Components.utils.import("resource://gre/modules/Services.jsm"); +let citation: Citation; +let Wikicite: any; +({ citation, Wikicite } = (window as any).arguments[0]); +const retVals: { item: Zotero.Item } = (window as any).arguments[1]; -const { citation, Wikicite } = window.arguments[0]; -const retVals = window.arguments[1]; +citation = citation as Citation; -let newItem: any; +let newItem: ItemWrapper; function onCancel() { retVals.item = false; @@ -21,7 +25,7 @@ function onCancel() { function onSave() { for (const pidType of newItem.getPIDTypes()) { const pid = newItem.getPID(pidType); - if (!checkPID(pidType, pid)) { + if (pid == undefined || !checkPID(pidType, pid)) { return; } } @@ -41,20 +45,46 @@ window.addEventListener("load", () => { document.title = Wikicite.getString("wikicite.editor.title"); newItem = new ItemWrapper(); newItem.fromJSON(citation.target.toJSON()); + + // remove the collapsible section: + // item box contains + // + // + // + // + // we want to replace the collapsible section with its body + const itemBox = document.getElementById("citation-editor-item-box")!; + // const collapsibleSection = itemBox.firstChild!; + // itemBox.firstChild!.replaceWith(itemBox.firstChild!.lastChild!); + // win.replaceChild(itemBox, itemBoxWrapper); + // itemBox.firstChild!.replaceWith(itemBox.firstChild!.lastChild!); + // just hide the head of the collapsible section + // (collapsibleSection as any).toggleAttribute("open", false); + // (collapsibleSection as any).toggleAttribute("open", true); + + (itemBox.firstChild!.firstChild! as HTMLElement).hidden = true; + // itemBox.removeCreator is calling itemBox.item.saveTx // even if itemBox.saveOnEdit is set to false; // overwrite saveTx as workaround - newItem.item.saveTx = () => - (document.getElementById("citation-editor-item-box") as any).refresh(); - ReactDOM.render( + newItem.item.saveTx = () => (itemBox as any).refresh(); + const root = createRoot(document.getElementById("root")!); + root.render( Wikicite.getString(name)} onCancel={onCancel} onSave={onSave} />, - document.getElementById("root"), ); + // itemBox.firstChild!.replaceWith(itemBox.firstChild!.lastChild!); + // alert("opening"); + // (collapsibleSection as any).toggleAttribute("open", false); + // (collapsibleSection as any).toggleAttribute("open", true); + // (collapsibleSection as any).open = true; + // alert("opened"); + // alert("rendered1"); });