|
20 | 20 | */ |
21 | 21 |
|
22 | 22 | // Let user customize the css file name |
23 | | -const CSS_FILE_NAME = "@@file/classhelper.css"; |
| 23 | +const CSS_STYLESHEET_FILE_NAME = "@@file/classhelper.css"; |
24 | 24 |
|
25 | 25 | const CLASSHELPER_TAG_NAME = "roundup-classhelper"; |
26 | 26 | const CLASSHELPER_ATTRIBUTE_SEARCH_WITH = "data-search-with"; |
| 27 | +const CLASSHELPER_POPUP_FEATURES = (width, height) => `popup=yes,width=${width},height=${height}`; |
| 28 | +const CLASSHELPER_POPUP_URL = "about:blank"; |
| 29 | +const CLASSHELPER_POPUP_TARGET = "_blank"; |
27 | 30 |
|
28 | 31 | const ALTERNATIVE_DROPDOWN_PATHNAMES = { |
29 | 32 | "roles": "/rest/roles" |
@@ -102,16 +105,16 @@ class ClassHelper extends HTMLElement { |
102 | 105 | /** @type {HelpUrlProps} */ |
103 | 106 | helpurlProps = null; |
104 | 107 |
|
105 | | - /** no-op function */ |
106 | | - preventDefault = e => e.preventDefault(); |
107 | | - |
108 | 108 | /** |
109 | | - * The qualified domain name with protocol and port(if any) |
110 | | - * with the tracker name if any. |
111 | | - * eg. http://localhost:8080/demo or https://demo.roundup-tracker.org |
112 | | - * @type {string} */ |
| 109 | + * The qualified domain name with protocol and port(if any) |
| 110 | + * with the tracker name if any. |
| 111 | + * eg. http://localhost:8080/demo or https://demo.roundup-tracker.org |
| 112 | + * @type {string} */ |
113 | 113 | trackerBaseURL = null; |
114 | 114 |
|
| 115 | + /** no-op function */ |
| 116 | + preventDefault = e => e.preventDefault(); |
| 117 | + |
115 | 118 | connectedCallback() { |
116 | 119 | try { |
117 | 120 | this.helpurl = this.findClassHelpLink(); |
@@ -801,78 +804,90 @@ class ClassHelper extends HTMLElement { |
801 | 804 | * @param {FormData} formData |
802 | 805 | * @throws {Error} when fetching or parsing data from roundup rest api fails |
803 | 806 | */ |
804 | | - async openPopUp(apiURL, props, preSelectedValues, formData) { |
805 | | - if (!preSelectedValues) { |
806 | | - // Find preselected values |
807 | | - const input = document.getElementsByName(props.formProperty).item(0); |
808 | | - if (input.value) { |
809 | | - preSelectedValues = input.value.split(','); |
810 | | - } else { |
811 | | - preSelectedValues = []; |
812 | | - } |
813 | | - } |
814 | | - |
815 | | - const popupFeatures = `popup=yes,width=${props.width},height=${props.height}`; |
816 | | - this.popupRef = window.open("about:blank", "_blank", popupFeatures); |
| 807 | + async openPopUp(apiURL, props) { |
817 | 808 |
|
| 809 | + /** @type {Response} */ |
818 | 810 | let resp; |
| 811 | + /** @type {any} */ |
| 812 | + let collection; |
| 813 | + /** @type {string} */ |
| 814 | + let prevPageURL; |
| 815 | + /** @type {string} */ |
| 816 | + let nextPageURL; |
| 817 | + /** @type {string[]} */ |
| 818 | + let preSelectedValues = []; |
| 819 | + |
819 | 820 | try { |
820 | 821 | resp = await fetch(apiURL); |
821 | 822 | } catch (error) { |
822 | | - // Show message fail to load data |
823 | | - throw new Error("error fetching data from roundup rest api"); |
| 823 | + let message = `Error fetching data from roundup rest api`; |
| 824 | + message += `url: ${apiURL.toString()}\n`; |
| 825 | + if (resp?.status) { |
| 826 | + message += `response status: ${resp.status}\n`; |
| 827 | + } |
| 828 | + throw new Error(message, { cause: error }); |
824 | 829 | } |
825 | 830 |
|
826 | | - let json; |
827 | 831 | try { |
828 | | - json = await resp.json(); |
| 832 | + const json = await resp.json(); |
| 833 | + collection = json.data.collection; |
| 834 | + |
| 835 | + const links = json.data["@links"]; |
| 836 | + if (links?.prev?.length > 0) { |
| 837 | + prevPageURL = links.prev[0].uri; |
| 838 | + } |
| 839 | + if (links?.next.length > 0) { |
| 840 | + nextPageURL = links.next[0].uri; |
| 841 | + } |
829 | 842 | } catch (error) { |
830 | | - // Show message fail to parse json |
831 | | - throw new Error("error parsing json from roundup rest api"); |
| 843 | + let message = "Error parsing json from roundup rest api\n"; |
| 844 | + message += `url: ${apiURL.toString()}\n`; |
| 845 | + message += `response status: ${resp.status}`; |
| 846 | + throw new Error(message, { cause: error }); |
832 | 847 | } |
833 | 848 |
|
834 | | - const data = json.data; |
835 | | - const links = json.data["@links"]; |
836 | | - |
837 | | - let prevPageURL, nextPageURL; |
838 | | - |
839 | | - if (links.prev && links.prev.length > 0) { |
840 | | - prevPageURL = links.prev[0].uri; |
841 | | - } |
842 | | - if (links.next && links.next.length > 0) { |
843 | | - nextPageURL = links.next[0].uri; |
| 849 | + if (props.formProperty) { |
| 850 | + // Find preselected values |
| 851 | + const input = document.getElementsByName(props.formProperty).item(0); |
| 852 | + if (input?.value) { |
| 853 | + preSelectedValues = input.value.split(','); |
| 854 | + } |
844 | 855 | } |
845 | 856 |
|
846 | | - const popupDocument = this.popupRef.document; |
847 | | - const popupBody = popupDocument.body; |
848 | | - const popupHead = popupDocument.head; |
| 857 | + const popupFeatures = CLASSHELPER_POPUP_FEATURES(props.width, props.height); |
| 858 | + this.popupRef = window.open(CLASSHELPER_POPUP_URL, CLASSHELPER_POPUP_TARGET, popupFeatures); |
849 | 859 |
|
850 | | - // Add external classhelper css to head |
851 | | - const css = popupDocument.createElement("link"); |
852 | | - css.rel = "stylesheet"; |
853 | | - css.type = "text/css"; |
854 | | - css.href = this.trackerBaseURL + '/' + CSS_FILE_NAME; |
855 | | - popupHead.appendChild(css); |
| 860 | + this.popupRef.addEventListener("load", (event) => { |
| 861 | + const doc = event.target; |
| 862 | + const body = doc.body; |
856 | 863 |
|
857 | | - popupBody.classList.add("flex-container"); |
| 864 | + // Add external classhelper stylesheet to head |
| 865 | + const styleSheet = doc.createElement("link"); |
| 866 | + styleSheet.rel = "stylesheet"; |
| 867 | + styleSheet.type = "text/css"; |
| 868 | + styleSheet.href = this.trackerBaseURL + '/' + CSS_STYLESHEET_FILE_NAME; |
| 869 | + doc.head.appendChild(styleSheet); |
858 | 870 |
|
859 | | - if (this.dataset.searchWith) { |
860 | | - const searchFrag = this.getSearchFragment(formData); |
861 | | - popupBody.appendChild(searchFrag); |
862 | | - } |
| 871 | + body.classList.add("flex-container"); |
863 | 872 |
|
864 | | - const paginationFrag = this.getPaginationFragment(prevPageURL, nextPageURL, props.pageIndex, props.pageSize, data.collection.length); |
865 | | - popupBody.appendChild(paginationFrag); |
| 873 | + if (this.dataset.searchWith) { |
| 874 | + const searchFrag = this.getSearchFragment(null); |
| 875 | + body.appendChild(searchFrag); |
| 876 | + } |
866 | 877 |
|
867 | | - const tableFrag = this.getTableFragment(props.fields, data.collection, preSelectedValues); |
868 | | - popupBody.appendChild(tableFrag); |
| 878 | + const paginationFrag = this.getPaginationFragment(prevPageURL, nextPageURL, props.pageIndex, props.pageSize, collection.length); |
| 879 | + body.appendChild(paginationFrag); |
869 | 880 |
|
870 | | - const separator = popupDocument.createElement("div"); |
871 | | - separator.classList.add("separator"); |
872 | | - popupBody.appendChild(separator); |
| 881 | + const tableFrag = this.getTableFragment(props.fields, collection, preSelectedValues); |
| 882 | + body.appendChild(tableFrag); |
873 | 883 |
|
874 | | - const accumulatorFrag = this.getAccumulatorFragment(preSelectedValues); |
875 | | - popupBody.appendChild(accumulatorFrag); |
| 884 | + const separator = doc.createElement("div"); |
| 885 | + separator.classList.add("separator"); |
| 886 | + body.appendChild(separator); |
| 887 | + |
| 888 | + const accumulatorFrag = this.getAccumulatorFragment(preSelectedValues); |
| 889 | + body.appendChild(accumulatorFrag); |
| 890 | + }); |
876 | 891 |
|
877 | 892 | this.popupRef.document.addEventListener("keydown", (e) => { |
878 | 893 | if (e.target.tagName == "TR") { |
|
0 commit comments