mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-31 04:51:31 +08:00 
			
		
		
		
	feat(time_selector): add time_selector options widget
This commit is contained in:
		
							parent
							
								
									fbacb5bb71
								
							
						
					
					
						commit
						c0714a92d5
					
				
							
								
								
									
										126
									
								
								src/public/app/widgets/type_widgets/options/time_selector.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								src/public/app/widgets/type_widgets/options/time_selector.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,126 @@ | ||||
| import OptionsWidget from "./options_widget.js"; | ||||
| import toastService from "../../../services/toast.js"; | ||||
| import { t } from "../../../services/i18n.js"; | ||||
| import type { OptionDefinitions, OptionMap } from "../../../../../services/options_interface.js"; | ||||
| 
 | ||||
| 
 | ||||
| type TimeSelectorConstructor = { | ||||
|     widgetId: string; | ||||
|     widgetLabelId: string; | ||||
|     optionValueId: keyof OptionDefinitions; | ||||
|     optionTimeScaleId: keyof OptionDefinitions; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| const TPL = (options: Pick<TimeSelectorConstructor, "widgetId" | "widgetLabelId">) => ` | ||||
|     <div class="form-group"> | ||||
|         <label for="${options.widgetId}">${t(options.widgetLabelId)}</label> | ||||
|         <div class="d-flex gap-2"> | ||||
|             <input id="${options.widgetId}" class="form-control options-number-input" type="number" min="0" steps="1" required> | ||||
|             <select id="${options.widgetId}-time-scale" class="form-select duration-selector" required> | ||||
|                 <option value="1">${t("duration.seconds")}</option> | ||||
|                 <option value="60">${t("duration.minutes")}</option> | ||||
|                 <option value="3600">${t("duration.hours")}</option> | ||||
|                 <option value="86400">${t("duration.days")}</option> | ||||
|             </select> | ||||
|         </div> | ||||
|     </div> | ||||
| 
 | ||||
| </div> | ||||
| <style> | ||||
|     .duration-selector { | ||||
|         width: auto; | ||||
|     } | ||||
| </style>`;
 | ||||
| 
 | ||||
| export default class TimeSelector extends OptionsWidget { | ||||
| 
 | ||||
|     private $timeValueInput!: JQuery<HTMLInputElement>; | ||||
|     private $timeScaleSelect!: JQuery<HTMLSelectElement>; | ||||
|     private internalTimeInSeconds!: string | number; | ||||
|     private widgetId: string; | ||||
|     private widgetLabelId: string; | ||||
|     private optionValueId: keyof OptionDefinitions; | ||||
|     private optionTimeScaleId: keyof OptionDefinitions; | ||||
| 
 | ||||
|     constructor(options: TimeSelectorConstructor) { | ||||
|         super(); | ||||
|         this.widgetId = options.widgetId; | ||||
|         this.widgetLabelId = options.widgetLabelId; | ||||
|         this.optionValueId = options.optionValueId; | ||||
|         this.optionTimeScaleId = options.optionTimeScaleId; | ||||
|     } | ||||
| 
 | ||||
|     doRender() { | ||||
|         this.$widget = $(TPL({ | ||||
|             widgetId: this.widgetId, | ||||
|             widgetLabelId: this.widgetLabelId | ||||
|         })); | ||||
| 
 | ||||
|         this.$timeValueInput = this.$widget.find(`#${this.widgetId}`); | ||||
|         this.$timeScaleSelect = this.$widget.find(`#${this.widgetId}-time-scale`); | ||||
| 
 | ||||
|         this.$timeValueInput.on("change", () => { | ||||
|             const time = this.$timeValueInput.val(); | ||||
|             const timeScale = this.$timeScaleSelect.val(); | ||||
| 
 | ||||
|             if (!this.handleTimeValidation() || typeof timeScale !== "string" || !time) return; | ||||
| 
 | ||||
|             this.internalTimeInSeconds = this.convertTime(time, timeScale).toOption(); | ||||
|             this.updateOption(this.optionValueId, this.internalTimeInSeconds); | ||||
| 
 | ||||
|         }); | ||||
| 
 | ||||
|         this.$timeScaleSelect.on("change", () => { | ||||
| 
 | ||||
|             const timeScale = this.$timeScaleSelect.val(); | ||||
| 
 | ||||
|             if (!this.handleTimeValidation() || typeof timeScale !== "string") return; | ||||
| 
 | ||||
|             //calculate the new displayed value
 | ||||
|             const displayedTime = this.convertTime(this.internalTimeInSeconds, timeScale).toDisplay(); | ||||
| 
 | ||||
|             this.updateOption(this.optionTimeScaleId, timeScale); | ||||
|             this.$timeValueInput.val(displayedTime).trigger("change"); | ||||
| 
 | ||||
|         }); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     async optionsLoaded(options: OptionMap) { | ||||
|         this.internalTimeInSeconds = options[this.optionValueId]; | ||||
|         const displayedTime = this.convertTime(options[this.optionValueId], options[this.optionTimeScaleId]).toDisplay(); | ||||
|         this.$timeValueInput.val(displayedTime); | ||||
|         this.$timeScaleSelect.val(options[this.optionTimeScaleId]); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     convertTime(time: string | number, timeScale: string | number) { | ||||
| 
 | ||||
|         const value = typeof time === "number" ? time : parseInt(time); | ||||
|         if (Number.isNaN(value)) { | ||||
|           throw new Error(`Time needs to be a valid integer, but received: ${time}`); | ||||
|         } | ||||
| 
 | ||||
|         const operand = typeof timeScale === "number" ? timeScale : parseInt(timeScale); | ||||
|         if (Number.isNaN(operand) || operand < 1) { | ||||
|             throw new Error(`TimeScale needs to be a valid integer >= 1, but received: ${timeScale}`); | ||||
|         } | ||||
| 
 | ||||
|         return { | ||||
|             toOption: () => Math.ceil(value * operand), | ||||
|             toDisplay: () => Math.ceil(value / operand), | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     handleTimeValidation() { | ||||
|         if (this.$timeValueInput.is(":invalid")) { | ||||
|             // TriliumNextTODO: i18n
 | ||||
|             toastService.showMessage("The entered time value is not a valid number."); | ||||
|             return false | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Panagiotis Papadopoulos
						Panagiotis Papadopoulos