diff --git a/collects/drracket/private/frame.rkt b/collects/drracket/private/frame.rkt
index a4e991a418..4ea4a4b1b5 100644
--- a/collects/drracket/private/frame.rkt
+++ b/collects/drracket/private/frame.rkt
@@ -153,12 +153,74 @@
menu
(get-additional-important-urls))
(new menu-item%
- (label (string-constant bug-report-submit-menu-item))
- (parent menu)
- (callback
+ [label (string-constant bug-report-submit-menu-item)]
+ [parent menu]
+ [callback
(λ (x y)
- (help-desk:report-bug))))
-
+ (define saved (saved-bug-report-titles/ids))
+ (cond
+ [(null? saved)
+ (help-desk:report-bug #f #:frame-mixin basics-mixin)]
+ [else
+ (define which #f)
+ (define (done the-one)
+ (set! which the-one)
+ (send dlg show #f))
+ (define dlg (new dialog%
+ [label (string-constant drscheme)]
+ [parent this]))
+ (define btn1 (new button%
+ [parent dlg]
+ [label (string-constant new-bug-report)]
+ [callback (λ (x y) (done #f))]))
+ (new message% [parent dlg] [label (string-constant saved-unsubmitted-bug-reports)])
+ (define btns
+ (cons btn1
+ (for/list ([a-brinfo (in-list saved)])
+ (new button%
+ [parent dlg]
+ [label (brinfo-title a-brinfo)]
+ [callback
+ (λ (x y) (done (brinfo-id a-brinfo)))]))))
+ (define width (apply max (map (λ (x) (let-values ([(w h) (send x get-client-size)]) w))
+ btns)))
+ (for ([x (in-list btns)])
+ (send x min-width width))
+ (send btn1 focus)
+ (send dlg show #t)
+ (help-desk:report-bug which #:frame-mixin basics-mixin)]))])
+ (new menu%
+ [label (string-constant saved-bug-reports-menu-item)]
+ [parent menu]
+ [demand-callback
+ (let ([last-time (gensym)]) ;; a unique thing to guarantee the menu is built the first time
+ (λ (saved-bug-reports-menu)
+ (define this-time (saved-bug-report-titles/ids))
+ (unless (equal? last-time this-time)
+ (set! last-time this-time)
+ (for ([x (in-list (send saved-bug-reports-menu get-items))])
+ (send x delete))
+ (cond
+ [(null? this-time)
+ (send (new menu-item%
+ [parent saved-bug-reports-menu]
+ [label (string-constant no-saved-bug-reports)]
+ [callback void])
+ enable #f)]
+ [else
+ (unless (null? (cdr this-time))
+ (new menu-item%
+ [parent saved-bug-reports-menu]
+ [label (string-constant disacard-all-saved-bug-reports)]
+ [callback (λ (x y) (discard-all-saved-bug-reports))])
+ (new separator-menu-item% [parent saved-bug-reports-menu]))
+ (for ([a-brinfo (in-list this-time)])
+ (new menu-item%
+ [parent saved-bug-reports-menu]
+ [label (brinfo-title a-brinfo)]
+ [callback
+ (λ (x y)
+ (help-desk:report-bug (brinfo-id a-brinfo) #:frame-mixin basics-mixin))]))]))))])
(drracket:app:add-language-items-to-help-menu menu))
(define/override (file-menu:new-string) (string-constant new-menu-item))
diff --git a/collects/drracket/private/main.rkt b/collects/drracket/private/main.rkt
index 4f3bbca282..3e3f659d4e 100644
--- a/collects/drracket/private/main.rkt
+++ b/collects/drracket/private/main.rkt
@@ -89,8 +89,6 @@
(drracket:modes:add-initial-modes)
-(namespace-set-variable-value! 'help-desk:frame-mixin drracket:frame:basics-mixin)
-
(finder:default-filters (list* '("Racket (.rkt)" "*.rkt")
'("Racket (.ss)" "*.ss")
'("Racket (.scm)" "*.scm")
diff --git a/collects/help/bug-report.rkt b/collects/help/bug-report.rkt
index 7eada5e9f1..b60cfa1b31 100644
--- a/collects/help/bug-report.rkt
+++ b/collects/help/bug-report.rkt
@@ -7,517 +7,248 @@
net/url
net/uri-codec
browser/htmltext
- setup/dirs
- "private/buginfo.ss")
+ "private/bug-report-controls.rkt"
+ "private/buginfo.ss"
+ "private/save-bug-report.rkt")
-(provide help-desk:report-bug)
+(provide help-desk:report-bug
+ (struct-out brinfo)
+ saved-bug-report-titles/ids
+ discard-all-saved-bug-reports)
(define bug-www-server "bugs.racket-lang.org")
(define bug-www-server-port 80)
-;; this one should be defined by help desk.
-(define frame-mixin
- (namespace-variable-value 'help-desk:frame-mixin #f (lambda () (lambda (x) x))))
-
(preferences:set-default 'drracket:email "" string? #:aliases '(drscheme:email))
(preferences:set-default 'drracket:full-name "" string? #:aliases '(drscheme:full-name))
-(define bug-frame%
- (class (frame-mixin (frame:standard-menus-mixin frame:basic%))
- (init title)
-
- ;; a bunch of stuff we don't want
- (define/override (file-menu:between-print-and-close menu) (void))
- (define/override (edit-menu:between-find-and-preferences menu) (void))
- (define/override (file-menu:create-open?) #f)
- (define/override (file-menu:create-open-recent?) #f)
- (define/override (file-menu:create-new?) #f)
- (define/override (file-menu:create-save?) #f)
- (define/override (file-menu:create-revert?) #f)
-
- (field (ok-to-close? #f))
- (public set-ok-to-close)
- (define (set-ok-to-close ok?) (set! ok-to-close? #t))
- (define/augment (can-close?)
- (or ok-to-close?
- (ask-yes-or-no (string-constant cancel-bug-report?)
- (string-constant are-you-sure-cancel-bug-report?)
- this)))
-
- (super-make-object title)))
+(define open-frames '())
+(define (discard-all-saved-bug-reports)
+ (discard-all-except
+ (λ (id) (ormap (λ (frame) (equal? (send frame get-bug-id) id))
+ open-frames))))
-(define (help-desk:report-bug)
- (define bug-frame (instantiate bug-frame% () (title (string-constant bug-report-form))))
+(define (help-desk:report-bug [this-bug-id #f] #:frame-mixin [frame-mixin values])
+ (cond
+ [this-bug-id
+ (let loop ([open-frames open-frames])
+ (cond
+ [(null? open-frames)
+ (report-bug/new-frame this-bug-id frame-mixin)]
+ [else
+ (let ([open-frame (car open-frames)])
+ (if (= (send open-frame get-bug-id) this-bug-id)
+ (send open-frame show #t)
+ (loop (cdr open-frames))))]))]
+ [else
+ (report-bug/new-frame this-bug-id frame-mixin)]))
+
+(define (report-bug/new-frame this-bug-id frame-mixin)
+ (define bug-frame%
+ (class (frame-mixin (frame:standard-menus-mixin frame:basic%))
+ (init title)
+ (init-field bug-id)
+ (define/public (get-bug-id) (and editing? bug-id))
+
+ (define editing? #t)
+ (define/public (no-longer-editing) (set! editing? #f))
+ (define/augment (on-close)
+ (inner (void) on-close)
+ (set! open-frames (remq this open-frames)))
+ (super-make-object title)
+ (set! open-frames (cons this open-frames))
+
+ ;; a bunch of stuff we don't want
+ (define/override (file-menu:between-print-and-close menu) (void))
+ (define/override (edit-menu:between-find-and-preferences menu) (void))
+ (define/override (file-menu:create-open?) #f)
+ (define/override (file-menu:create-open-recent?) #f)
+ (define/override (file-menu:create-new?) #f)
+ (define/override (file-menu:create-save?) #f)
+ (define/override (file-menu:create-revert?) #f)))
+
+ (define init-bug-report (if this-bug-id
+ (lookup-bug-report this-bug-id)
+ (register-new-bug-id)))
+ (define bug-frame (new bug-frame%
+ [bug-id (saved-report-id init-bug-report)]
+ [title (string-constant bug-report-form)]))
(define single (new panel:single% (parent (send bug-frame get-area-container))))
- (define outermost-panel (make-object vertical-panel% single))
+ (define compose-panel (make-object vertical-panel% single))
- (define response-panel (new vertical-panel% (parent single)))
- (define response-text (new (html-text-mixin text%) (auto-wrap #t)))
- (define response-ec (new editor-canvas% (parent response-panel) (editor response-text)))
- (define response-button-panel (new horizontal-panel%
- (stretchable-height #f)
- (parent response-panel)
- (alignment '(right center))))
- (define cancel-kill-thread #f)
- (define response-reset (new button%
- (parent response-button-panel)
- (enabled #f)
- (label (string-constant dialog-back))
- (callback
- (lambda (x y)
- (switch-to-compose-view)))))
- (define response-abort (new button%
- (parent response-button-panel)
- (enabled #f)
- (callback
- (lambda (x y)
- (kill-thread cancel-kill-thread)
- (switch-to-compose-view)))
- (label (string-constant abort))))
- (define response-close (new button%
- (parent response-button-panel)
- (enabled #f)
- (callback (lambda (x y) (cleanup-frame)))
- (label (string-constant close))))
- (new grow-box-spacer-pane% (parent response-button-panel))
+ (define cancel-kill-cust #f)
- (define top-panel (make-object vertical-panel% outermost-panel))
+ (define-values (compose-view-focus get-query sanity-checking)
+ (add-bug-report-controls compose-panel
+ init-bug-report
+ (λ () (ok))
+ (λ () (cancel))
+ (λ () (close-and-save))))
- (define (switch-to-response-view)
- (send response-text lock #f)
- (send response-text erase)
- (render-html-to-text ; hack to get nice text in
- (open-input-string
- "
\n") + (display (exn-message exn) out) + (fprintf out "\n\n") + (close-output-port out))) + (with-pending-text + (λ () (render-html-to-text in pending-text #t #f))) + (send pending-back enable #t) + (send pending-abort enable #f))))) + (handle-evt + (thread-dead-evt worker-thread) + (λ (_) + (queue-callback + (λ () + (with-pending-text + (λ () + (define p (send pending-text last-position)) + (send pending-text insert "Killed." p p))) + (send pending-back enable #t) + (send pending-abort enable #f))))) + (handle-evt + response-chan + (λ (finished-text) + (queue-callback + (lambda () + (switch-to-finished-view finished-text)))))))) + + (init-pending-view)) + (define (ok) (when (sanity-checking) (send-bug-report))) (define (cancel) - (cleanup-frame)) + (when (ask-yes-or-no (string-constant cancel-bug-report?) + (string-constant are-you-sure-cancel-bug-report?) + bug-frame) + (unsave-bug-report (saved-report-id init-bug-report)) + (send bug-frame close))) - (define (cleanup-frame) + (define (close-and-save) (send bug-frame close)) - (define (directories-contents dirs) - (map (lambda (d) - (cons (path->string d) - (if (directory-exists? d) - (map path->string (directory-list d)) - '(non-existent-path)))) - dirs)) - - (define (split-by-directories dirs split-by) - (let ([res (append (map list (map path->string split-by)) '((*)))] - [dirs (map path->string dirs)]) - (for-each - (lambda (d) - (let* ([l (string-length d)] - [x (assf - (lambda (d2) - (or (eq? d2 '*) - (let ([l2 (string-length d2)]) - (and (< l2 l) (equal? d2 (substring d 0 l2)) - (member (string-ref d l2) '(#\/ #\\)))))) - res)]) - (append x (list (if (string? (car x)) - (substring d (add1 (string-length (car x)))) - d))))) - dirs) - (filter (lambda (x) (pair? (cdr x))) res))) - - (send response-ec allow-tab-exit #t) - - (send severity set-selection 1) - (send version set-value (format "~a" (version:version))) - - (send environment set-value - (format "~a ~s (~a) (get-display-depth) = ~a" - (system-type) - (system-type 'machine) - (system-library-subpath) - (get-display-depth))) - - (send (send collections get-editor) - insert - (format "~s" (directories-contents (get-collects-search-dirs)))) - - (send human-language set-value (format "~a" (this-language))) - (send memory-use set-value (format "~a" (current-memory-use))) - - (send (send collections get-editor) auto-wrap #t) - ;; Currently, the help-menu is left empty (frame:remove-empty-menus bug-frame) - (align-labels) (switch-to-compose-view) (send bug-frame show #t)) +(define html-text% (text:hide-caret/selection-mixin (html-text-mixin text:basic%))) + (define (ask-yes-or-no title msg parent) (gui-utils:get-choice msg (string-constant yes) diff --git a/collects/help/private/bug-report-controls.rkt b/collects/help/private/bug-report-controls.rkt new file mode 100644 index 0000000000..12ed27f720 --- /dev/null +++ b/collects/help/private/bug-report-controls.rkt @@ -0,0 +1,405 @@ +#lang racket/base +(require racket/gui/base + racket/class + racket/contract + racket/pretty + string-constants/string-constant + setup/dirs + framework + "buginfo.ss" + "save-bug-report.rkt") + +(provide/contract + [add-bug-report-controls + (-> (is-a?/c area-container<%>) + saved-report? + (-> any) + (-> any) + (-> any) + any)]) + +(define (add-bug-report-controls compose-panel init-bug-report ok cancel close-and-save) + (define top-panel (make-object vertical-panel% compose-panel)) + + (define lps null) + + ; build/label : ((union string (list-of string)) + ; (area-container<%> -> item<%>) + ; boolean + ; area-container<%> + ; -> item<%>) + ; constructs and arranges the gui objects for the bug report form + ; effect: updates lps with the new label panel, for future alignment + (define (build/label text make-item top? #:stretch? [stretch? #f] #:top-panel [top-panel top-panel] #:vertical? [vertical? #f]) + (define hp (make-object (if vertical? + vertical-panel% + horizontal-panel%) + top-panel)) + (define lp (make-object vertical-panel% hp)) + (define ip (make-object vertical-panel% hp)) + (if (string? text) + (make-object message% text lp) + (map (lambda (s) + (make-object message% s lp)) + text)) + (define item (make-item ip)) + (set! lps (cons lp lps)) + (unless stretch? + (send hp stretchable-height #f) + (send lp stretchable-height #f) + (send ip stretchable-height #f)) + (send lp stretchable-width #f) + (send lp stretchable-height #f) + (send lp set-alignment (if vertical? 'left 'right) (if top? 'top 'center)) + (send ip set-alignment 'left 'top) + item) + + (define (align-labels) + (send synthesized-dialog reflow-container) + (send compose-panel reflow-container) + (let ([width (apply max (map (lambda (x) (send (car (send x get-children)) get-width)) + lps))]) + (for ([x (in-list lps)]) + (send x min-width width)))) + + (define name + (build/label + (string-constant bug-report-field-name) + (lambda (panel) + (keymap:call/text-keymap-initializer + (lambda () + (make-object text-field% #f panel + (lambda (text event) + (preferences:set 'drracket:full-name (send text get-value))) + (preferences:get 'drracket:full-name))))) + #f)) + + (define email + (build/label + (string-constant bug-report-field-email) + (lambda (panel) + (keymap:call/text-keymap-initializer + (lambda () + (make-object text-field% #f panel + (lambda (text event) + (preferences:set 'drracket:email (send text get-value))) + (preferences:get 'drracket:email))))) + #f)) + + (define summary + (build/label + (string-constant bug-report-field-summary) + (lambda (panel) + (keymap:call/text-keymap-initializer + (lambda () + (define tf (new text-field% + [label #f] + [parent panel] + [callback (λ (a b) (bug-report-out-of-date))])) + (send tf set-value (saved-report-lookup init-bug-report 'subject)) + tf))) + #f)) + + (define severity + (build/label + (string-constant bug-report-field-severity) + (lambda (panel) + (define choice + (make-object choice% + #f + bug-severities + panel + (λ (a b) (bug-report-out-of-date)))) + (send choice set-string-selection (saved-report-lookup init-bug-report 'severity)) + choice) + #f)) + + (define bug-class + (build/label + (string-constant bug-report-field-class) + (lambda (panel) + (define choice (make-object choice% + #f + (map car bug-classes) + panel + (λ (a b) (bug-report-out-of-date)))) + (send choice set-string-selection + (saved-report-lookup init-bug-report 'class)) + choice) + #f)) + + (define save-text% + (class text:basic% + (define initialized? #f) + (define/public (initialized) (set! initialized? #t)) + (define/augment (after-insert a b) + (when initialized? + (bug-report-out-of-date)) + (inner (void) after-insert a b)) + (define/augment (after-delete a b) + (when initialized? + (bug-report-out-of-date)) + (inner (void) after-delete a b)) + (super-new))) + + (define (make-big-text label #:key [key #f] #:stretch? [stretch? #f] #:top-panel [top-panel top-panel] #:vertical? [vertical? #f]) + (let ([canvas + (build/label + label + (lambda (panel) + (let* ([text (new (editor:standard-style-list-mixin + (editor:keymap-mixin + (if key + save-text% + text:basic%))))] + [canvas (new canvas:basic% + (style '(hide-hscroll)) + (parent panel) + (editor text))]) + (send text set-paste-text-only #t) + (send text auto-wrap #t) + (send text set-max-undo-history 'forever) + (send text set-styles-fixed #t) + (when key + (send text insert (saved-report-lookup init-bug-report key)) + (send text set-position 0 0) + (send text initialized)) + canvas)) + #t + #:stretch? stretch? + #:top-panel top-panel + #:vertical? vertical?)]) + (send canvas min-width 500) + (send canvas min-height 130) + (send canvas get-editor) + (send canvas allow-tab-exit #t) + canvas)) + + (define description (make-big-text (string-constant bug-report-field-description) + #:key 'description + #:stretch? #t)) + (define reproduce (make-big-text (list (string-constant bug-report-field-reproduce1) + (string-constant bug-report-field-reproduce2)) + #:key 'how-to-repeat + #:stretch? #t)) + + (define synthesized-dialog (make-object dialog% (string-constant bug-report-synthesized-information))) + (define synthesized-panel (make-object vertical-panel% synthesized-dialog)) + (define synthesized-button-panel + (new horizontal-panel% [parent synthesized-dialog] + [alignment '(right center)] [stretchable-height #f])) + (define synthesized-ok-button (make-object button% (string-constant ok) synthesized-button-panel + (lambda (x y) + (send synthesized-dialog show #f)))) + (define synthesized-info-shown? #t) + (define (show-synthesized-info) + (send synthesized-dialog show #t)) + + (define version-tf + (build/label + (string-constant bug-report-field-version) + (lambda (panel) + (keymap:call/text-keymap-initializer + (lambda () + (make-object text-field% #f panel void "")))) + #f + #:top-panel synthesized-panel)) + (define environment + (build/label + (string-constant bug-report-field-environment) + (lambda (panel) + (keymap:call/text-keymap-initializer + (lambda () + (make-object text-field% #f panel void "")))) + #f + #:top-panel synthesized-panel)) + + (define human-language + (build/label + (string-constant bug-report-field-human-language) + (lambda (panel) + (keymap:call/text-keymap-initializer + (lambda () + (make-object text-field% #f panel void "")))) + #f + #:top-panel synthesized-panel)) + + (define memory-use + (build/label + (string-constant bug-report-field-memory-use) + (lambda (panel) + (keymap:call/text-keymap-initializer + (lambda () + (make-object text-field% #f panel void "")))) + #f + #:top-panel synthesized-panel)) + + (define collections + (make-big-text + (string-constant bug-report-field-collections) + #:stretch? #t + #:top-panel synthesized-panel)) + + (send synthesized-dialog reflow-container) ;; help out the editor by resizing the container to a reasonable width (and thus make word-wrapping easier) + + (define extras + (map (lambda (bri) + (let ([label (bri-label bri)]) + (cons + label + (build/label + label + (lambda (panel) + (let ([field + (keymap:call/text-keymap-initializer + (lambda () + (make-object text-field% #f panel void "")))]) + (send field set-value (bri-value bri)) + field)) + #f + #:top-panel synthesized-panel)))) + (get-bug-report-infos))) + + (define (save-this-bug-report) + (save-bug-report + (saved-report-id init-bug-report) + #:severity (send severity get-string-selection) + #:class (send bug-class get-string-selection) + #:subject (send summary get-value) + #:description (get-content description) + #:how-to-repeat (get-content reproduce))) + + (define timer + (new timer% + [notify-callback save-this-bug-report] + [just-once? #t])) + (define (bug-report-out-of-date) + (send timer stop) + (send timer start 200 #t)) + + (define (get-query) + (append (list (cons 'help-desk "true") + (cons 'replyto (preferences:get 'drracket:email)) + (cons 'originator (preferences:get 'drracket:full-name)) + (cons 'subject (send summary get-value)) + (cons 'severity (send severity get-string-selection)) + (cons 'class (translate-class (send bug-class get-string-selection))) + (cons 'release (send version-tf get-value)) + (cons 'description (get-content description)) + (cons 'how-to-repeat (get-content reproduce)) + (cons 'platform (get-environment))) + (map (λ (bri) (cons (string->symbol (format "~a" (bri-label bri))) + (bri-value bri))) + (get-bug-report-infos)))) + + (define (get-environment) + (string-append (send environment get-value) + "\n" + (format "Human Language: ~a\n" (send human-language get-value)) + (format "(current-memory-use) ~a\n" (send memory-use get-value)) + "\nCollections:\n" + (format "~a" (send (send collections get-editor) get-text)) + "\n" + (apply + string-append + (map (lambda (extra) + (format "~a: ~a\n" + (car extra) + (send (cdr extra) get-value))) + extras)))) + + (define (get-content canvas) + (define t (send canvas get-editor)) + (send t get-text 0 (send t last-position))) + + (define (set-content canvas str) + (define t (send canvas get-editor)) + (send t begin-edit-sequence) + (send t erase) + (send t insert str) + (send t end-edit-sequence)) + + (define (compose-view-focus) + (send (if (string=? "" (preferences:get 'drracket:full-name)) + name + summary) + focus)) + + (define button-panel + (new horizontal-panel% [parent compose-panel] + [alignment '(right center)] [stretchable-height #f])) + (define synthesized-button + (make-object button% + (string-constant bug-report-show-synthesized-info) + button-panel (lambda x (show-synthesized-info)))) + (new horizontal-pane% (parent button-panel)) + (new button% + [parent button-panel] + [label (string-constant close-and-save)] + [callback (λ (a b) (close-and-save))]) + (gui-utils:ok/cancel-buttons button-panel + (λ (a b) (ok)) + (λ (a b) (cancel)) + (string-constant bug-report-submit)) + (new grow-box-spacer-pane% [parent button-panel]) + + + (define (sanity-checking) + (let ([no-value? + (lambda (f) + (cond + [(is-a? f editor-canvas%) + (= 0 (send (send f get-editor) last-position))] + [else (string=? "" (send f get-value))]))]) + (let/ec done-checking + (for-each + (lambda (field field-name) + (when (no-value? field) + (message-box (string-constant illegal-bug-report) + (format (string-constant pls-fill-in-field) field-name)) + (done-checking #f))) + (list name summary) + (list (string-constant bug-report-field-name) + (string-constant bug-report-field-summary))) + + (when (and (no-value? description) + (no-value? reproduce)) + (message-box (string-constant illegal-bug-report) + (string-constant pls-fill-in-either-description-or-reproduce)) + (done-checking #f)) + + (unless (regexp-match #rx"@" (or (preferences:get 'drracket:email) "")) + (message-box (string-constant illegal-bug-report) + (string-constant malformed-email-address)) + (done-checking #f)) + (done-checking #t)))) + + (send version-tf set-value (format "~a" (version:version))) + + (send environment set-value + (format "~a ~s (~a) (get-display-depth) = ~a" + (system-type) + (system-type 'machine) + (system-library-subpath) + (get-display-depth))) + + (send (send collections get-editor) + insert + (apply + string-append + (for/list ([d (get-collects-search-dirs)]) + (format "(~s\n ~s)\n" + (path->string d) + (if (directory-exists? d) + (map path->string (directory-list d)) + '(non-existent-path)))))) + + (send human-language set-value (format "~a" (this-language))) + (send memory-use set-value (format "~a" (current-memory-use))) + + (send (send collections get-editor) auto-wrap #t) + (align-labels) + + (values compose-view-focus + get-query + sanity-checking)) diff --git a/collects/help/private/buginfo.rkt b/collects/help/private/buginfo.rkt index 5dd1ccf0f4..fc3c859493 100644 --- a/collects/help/private/buginfo.rkt +++ b/collects/help/private/buginfo.rkt @@ -1,17 +1,17 @@ -#lang mzscheme +#lang racket/base (provide set-bug-report-info! get-bug-report-infos bri-label bri-value) -(define-struct bri (label get-value)) +(struct bri (label get-value) #:transparent) (define (bri-value bri) ((bri-get-value bri))) ;; update with symbol/string assoc list (define bug-report-infos null) (define (set-bug-report-info! str thunk) - (set! bug-report-infos (cons (make-bri str thunk) bug-report-infos))) + (set! bug-report-infos (cons (bri str thunk) bug-report-infos))) (define (get-bug-report-infos) bug-report-infos) diff --git a/collects/help/private/save-bug-report.rkt b/collects/help/private/save-bug-report.rkt new file mode 100644 index 0000000000..56b10adf31 --- /dev/null +++ b/collects/help/private/save-bug-report.rkt @@ -0,0 +1,200 @@ +#lang racket/base + +#| + +If there are saved reports when a window opens, offer to open the saved ones. + +Put the saved things in the help menu. + +|# + +(require racket/match + racket/contract + racket/serialize + racket/list + framework/preferences) + +(define bug-classes '(("software bug" "sw-bug") + ("documentation bug" "doc-bug") + ("change request" "change-request") + ("support" "support"))) + +(define (translate-class class) + (cadr (assoc class bug-classes))) + +(define bug-severities '("critical" "serious" "non-critical")) + +(define (with-pref func #:rewrite? rewrite?) + (define old (preferences:get 'drracket:unfinished-bug-reports)) + (define ans (func old)) + (if rewrite? + (preferences:set 'drracket:unfinished-bug-reports ans) + ans)) + +(define (discard-all-except f) + (with-pref + #:rewrite? #t + (λ (exp) + (filter (λ (saved-report) (f (saved-report-id saved-report))) + exp)))) + +(define valid-keys (sort '(severity + class + subject + description + how-to-repeat) + string<=? + #:key symbol->string)) + +;; id : number +;; open? : boolean? +;; table : (listof (list sym string?)) +;; (the above are only an upper bound on the constraints here; +;; see validate for more info) +(serializable-struct saved-report (id table) #:transparent) + +(define (blank-bug-form id) + (saved-report id + (for/list ([key (in-list valid-keys)]) + (list key + (case key + [(class) (car (car bug-classes))] + [(severity) (list-ref bug-severities 1)] + [else ""]))))) + + +;; valid? : any -> boolean? +;; returns #t if the saved-reports are well formed +(define (valid? saved-reports) + (cond + [(list? saved-reports) + (and (for/and ([saved-report (in-list saved-reports)]) + (validate-single saved-report)) + (no-dups (map saved-report-id saved-reports)))] + [else #f])) + +(define (no-dups l) (equal? l (remove-duplicates l))) + +(define (validate-single a-saved-report) + (match a-saved-report + [(struct saved-report ((? number?) + (list (list (? symbol? keys) vals) ...))) + (and (equal? (sort keys string<=? #:key symbol->string) + valid-keys) + (for/and ([key (in-list keys)] + [val (in-list vals)]) + (case key + [(class) (member val (map car bug-classes))] + [(severity) (member val bug-severities)] + [else (string? val)])))] + [else #f])) + +(define (register-new-bug-id) + (define ans #f) + (with-pref + #:rewrite? #t + (λ (bug-reports) + (define ids (map saved-report-id bug-reports)) + (define new-id + (let loop ([i 0]) + (cond + [(member i ids) + (loop (+ i 1))] + [else + i]))) + (set! ans (blank-bug-form new-id)) + (cons ans bug-reports))) + ans) + +;; title : label-string? +;; id : number? +(struct brinfo (title id) #:transparent) + +(define (saved-bug-report-titles/ids) + (with-pref + #:rewrite? #f + (λ (x) + (for/list ([a-saved-report (in-list x)]) + (define assoc-l (saved-report-table a-saved-report)) + (define subj-p (assoc 'subject assoc-l)) + (brinfo (trim-to-200 (regexp-replace* #rx"&" (cadr subj-p) "&&")) + (saved-report-id a-saved-report)))))) + +(define (trim-to-200 str) + (cond + [(<= (string-length str) 200) + str] + [else + (define len (string-length str)) + (define spacer " ... ") + (string-append + (substring str 0 100) + spacer + (substring str (+ (- len 100) (string-length spacer)) len))])) + +(define (lookup-bug-report id) + (or (with-pref + #:rewrite? #f + (λ (exp) + (ormap (λ (x) (and (equal? id (saved-report-id x)) x)) + exp))) + (register-new-bug-id))) + +(define (saved-report-lookup a-saved-report key) + (cadr (assoc key (saved-report-table a-saved-report)))) + +(define (save-bug-report id + #:severity severity + #:class class + #:subject subject + #:description description + #:how-to-repeat how-to-repeat) + (with-pref + #:rewrite? #t + (λ (reports) + (cons + (saved-report id (list (list 'severity severity) + (list 'class class) + (list 'subject subject) + (list 'description description) + (list 'how-to-repeat how-to-repeat))) + (filter (λ (saved-report) + (not (equal? id (saved-report-id saved-report)))) + reports))))) + +(define (unsave-bug-report id) + (with-pref + #:rewrite? #t + (λ (reports) + (filter (λ (saved-report) (not (equal? id (saved-report-id saved-report)))) + reports)))) + +(preferences:set-default 'drracket:unfinished-bug-reports + '() + valid?) +(preferences:set-un/marshall 'drracket:unfinished-bug-reports + serialize + (λ (x) + (with-handlers ((exn:fail? (λ (exn) '()))) + (deserialize x)))) + +(provide bug-severities + bug-classes + translate-class + (struct-out brinfo) + saved-report?) +(provide/contract + [register-new-bug-id (-> saved-report?)] + [lookup-bug-report (-> number? saved-report?)] + [saved-report-lookup (-> saved-report? (apply or/c valid-keys) string?)] + [saved-report-id (-> saved-report? number?)] + [save-bug-report (-> number? + #:severity (apply or/c bug-severities) + #:class (apply or/c (map car bug-classes)) + #:subject string? + #:description string? + #:how-to-repeat string? + void?)] + [unsave-bug-report (-> number? void?)] + [saved-bug-report-titles/ids (-> (listof brinfo?))] + [discard-all-except (-> (-> number? boolean?) void?)]) diff --git a/collects/string-constants/danish-string-constants.rkt b/collects/string-constants/danish-string-constants.rkt index a0704a2324..90b4319445 100644 --- a/collects/string-constants/danish-string-constants.rkt +++ b/collects/string-constants/danish-string-constants.rkt @@ -156,7 +156,7 @@ please adhere to these guidelines: (bug-report-synthesized-information "Indsamlet information") ;; dialog title (bug-report-show-synthesized-info "Vis indsamlet information") (bug-report-submit "Send") - (bug-report-submit-menu-item "Send fejlrapport") ;; in Help Menu (drs & help desk) + (bug-report-submit-menu-item "Send fejlrapport...") ;; in Help Menu (drs & help desk) (error-sending-bug-report "Fejl under afsendelse af fejlrapport") (error-sending-bug-report-expln "Der opstod en fejl ved afsendelse af fejlrapporten. Hvis din internetforbindelse ellers er velfungerende, besøg venligst:\n\n http://bugs.racket-lang.org/\n\nog send fejlrapporten ved hjælp af vores online fejlrapporteringsside. Vi er kede af besværet.\n\nFejlmeddelelsen er:\n~a") (illegal-bug-report "Ugyldig fejlrapport") diff --git a/collects/string-constants/english-string-constants.rkt b/collects/string-constants/english-string-constants.rkt index ed11703cff..4f83a864bf 100644 --- a/collects/string-constants/english-string-constants.rkt +++ b/collects/string-constants/english-string-constants.rkt @@ -153,12 +153,19 @@ please adhere to these guidelines: (bug-report-field-docs-installed "Docs Installed") (bug-report-field-collections "Collections") (bug-report-field-human-language "Human Language") - (bug-report-field-memory-use "Memory Use") + (bug-report-field-memory-use "Memory Use") (bug-report-field-version "Version") (bug-report-synthesized-information "Synthesized Information") ;; dialog title (bug-report-show-synthesized-info "Show Synthesized Info") (bug-report-submit "Submit") - (bug-report-submit-menu-item "Submit Bug Report") ;; in Help Menu (drs & help desk) + (close-and-save-bug-report "Close && Save") ;; button in bug report dialog, next to cancel and bug-report-submit + (bug-report-submit-menu-item "Submit Bug Report...") ;; same as above, but used when there are saved bug reports + (saved-bug-reports-menu-item "Saved Bug Reports") ;; in Help Menu, submenu title + (disacard-all-saved-bug-reports "Discard All Saved Bug Reports") ;; menu item: only shows up when there is more than one saved bug report + (no-saved-bug-reports "No bug reports have been saved") ;; an info message that shows up as a disabled menu item when no saved bug reports are around + (new-bug-report "New Bug Report") ;; button label the user sees when there are saved bug reports, but the user asks to save another one. + (close-and-save "Close and Save") ;; button on the bottom of the bug report form + (saved-unsubmitted-bug-reports "Saved, unsubmitted bug reports:") ;; next to previous line in same dialog, followed by list of bug report subjects (as buttons) (error-sending-bug-report "Error Sending Bug Report") (error-sending-bug-report-expln "An error occurred when sending this bug report. If your internet connection is otherwise working fine, please visit:\n\n http://bugs.racket-lang.org/\n\nand submit the bug via our online web-form. Sorry for the difficulties.\n\nThe error message is:\n~a") (illegal-bug-report "Illegal Bug Report") diff --git a/collects/string-constants/french-string-constants.rkt b/collects/string-constants/french-string-constants.rkt index 28c27946cb..51f572b7c2 100644 --- a/collects/string-constants/french-string-constants.rkt +++ b/collects/string-constants/french-string-constants.rkt @@ -158,7 +158,7 @@ (bug-report-synthesized-information "Information Synthétisée") ;; dialog title (bug-report-show-synthesized-info "Montrer l'information synthétisée") (bug-report-submit "Soumettre") - (bug-report-submit-menu-item "Soumettre un rapport de bogue") ;; in Help Menu (drs & help desk) + (bug-report-submit-menu-item "Soumettre un rapport de bogue...") ;; in Help Menu (drs & help desk) (error-sending-bug-report "Erreur durant la soumission du rapport de bogue.") (error-sending-bug-report-expln "Une erreur s'est produite pendant la soumission de votre rapport de bogue. Si votre connexion Internet fonctionne correctement, veuillez visiter :\n\n http://bugs.racket-lang.org/\n\net soumettre votre bogue en utilisant notre formulaire web en ligne. Je suis vraiment profondément désolé pour toutes vos difficultés.\n\nLe message d'erreur est :\n~a") (illegal-bug-report "Formulaire de soumission de bogue incomplet.") diff --git a/collects/string-constants/german-string-constants.rkt b/collects/string-constants/german-string-constants.rkt index dab3600c79..08a11d8e37 100644 --- a/collects/string-constants/german-string-constants.rkt +++ b/collects/string-constants/german-string-constants.rkt @@ -60,7 +60,7 @@ (bug-report-synthesized-information "Generierte Information") ;; dialog title (bug-report-show-synthesized-info "Generierte Informationen anzeigen") ; (an)zeigen (bug-report-submit "Abschicken") - (bug-report-submit-menu-item "Bug-Report abschicken") ;; in Help Menu (drs & help desk) + (bug-report-submit-menu-item "Bug-Report abschicken...") ;; in Help Menu (drs & help desk) (error-sending-bug-report "Versendung des Bug-Reports fehlgeschlagen") (error-sending-bug-report-expln "Ein Fehler ist beim Versenden des Bug-Reports aufgetreten. Falls Ihre Internet-Verbindung eigentlich funktioniert, besuchen Sie bitte:\n\n http://bugs.racket-lang.org/ \n\nund teilen Sie uns den Bug mit unserem Online-Formular mit. Wir bitten um Ihr Verständnis.\n\nDie Fehlermeldung lautet:\n~a") (illegal-bug-report "Ungültiger Bug-Report") diff --git a/collects/string-constants/japanese-string-constants.rkt b/collects/string-constants/japanese-string-constants.rkt index ea6329e7ab..f54e686b0e 100644 --- a/collects/string-constants/japanese-string-constants.rkt +++ b/collects/string-constants/japanese-string-constants.rkt @@ -157,7 +157,7 @@ please adhere to these guidelines: (bug-report-synthesized-information "詳細情報") ;; dialog title (bug-report-show-synthesized-info "詳細情報の表示") (bug-report-submit "送信") - (bug-report-submit-menu-item "バグ報告の送信") ;; in Help Menu (drs & help desk) + (bug-report-submit-menu-item "バグ報告の送信...") ;; in Help Menu (drs & help desk) (error-sending-bug-report "バグ報告の送信エラー") (error-sending-bug-report-expln "バグ報告の送信中にエラーが発生しました。もし、インターネット接続が正常であるなら、\n\n http://bugs.racket-lang.org/\n\nを開いて、オンラインのウェブフォームからバグ報告を行ってください。お手間をかけて申し訳ありません。\n\nエラーメッセージ:\n~a") (illegal-bug-report "バグ報告が正しく入力されていません") diff --git a/collects/string-constants/korean-string-constants.rkt b/collects/string-constants/korean-string-constants.rkt index b25054444f..7ffb079625 100644 --- a/collects/string-constants/korean-string-constants.rkt +++ b/collects/string-constants/korean-string-constants.rkt @@ -76,7 +76,7 @@ (bug-report-synthesized-information "세부 정보") ;; dialog title (bug-report-show-synthesized-info "세부 정보 보기") (bug-report-submit "제출") - (bug-report-submit-menu-item "오류 보고 제출") ;; in Help Menu (drs & help desk) + (bug-report-submit-menu-item "오류 보고 제출...") ;; in Help Menu (drs & help desk) (error-sending-bug-report "오류 보고 보내기 오류") (error-sending-bug-report-expln "오류 보고 도중에 오류가 발생했습니다. 다른 인터넷 연결이 원활하다면, 다음 사이트를 방문하여:\n\n http://bugs.racket-lang.org/\n\n 오류 보고를 온라인 형식으로 제출하여 주십시오. 불편을 드려 죄송합니다.\n\n 오류 메세지는 다음과 같습니다 :\n~a") diff --git a/collects/string-constants/portuguese-string-constants.rkt b/collects/string-constants/portuguese-string-constants.rkt index cf04a382e6..37a994aba8 100644 --- a/collects/string-constants/portuguese-string-constants.rkt +++ b/collects/string-constants/portuguese-string-constants.rkt @@ -158,7 +158,7 @@ please adhere to these guidelines: (bug-report-synthesized-information "Informação Gerada") ;; dialog title (bug-report-show-synthesized-info "Mostrar Informação Gerada") (bug-report-submit "Enviar") - (bug-report-submit-menu-item "Enviar relatório de erro") ;; in Help Menu (drs & help desk) + (bug-report-submit-menu-item "Enviar relatório de erro...") ;; in Help Menu (drs & help desk) (error-sending-bug-report "Erro a Enviar relatório de erro") (error-sending-bug-report-expln "Um erro ocorreu enquanto o relatório de erro estava a ser enviado. Se a sua ligação à internet está a funcionar correctamente, por favor visite:\n\n http://bugs.racket-lang.org/\n\ne envie o erro através do nosso formulário online. Pedimos desculpa pelo incómodo.\n\nA mensagem de erro é:\n~a") (illegal-bug-report "Relatório de Erro Ilegal") diff --git a/collects/string-constants/russian-string-constants.rkt b/collects/string-constants/russian-string-constants.rkt index 46b5fd8004..a8648342e9 100644 --- a/collects/string-constants/russian-string-constants.rkt +++ b/collects/string-constants/russian-string-constants.rkt @@ -158,7 +158,7 @@ please adhere to these guidelines: (bug-report-synthesized-information "Собранные данные") ;; dialog title (bug-report-show-synthesized-info "Показать собранные данные") (bug-report-submit "Отправить") - (bug-report-submit-menu-item "Отправить отчет об ошибке") ;; in Help Menu (drs & help desk) + (bug-report-submit-menu-item "Отправить отчет об ошибке...") ;; in Help Menu (drs & help desk) (error-sending-bug-report "Сбой при отправке отчета об ошибке") (error-sending-bug-report-expln "При отправке отчета об ошибке произошел сбой. При наличии работающего подключения к Internet посетите сайт:\n\n http://bugs.racket-lang.org/\n\nи отправьте отчет об ошибке через Web-форму на нем. Извините за неудобства.\n\nСообщение об ошибке:\n~a") (illegal-bug-report "Некорректный отчет об ошибке") diff --git a/collects/string-constants/simplified-chinese-string-constants.rkt b/collects/string-constants/simplified-chinese-string-constants.rkt index c0d39b5448..714648f79a 100644 --- a/collects/string-constants/simplified-chinese-string-constants.rkt +++ b/collects/string-constants/simplified-chinese-string-constants.rkt @@ -85,7 +85,7 @@ (bug-report-synthesized-information "综合信息") ;; dialog title (bug-report-show-synthesized-info "显示综合信息") (bug-report-submit "提交") - (bug-report-submit-menu-item "提交程序错误报告") ;; in Help Menu (drs & help desk) + (bug-report-submit-menu-item "提交程序错误报告...") ;; in Help Menu (drs & help desk) (error-sending-bug-report "程序错误报告传输出错") (error-sending-bug-report-expln "在传输程序错误报告的过程中出现了错误。如果你能够正常浏览网络,请访问:\n\n http://bugs.racket-lang.org/\n\n使用网页上的表单提交程序错误报告。对于由此产生的不便,我们表示抱歉。\n\n传输错误详情:\n~a") (illegal-bug-report "非法的程序错误报告") diff --git a/collects/string-constants/spanish-string-constants.rkt b/collects/string-constants/spanish-string-constants.rkt index 2eda0ca238..effdd4d683 100644 --- a/collects/string-constants/spanish-string-constants.rkt +++ b/collects/string-constants/spanish-string-constants.rkt @@ -65,7 +65,7 @@ (bug-report-synthesized-information "Información sintetizada") ;; dialog title (bug-report-show-synthesized-info "Muestra información resumida") (bug-report-submit "Enviar") - (bug-report-submit-menu-item "Enviar reporte de problemas") ;; in Help Menu (drs & help desk) + (bug-report-submit-menu-item "Enviar reporte de problemas...") ;; in Help Menu (drs & help desk) (error-sending-bug-report "Error al enviar el reporte de problemas") (error-sending-bug-report-expln "Un error ocurrió mientras enviaba éste reporte de problemas. Si tu conexión a Internet está funcionando bien, por favor visita:\n\n http://bugs.racket-lang.org/\n\ny envía el reporte de problemas por medio de la forma de web en esea página de WEB. Sentimos mucho las molestias que esto te ocasiona.\n\nEl mensaje de error es:\n~a") (illegal-bug-report "Reporte de problemas ilegal") diff --git a/collects/string-constants/traditional-chinese-string-constants.rkt b/collects/string-constants/traditional-chinese-string-constants.rkt index 82176b6a12..5aea32505d 100644 --- a/collects/string-constants/traditional-chinese-string-constants.rkt +++ b/collects/string-constants/traditional-chinese-string-constants.rkt @@ -84,7 +84,7 @@ (bug-report-synthesized-information "综合信息") ;; dialog title (bug-report-show-synthesized-info "显示综合信息") (bug-report-submit "提交") - (bug-report-submit-menu-item "提交程序错误报告") ;; in Help Menu (drs & help desk) + (bug-report-submit-menu-item "提交程序错误报告...") ;; in Help Menu (drs & help desk) (error-sending-bug-report "程序错误报告传输出错") (error-sending-bug-report-expln "在传输程序错误报告的过程中出现了错误。如果你能够正常浏览网络,请访问:\n\n http://bugs.racket-lang.org/\n\n使用网页上的表单提交程序错误报告。对于由此产生的不便,我们表示抱歉。\n\n传输错误详情:\n~a") (illegal-bug-report "非法的程序错误报告") diff --git a/collects/string-constants/ukrainian-string-constants.rkt b/collects/string-constants/ukrainian-string-constants.rkt index 0dddde3444..9b8e542fdf 100644 --- a/collects/string-constants/ukrainian-string-constants.rkt +++ b/collects/string-constants/ukrainian-string-constants.rkt @@ -158,7 +158,7 @@ please adhere to these guidelines: (bug-report-synthesized-information "Зібрані дані") ;; dialog title (bug-report-show-synthesized-info "Показати зібрані дані") (bug-report-submit "Відправити") - (bug-report-submit-menu-item "Відправити звіт про помилку") ;; in Help Menu (drs & help desk) + (bug-report-submit-menu-item "Відправити звіт про помилку...") ;; in Help Menu (drs & help desk) (error-sending-bug-report "Збій при відправці звіту про помилку") (error-sending-bug-report-expln "При відправці звіту про помилку відбувся збій. При наявності підключення до Internet відвідайте сайт:\n\n http://bugs.racket-lang.org/\n\nі відправте звіт про помилку через Web-форму на ньому. Вибачте за незручності.\n\nПовідомлення про помилку:\n~a") (illegal-bug-report "Некоректний звіт про помилку")