Skip to content

Commit c78b249

Browse files
committed
Time input and start of input field parser rewrite
1 parent e56e0b3 commit c78b249

14 files changed

+492
-15
lines changed

jest.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ module.exports = {
22
preset: "ts-jest",
33
testEnvironment: "jsdom",
44
moduleDirectories: ["node_modules", "src"],
5+
verbose: true,
56
};

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/inputFields/DateInputField.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ export class DateInputField extends AbstractInputField {
2222
'12': 'December',
2323
};
2424
days: Record<string, string>;
25-
years: Record<string, string>;
2625

2726
monthComponent: DropdownComponent;
2827
dayComponent: DropdownComponent;
@@ -36,11 +35,6 @@ export class DateInputField extends AbstractInputField {
3635
for (let i = 1; i <= 31; i++) {
3736
this.days[i.toString()] = i.toString();
3837
}
39-
40-
this.years = {};
41-
for (let i = 1970; i < 2030; i++) {
42-
this.years[i.toString()] = i.toString();
43-
}
4438
}
4539

4640
public getHtmlElement(): HTMLElement {
@@ -53,7 +47,7 @@ export class DateInputField extends AbstractInputField {
5347

5448
public setValue(value: string): void {
5549
this.date = DateParser.parse(value);
56-
console.log(this.date);
50+
// console.log(this.date);
5751
this.monthComponent.setValue(this.date.getMonth().toString());
5852
this.dayComponent.setValue(this.date.getDay().toString());
5953
this.yearComponent.setValue(this.date.getYear().toString());
@@ -69,7 +63,7 @@ export class DateInputField extends AbstractInputField {
6963

7064
public render(container: HTMLDivElement): void {
7165
this.date = DateParser.parse(this.inputFieldMarkdownRenderChild.getInitialValue()) ?? DateParser.getDefaultDate();
72-
console.log(this.date);
66+
// console.log(this.date);
7367

7468
container.removeClass('meta-bind-plugin-input-wrapper');
7569
container.addClass('meta-bind-plugin-flex-input-wrapper', 'meta-bind-plugin-input-element-group');
@@ -115,7 +109,7 @@ export class DateInputField extends AbstractInputField {
115109
}
116110

117111
private onMonthChange(value: string): void {
118-
console.log(value);
112+
// console.log(value);
119113
this.date.setMonthFromString(value);
120114
this.onValueChange(this.getValue());
121115
}

src/inputFields/InputFieldFactory.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {TextAreaInputField} from './TextAreaInputField';
77
import {SelectInputField} from './SelectInputField';
88
import {MultiSelectInputField} from './MultiSelectInputField';
99
import {DateInputField} from './DateInputField';
10+
import {TimeInputField} from './TimeInputField';
1011

1112
export enum InputFieldType {
1213
TOGGLE = 'toggle',
@@ -16,6 +17,7 @@ export enum InputFieldType {
1617
SELECT = 'select',
1718
MULTI_SELECT = 'multi_select',
1819
DATE = 'date',
20+
TIME = 'time',
1921
INVALID = 'invalid',
2022
}
2123

@@ -77,6 +79,14 @@ export class InputFieldFactory {
7779
throw new Error(`can not create ${inputFieldType} as inline code block`);
7880
}
7981
return new DateInputField(args.inputFieldMarkdownRenderChild, args.onValueChanged);
82+
} else if (inputFieldType === InputFieldType.TIME) {
83+
if (args.type === InputFieldMarkdownRenderChildType.CODE_BLOCK && !TimeInputField.allowCodeBlock) {
84+
throw new Error(`can not create ${inputFieldType} as code block`);
85+
}
86+
if (args.type === InputFieldMarkdownRenderChildType.INLINE_CODE_BLOCK && !TimeInputField.allowInlineCodeBlock) {
87+
throw new Error(`can not create ${inputFieldType} as inline code block`);
88+
}
89+
return new TimeInputField(args.inputFieldMarkdownRenderChild, args.onValueChanged);
8090
}
8191

8292
return null;

src/inputFields/SliderInputField.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export class SliderInputField extends AbstractInputField {
4848

4949
let labelArgument = this.inputFieldMarkdownRenderChild.getArgument('labels');
5050
if (labelArgument && labelArgument.value === true) {
51-
container.createSpan({text: this.minValue.toString(), cls: 'meta-bind-slider-label'});
51+
container.createSpan({text: this.minValue.toString(), cls: 'meta-bind-plugin-slider-input-label'});
5252
}
5353

5454
const component = new SliderComponent(container);
@@ -59,7 +59,7 @@ export class SliderInputField extends AbstractInputField {
5959
component.sliderEl.addClass('meta-bind-plugin-slider-input');
6060

6161
if (labelArgument && labelArgument.value === true) {
62-
container.createSpan({text: this.maxValue.toString(), cls: 'meta-bind-slider-label'});
62+
container.createSpan({text: this.maxValue.toString(), cls: 'meta-bind-plugin-slider-input-label'});
6363
}
6464

6565
this.sliderComponent = component;

src/inputFields/TimeInputField.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import {AbstractInputField} from './AbstractInputField';
2+
import {DropdownComponent} from 'obsidian';
3+
import {InputFieldMarkdownRenderChild} from '../InputFieldMarkdownRenderChild';
4+
import {Time, TimeParser} from '../parsers/TimeParser';
5+
6+
export class TimeInputField extends AbstractInputField {
7+
container: HTMLDivElement;
8+
time: Time;
9+
10+
hours: Record<string, string>;
11+
minutes: Record<string, string>;
12+
13+
hourComponent: DropdownComponent;
14+
minuteComponent: DropdownComponent;
15+
16+
17+
constructor(inputFieldMarkdownRenderChild: InputFieldMarkdownRenderChild, onValueChange: (value: any) => (void | Promise<void>)) {
18+
super(inputFieldMarkdownRenderChild, onValueChange);
19+
20+
this.hours = {};
21+
for (let i = 0; i <= 24; i++) {
22+
this.hours[i.toString()] = i.toString();
23+
}
24+
25+
this.minutes = {};
26+
for (let i = 0; i <= 59; i++) {
27+
this.minutes[i.toString()] = i.toString();
28+
}
29+
}
30+
31+
public getHtmlElement(): HTMLElement {
32+
return this.container;
33+
}
34+
35+
public getValue(): string {
36+
return TimeParser.stringify(this.time);
37+
}
38+
39+
public setValue(value: string): void {
40+
this.time = TimeParser.parse(value);
41+
// console.log(this.time);
42+
this.hourComponent.setValue(this.time.getHour().toString());
43+
this.minuteComponent.setValue(this.time.getMinute().toString());
44+
}
45+
46+
public isEqualValue(value: any): boolean {
47+
return value == this.getValue();
48+
}
49+
50+
public getDefaultValue(): any {
51+
return TimeParser.stringify(TimeParser.getDefaultTime());
52+
}
53+
54+
public render(container: HTMLDivElement): void {
55+
this.time = TimeParser.parse(this.inputFieldMarkdownRenderChild.getInitialValue()) ?? TimeParser.getDefaultTime();
56+
// console.log(this.date);
57+
58+
container.removeClass('meta-bind-plugin-input-wrapper');
59+
container.addClass('meta-bind-plugin-flex-input-wrapper', 'meta-bind-plugin-input-element-group');
60+
61+
this.hourComponent = new DropdownComponent(container);
62+
this.hourComponent.addOptions(this.hours);
63+
this.hourComponent.setValue(this.time.getHour().toString());
64+
this.hourComponent.onChange(this.onHourChange.bind(this));
65+
66+
this.minuteComponent = new DropdownComponent(container);
67+
this.minuteComponent.addOptions(this.minutes);
68+
this.minuteComponent.setValue(this.time.getMinute().toString());
69+
this.minuteComponent.onChange(this.onMinuteChange.bind(this));
70+
71+
this.hourComponent.selectEl.addClass('meta-bind-plugin-input-element-group-element');
72+
this.minuteComponent.selectEl.addClass('meta-bind-plugin-input-element-group-element');
73+
74+
this.container = container;
75+
}
76+
77+
private onHourChange(value: string): void {
78+
this.time.setHourFromString(value);
79+
this.onValueChange(this.getValue());
80+
}
81+
82+
private onMinuteChange(value: string): void {
83+
this.time.setMinuteFromString(value);
84+
this.onValueChange(this.getValue());
85+
}
86+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import {InputFieldType} from '../inputFields/InputFieldFactory';
2+
import {CharPair, ParserUtils} from '../utils/ParserUtils';
3+
4+
interface InputFieldDeclaration {
5+
fullDeclaration: string;
6+
declaration: string;
7+
inputFieldType: InputFieldType;
8+
isBound: boolean;
9+
bindTarget: string;
10+
11+
arguments: InputFieldArgument[];
12+
}
13+
14+
interface InputFieldArgument {
15+
name: string;
16+
value: any;
17+
}
18+
19+
export class InputFieldDeclarationParser {
20+
static roundBracesPair: CharPair = new CharPair('(', ')');
21+
static squareBracesPair: CharPair = new CharPair('[', ']');
22+
static curlyBracesPair: CharPair = new CharPair('{', '}');
23+
static allBracesPairs: CharPair[] = [
24+
InputFieldDeclarationParser.roundBracesPair,
25+
InputFieldDeclarationParser.squareBracesPair,
26+
InputFieldDeclarationParser.curlyBracesPair,
27+
];
28+
29+
30+
static parse(fullDeclaration: string): InputFieldDeclaration {
31+
const inputFieldDeclaration: InputFieldDeclaration = {} as InputFieldDeclaration;
32+
33+
inputFieldDeclaration.fullDeclaration = fullDeclaration;
34+
inputFieldDeclaration.declaration = InputFieldDeclarationParser.extractDeclaration(inputFieldDeclaration.fullDeclaration);
35+
36+
const declarationParts: string[] = ParserUtils.split(inputFieldDeclaration.declaration, ':', InputFieldDeclarationParser.allBracesPairs);
37+
38+
const bindTarget: string = declarationParts[1] ?? '';
39+
inputFieldDeclaration.isBound = !!bindTarget;
40+
41+
const inputFieldTypeWithArguments: string = declarationParts[0];
42+
43+
44+
return inputFieldDeclaration;
45+
}
46+
47+
static extractDeclaration(fullDeclaration: string): string {
48+
return ParserUtils.sliceInBetween(fullDeclaration, InputFieldDeclarationParser.squareBracesPair);
49+
}
50+
51+
52+
}

src/parsers/TimeParser.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
export class Time {
2+
private _hour: number;
3+
private _minute: number;
4+
5+
constructor() {
6+
this.setHour(TimeParser.getDefaultHour());
7+
this.setMinute(TimeParser.getDefaultMinute());
8+
}
9+
10+
public getHour(): number {
11+
return this._hour;
12+
}
13+
14+
public setHour(value: number) {
15+
if (value < 0 || value > 24) {
16+
return;
17+
}
18+
this._hour = value;
19+
}
20+
21+
public getMinute(): number {
22+
return this._minute;
23+
}
24+
25+
public setMinute(value: number) {
26+
if (value < 0 || value > 59) {
27+
return;
28+
}
29+
this._minute = value;
30+
}
31+
32+
public getUniformHour(): string {
33+
return ('00' + this.getHour().toString()).slice(-2);
34+
}
35+
36+
public getUniformMinute(): string {
37+
return ('00' + this.getMinute().toString()).slice(-2);
38+
}
39+
40+
public setHourFromString(str: string) {
41+
let v = Number.parseInt(str);
42+
this.setHour(Number.isNaN(v) ? TimeParser.getDefaultHour() : v);
43+
}
44+
45+
public setMinuteFromString(str: string) {
46+
let v = Number.parseInt(str);
47+
this.setMinute(Number.isNaN(v) ? TimeParser.getDefaultMinute() : v);
48+
}
49+
}
50+
51+
export class TimeParser {
52+
public static parse(timeString: string): Time {
53+
const time: Time = TimeParser.getDefaultTime();
54+
55+
const timeParts = timeString.split(':');
56+
if (timeParts.length !== 2) {
57+
return null;
58+
}
59+
60+
time.setHourFromString(timeParts[0]);
61+
time.setMinuteFromString(timeParts[1]);
62+
63+
return time;
64+
}
65+
66+
public static stringify(time: Time): string {
67+
return `${time.getUniformHour()}:${time.getUniformMinute()}`;
68+
}
69+
70+
public static getDefaultTime(): Time {
71+
return new Time();
72+
}
73+
74+
public static getDefaultHour(): number {
75+
return 0;
76+
}
77+
78+
public static getDefaultMinute(): number {
79+
return 0;
80+
}
81+
}

src/settings/Settings.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export class MetaBindSettingTab extends PluginSettingTab {
6464
'fs_us': 'US date format (Jan 30, 2022)',
6565
});
6666
cb.onChange(data => {
67-
this.plugin.settings.dateFormat = data as any;
67+
this.plugin.settings.dateFormat = data as DateFormat;
6868
this.plugin.saveSettings();
6969
});
7070
});

0 commit comments

Comments
 (0)