PageSourceSearch

https://quorumapp.com/ts/CustomJSModal.js

js quorumapp.com collected 2026-09-26 04:39:50 UTC 24,201 bytes, 456 lines download raw bytes

1/// <reference path="references.d.ts" />
2/// <reference path="application.ts" />
3var __assign = (this && this.__assign) || function () {
4    __assign = Object.assign || function(t) {
5        for (var s, i = 1, n = arguments.length; i < n; i++) {
6            s = arguments[i];
7            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
8                t[p] = s[p];
9        }
10        return t;
11    };
12    return __assign.apply(this, arguments);
13};
14var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
15    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
16    return new (P || (P = Promise))(function (resolve, reject) {
17        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
18        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
19        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
20        step((generator = generator.apply(thisArg, _arguments || [])).next());
21    });
22};
23var __generator = (this && this.__generator) || function (thisArg, body) {
24    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
25    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
26    function verb(n) { return function (v) { return step([n, v]); }; }
27    function step(op) {
28        if (f) throw new TypeError("Generator is already executing.");
29        while (g && (g = 0, op[0] && (_ = 0)), _) try {
30            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
31            if (y = 0, t) op = [op[0] & 2, t.value];
32            switch (op[0]) {
33                case 0: case 1: t = op; break;
34                case 4: _.label++; return { value: op[1], done: false };
35                case 5: _.label++; y = op[1]; op = [0]; continue;
36                case 7: op = _.ops.pop(); _.trys.pop(); continue;
37                default:
38                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
39                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
40                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
41                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
42                    if (t[2]) _.ops.pop();
43                    _.trys.pop(); continue;
44            }
45            op = body.call(thisArg, _);
46        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
47        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
48    }
49};
50import { Distiller } from './application.js';
51var CustomJSModal = /** @class */ (function () {
52    function CustomJSModal(params) {
53        var _this = this;
54        var _a, _b, _c, _d, _e;
55        this.closeModal = function () {
56            if (Distiller.llmStatusText()) {
57                alert("Your Quorum assistant is still working on your request. Please wait for it to finish before leaving this page. If you want the assistant to stop working and abandon any changes it was going to make, click the stop button towards the bottom of your chat interface.");
58                return;
59            }
60            Distiller.modalInView(null);
61        };
62        this.processJSFile = function (fileId) {
63            var self = _this;
64            var input = document.createElement('input');
65            input.type = 'file';
66            input.setAttribute('accept', '.js,application/javascript');
67            input.onchange = function (e) {
68                var file = e.target.files[0];
69                if (!file) {
70                    console.error("No file selected.");
71                    return;
72                }
73                var reader = new FileReader();
74                reader.onload = function (readerEvent) { return __awaiter(_this, void 0, void 0, function () {
75                    var base64, err_1;
76                    return __generator(this, function (_a) {
77                        switch (_a.label) {
78                            case 0:
79                                if (!file) return [3 /*break*/, 5];
80                                base64 = null;
81                                _a.label = 1;
82                            case 1:
83                                _a.trys.push([1, 3, , 4]);
84                                return [4 /*yield*/, Distiller.convertFileToBase64(file)];
85                            case 2:
86                                base64 = _a.sent();
87                                return [3 /*break*/, 4];
88                            case 3:
89                                err_1 = _a.sent();
90                                console.log("error converting file to base64 " + err_1);
91                                alert("Oops! Something went wrong when we tried to upload your file. Please contact [email protected].");
92                                return [3 /*break*/, 4];
93                            case 4:
94                                self.uploadJSFile(fileId, { fileName: file.name, dataURL: base64 });
95                                _a.label = 5;
96                            case 5: return [2 /*return*/];
97                        }
98                    });
99                }); };
100                reader.readAsDataURL(file); // Use readAsDataURL for images
101            };
102            document.body.appendChild(input); // Ensure input is part of the DOM
103            input.style.display = 'none'; // Hide input from view
104            input.click();
105        };
106        this.switchView = function (view) {
107            if (Distiller.llmStatusText()) {
108                alert("Your Quorum assistant is still working on your request. Please wait for it to finish before leaving this page. If you want the assistant to stop working and abandon any changes it was going to make, click the stop button towards the bottom of your chat interface.");
109                return;
110            }
111            // if (window.location.hostname === "localhost") {
112            Distiller.customJSView(view);
113            /*  }
114              else {
115                  if (view === "vibe-code") {
116                      alert("This feature is coming soon! Contact [email protected] for more information.");
117                  }
118              } */
119        };
120        this.fileInView = ko.observable({
121            fileId: ko.observable(null),
122            fileName: ko.observable(null),
123            name: ko.observable(null),
124            description: ko.observable(null),
125            isAuthor: ko.observable(true),
126            status: ko.observable(null),
127            url: ko.observable(null),
128            version: ko.observable(1)
129        });
130        this.showingOptions = ko.observable(null);
131        this.customJSList = ko.observableArray([]);
132        this.filteredCustomJSList = ko.computed(function () {
133            if (Distiller.customJSFilter() === 'myFeatures') {
134                return _this.customJSList().filter(function (item) { return item.isAuthor && item.isAuthor(); });
135            }
136            return _this.customJSList();
137        });
138        this.getCustomJS = function () {
139            var self = _this;
140            var fileId = _this.customJSParam().fileId();
141            _this.loading(true);
142            Distiller.httpGetAsync(Distiller.apiEndpoint + "/api/getCustomJS/" + Distiller.currentUser().userId + "/" + Distiller.currentUser().communityId + "/" + Distiller.studyInView().communityId() + "/" + fileId, function (response) {
143                response = JSON.parse(response);
144                if (!response.err) {
145                    var list = [];
146                    for (var i = 0; i < response.data.length; i++) {
147                        list.push({
148                            fileId: ko.observable(response.data[i].ID),
149                            fileName: ko.observable(response.data[i].fileName),
150                            name: ko.observable(response.data[i].name),
151                            description: ko.observable(response.data[i].description),
152                            isAuthor: ko.observable(response.data[i].isAuthor),
153                            isNew: ko.observable(response.data[i].isNew),
154                            status: ko.observable(response.data[i].status),
155                            url: ko.observable(response.data[i].url),
156                            version: ko.observable(response.data[i].version)
157                        });
158                    }
159                    self.customJSList(list);
160                    if (self.customJSList().find(function (a) { return a.fileId() === self.customJSParam().fileId(); })) {
161                        self.fileInView(self.customJSList().find(function (a) { return a.fileId() === self.customJSParam().fileId(); }));
162                        self.getFileVersions(self.fileInView().fileId());
163                        self.subscribeToChanges();
164                    }
165                    else if (self.customJSList().find(function (a) { return a.isNew(); })) {
166                        self.fileInView(self.customJSList().find(function (a) { return a.isNew(); }));
167                        self.customJSParam().fileId(self.fileInView().fileId());
168                        self.subscribeToChanges();
169                    }
170                }
171                else {
172                    alert("Oops! Something went wrong when we tried to get your custom JS. Please report this issue to [email protected]");
173                }
174                self.loading(false);
175            });
176        };
177        this.showCustomJS = function (customJS) {
178            if (customJS) {
179                _this.fileInView(customJS);
180                _this.customJSParam().fileId(customJS.fileId());
181            }
182            else {
183                _this.fileInView({
184                    fileId: ko.observable(null),
185                    fileName: ko.observable(null),
186                    name: ko.observable(null),
187                    description: ko.observable(null),
188                    isNew: ko.observable(true),
189                    isAuthor: ko.observable(true),
190                    status: ko.observable(null),
191                    url: ko.observable(null),
192                    version: ko.observable(1)
193                });
194            }
195            _this.subscribeToChanges();
196            _this.getFileVersions(_this.fileInView().fileId());
197        };
198        this.showVersion = function (newVersion) {
199            var self = _this;
200            var fileId = _this.fileInView().fileId();
201            if (newVersion === _this.fileInView().version()) {
202                return;
203            }
204            Distiller.httpPostAsync(Distiller.apiEndpoint + "/api/setFileVersion/" + Distiller.currentUser().userId + "/" + Distiller.studyInView().communityId() + "/" + fileId + "/" + newVersion, function (response) {
205                response = JSON.parse(response);
206                if (!response.err) {
207                    self.fileInView().version(newVersion);
208                    self.fileInView().url(response.url);
209                    self.fileInView().description(response.description);
210                    self.showingOptions(null);
211                    Distiller.changingJSVersion(true);
212                }
213            });
214        };
215        this.getVersionString = function (version) {
216            // Convert version number to minor version label
217            // e.g., version 1 -> .01, version 10 -> .10, version 5 -> .05, version 35 -> .35
218            return 'v.' + version.toString().padStart(2, '0');
219        };
220        this.currentFileVersions = ko.observableArray([]);
221        this.getFileVersions = function (fileId) {
222            var self = _this;
223            Distiller.httpGetAsync(Distiller.apiEndpoint + "/api/getFileVersions/" + Distiller.currentUser().userId + "/" + Distiller.studyInView().communityId() + "/" + fileId, function (response) {
224                response = JSON.parse(response);
225                if (!response.err) {
226                    self.currentFileVersions(response.data);
227                }
228            });
229        };
230        this.subscriptions = ko.observableArray([]);
231        this.subscribeToChanges = function () {
232            var self = _this;
233            _this.subscriptions().forEach(function (element) {
234                element.dispose();
235            });
236            _this.subscriptions([]);
237            _this.subscriptions.push(_this.fileInView().name.subscribe(function (newVal) {
238                self.saveCustomJSAttributes();
239            }));
240            _this.subscriptions.push(_this.fileInView().description.subscribe(function (newVal) {
241                self.saveCustomJSAttributes();
242            }));
243            _this.subscriptions.push(_this.fileInView().fileId.subscribe(function (newVal) {
244                self.customJSParam().fileId(newVal);
245            }));
246        };
247        this.timeout = null;
248        this.saveCustomJSAttributes = function () {
249            var self = _this;
250            if (_this.timeout) {
251                clearTimeout(_this.timeout);
252            }
253            _this.timeout = setTimeout(function () {
254                Distiller.httpSendAsync(Distiller.apiEndpoint + "/api/saveCustomJSAttributes/" + Distiller.currentUser().userId + "/" + Distiller.studyInView().communityId() + "/" + _this.fileInView().fileId(), JSON.stringify(ko.toJS(_this.fileInView())), function (response) {
255                    response = JSON.parse(response);
256                    self.fileInView().fileId(response.fileId);
257                });
258            }, 500);
259        };
260        this.uploadJSFile = function (fileId, payload) {
261            _this.fileInView().fileName('Uploading...');
262            var self = _this;
263            Distiller.httpSendAsync(Distiller.apiEndpoint + "/api/uploadCustomJS/" + Distiller.currentUser().userId + "/" + Distiller.studyInView().communityId() + "/" + fileId, JSON.stringify(payload), function (response) {
264                response = JSON.parse(response);
265                if (!response.err) {
266                    self.fileInView().fileName(payload.fileName);
267                    self.fileInView().fileId(response.fileId);
268                    self.customJSParam().fileId(response.fileId);
269                    self.fileInView().version(response.version);
270                }
271                else {
272                    alert("Oops! Something went wrong when we tried to upload your image. Please report this issue to [email protected]");
273                }
274            });
275        };
276        this.deleteFeature = function () {
277            var confirm = window.confirm("Are you sure you want to delete this feature? This action cannot be easily undone.");
278            if (!confirm) {
279                return;
280            }
281            var self = _this;
282            Distiller.httpPostAsync(Distiller.apiEndpoint + "/api/deleteCustomJS/" + Distiller.currentUser().userId + "/" + Distiller.studyInView().communityId() + "/" + _this.fileInView().fileId(), function (response) {
283                response = JSON.parse(response);
284                if (!response.err) {
285                    self.fileInView().status("deleted");
286                    self.showCustomJS(self.customJSList().find(function (a) { return a.isNew(); }));
287                }
288                else {
289                    alert("Oops! Something went wrong when we tried to delete your feature. Please report this issue to [email protected]: " + response.err);
290                }
291            });
292        };
293        this.customJSParam = ko.observable(null);
294        this.questionsCode = ko.observable(null);
295        // Example usage:
296        this.generateQuestionsCode = function (questions) {
297            var cleanedQuestions = questions.map(function (question) {
298                var copy = __assign({}, question);
299                delete copy.teammateComments;
300                delete copy.currentUserRationales;
301                delete copy.arrayOfUserForecasts;
302                delete copy.arrayOfHistoricalForecasts;
303                delete copy.pendingRationaleText;
304                return copy;
305            });
306            var formattedJSON = JSON.stringify(ko.toJS(cleanedQuestions), null, 2);
307            _this.questionsCode(formattedJSON);
308        };
309        this.getParamsForVibeCode = function () {
310            var urlParams = new URLSearchParams(window.location.search);
311            var setId = urlParams.get('page');
312            if (setId) {
313                setId = parseInt(setId);
314            }
315            var params = {
316                setId: setId,
317                element: _this.element,
318                //  questions: questions,
319                featurePreviewURL: _this.featurePreviewURL,
320                studyPreviewURL: _this.studyPreviewURL,
321                fileInView: _this.fileInView,
322                startFreshFile: _this.customJSList().find(function (a) { return a.isNew(); }),
323                customJSParam: _this.customJSParam,
324                showCustomJS: _this.showCustomJS,
325                currentFileVersions: _this.currentFileVersions,
326                workflowIndex: _this.indexInFocus(),
327                pageVersionIndex: _this.pageVersionIndex(),
328                stageIndex: _this.stageIndex(),
329            };
330            return params;
331        };
332        this.openPreviewLink = function () {
333            var urlParams = new URLSearchParams(window.location.search);
334            var setId = urlParams.get('page');
335            if (setId) {
336                setId = parseInt(setId);
337            }
338            var previewURL = window.location.origin + "/?sid=".concat(Distiller.studyInView().communityId(), "&set=").concat(setId, "&devIndices=[").concat(_this.indexInFocus(), "]");
339            if (Distiller.llmPreviewType() === 'full-study') {
340                previewURL = window.location.origin + "/?sid=".concat(Distiller.studyInView().communityId(), "&set=").concat(setId);
341            }
342            window.open(previewURL, '_blank');
343        };
344        this.element = ko.observable(null);
345        this.indexInFocus = ko.observable(null);
346        this.setId = ko.observable(null);
347        this.pageVersionIndex = ko.observable(null);
348        this.stageIndex = ko.observable(null);
349        this.workflowIndex = ko.observable(null);
350        this.loading = ko.observable(false);
351        this.questions = ko.observableArray([]);
352        this.deleting = ko.observable(null);
353        this.downloadJavaScript = function () {
354            var url = _this.fileInView().url();
355            if (!url) {
356                alert("No JavaScript file URL available for download.");
357                return;
358            }
359            // Try to fetch the file and force download
360            fetch(url)
361                .then(function (response) {
362                if (!response.ok) {
363                    throw new Error('Network response was not ok');
364                }
365                return response.blob();
366            })
367                .then(function (blob) {
368                // Create a blob URL and force download
369                var blobUrl = window.URL.createObjectURL(blob);
370                var link = document.createElement('a');
371                link.href = blobUrl;
372                link.download = _this.fileInView().fileName() || 'custom-javascript.js';
373                document.body.appendChild(link);
374                link.click();
375                document.body.removeChild(link);
376                // Clean up the blob URL
377                window.URL.revokeObjectURL(blobUrl);
378            })
379                .catch(function (error) {
380                console.log('Failed to download file, opening in new tab instead:', error);
381                // Fallback: open in new tab if download fails
382                window.open(url, '_blank');
383            });
384            _this.showingOptions(null);
385        };
386        this.deleteMySubmissions = function (forFeature) { return __awaiter(_this, void 0, void 0, function () {
387            var questionIds, featurePreviewURL, studyPreviewURL;
388            return __generator(this, function (_a) {
389                switch (_a.label) {
390                    case 0:
391                        if (!this.deleteMySubmissionsFunction) {
392                            return [2 /*return*/];
393                        }
394                        if (!forFeature) return [3 /*break*/, 2];
395                        this.deleting("submissionsForFeature");
396                        questionIds = this.questions().map(function (a) { return a.questionId(); });
397                        return [4 /*yield*/, this.deleteMySubmissionsFunction(questionIds)];
398                    case 1:
399                        _a.sent();
400                        return [3 /*break*/, 4];
401                    case 2:
402                        this.deleting("submissionsForStudy");
403                        return [4 /*yield*/, this.deleteMySubmissionsFunction()];
404                    case 3:
405                        _a.sent();
406                        _a.label = 4;
407                    case 4:
408                        featurePreviewURL = this.featurePreviewURL();
409                        studyPreviewURL = this.studyPreviewURL();
410                        this.featurePreviewURL(null);
411                        this.studyPreviewURL(null);
412                        this.featurePreviewURL(featurePreviewURL);
413                        this.studyPreviewURL(studyPreviewURL);
414                        this.showingOptions(null);
415                        this.deleting(null);
416                        return [2 /*return*/];
417                }
418            });
419        }); };
420        this.featurePreviewURL = ko.observable(null);
421        this.studyPreviewURL = ko.observable(null);
422        this.customJSParam(params.customJSParam);
423        this.getCustomJS();
424        this.subscribeToChanges();
425        this.element(params.element);
426        this.indexInFocus(params.indexInFocus);
427        this.setId(params.setId);
428        this.pageVersionIndex(params.pageVersionIndex);
429        this.stageIndex(params.stageIndex);
430        var urlParams = new URLSearchParams(window.location.search);
431        var setId = urlParams.get('page');
432        if (setId) {
433            setId = parseInt(setId);
434        }
435        var featurePreviewURL = window.location.origin + "/?sid=".concat(Distiller.studyInView().communityId(), "&set=").concat(setId, "&devIndices=[").concat(this.indexInFocus(), "]");
436        var studyPreviewURL = window.location.origin + "/?sid=".concat(Distiller.studyInView().communityId(), "&set=").concat(setId);
437        this.featurePreviewURL(featurePreviewURL);
438        this.studyPreviewURL(studyPreviewURL);
439        this.deleteMySubmissionsFunction = params.deleteMySubmissionsFunction;
440        //temp 
441        if (params.element.question && params.element.question()) {
442            this.questions.push(params.element.question());
443            var primaryQuestion = Distiller.simplifyObject(params.element.question(), Distiller.simpleQuestionKeys); //JSON.parse(JSON.stringify(ko.toJS(params.element.question())));
444            var questions = [primaryQuestion];
445            if (((_a = params.element.question()) === null || _a === void 0 ? void 0 : _a.timepointQuestions()) && ((_b = params.element.question()) === null || _b === void 0 ? void 0 : _b.timepointQuestions().length) > 0) {
446                for (var i = 0; i < ((_c = params.element.question()) === null || _c === void 0 ? void 0 : _c.timepointQuestions().length); i++) {
447                    this.questions.push((_d = params.element.question()) === null || _d === void 0 ? void 0 : _d.timepointQuestions()[i]);
448                    questions.push(Distiller.simplifyObject((_e = params.element.question()) === null || _e === void 0 ? void 0 : _e.timepointQuestions()[i], Distiller.simpleQuestionKeys));
449                }
450            }
451            this.generateQuestionsCode(questions);
452        }
453    }
454    return CustomJSModal;
455}());
456export default CustomJSModal;

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.