Compare commits

..

No commits in common. "835bf0345adbecb5af842002ff3323b37f74b9cb" and "96a374726218055f3f150c3d3a6bf51999b85062" have entirely different histories.

6 changed files with 113 additions and 75 deletions

View file

@ -66,8 +66,8 @@ export default class extends Vue {
public password = ""; public password = "";
private on_keydown(e: KeyboardEvent) { private on_keydown(e: KeyboardEvent) {
if (e.key === "Enter") this.submit(); if (e.key == "Enter") this.submit();
else if (e.key === "Escape") this.cancel(); else if (e.key == "Escape") this.cancel();
} }
public mounted(): void { public mounted(): void {

View file

@ -38,7 +38,7 @@ export default class extends Vue {
public caption = ""; public caption = "";
private on_keydown(e: KeyboardEvent) { private on_keydown(e: KeyboardEvent) {
if (e.key === "Escape") this.dismiss(); if (e.key == "Escape") this.dismiss();
} }
public created(): void { public created(): void {

View file

@ -241,7 +241,7 @@ let ui_credentials: Credentials = ["", ""];
function fmt_puzzle_date(name: keyof AdminConfigModel["puzzle"]): string { function fmt_puzzle_date(name: keyof AdminConfigModel["puzzle"]): string {
const iso_date = admin_config_model.puzzle[name]; const iso_date = admin_config_model.puzzle[name];
if (!(typeof iso_date === "string")) return "-"; if (!(typeof iso_date == "string")) return "-";
return DateTime.fromISO(iso_date).toLocaleString(DateTime.DATE_SHORT); return DateTime.fromISO(iso_date).toLocaleString(DateTime.DATE_SHORT);
} }

View file

@ -5,8 +5,8 @@
<li <li
v-for="(step, index) in steps" v-for="(step, index) in steps"
:key="index" :key="index"
:class="model === index ? 'is-active' : ''" :class="modelValue === index ? 'is-active' : ''"
@click.left="model = index" @click.left="change_step(index)"
> >
<a> <a>
<span class="icon is-small"> <span class="icon is-small">
@ -22,9 +22,18 @@
<script setup lang="ts"> <script setup lang="ts">
import { Step } from "@/lib/helpers"; import { Step } from "@/lib/helpers";
const model = defineModel<number>({ required: true }); const props = defineProps<{
defineProps<{
steps: Step[]; steps: Step[];
modelValue: number;
}>(); }>();
const emit = defineEmits<{
(event: "update:modelValue", value: number): void;
}>();
function change_step(next_step: number) {
if (next_step === props.modelValue) return;
emit("update:modelValue", next_step);
}
</script> </script>

View file

@ -42,7 +42,6 @@ function transform_mouse_event(event: MouseEvent) {
// mute a useless typescript error // mute a useless typescript error
const event_type = event.type as "mousedown"; const event_type = event.type as "mousedown";
emit(event_type, event, point); emit(event_type, event, point);
} }
</script> </script>

View file

@ -9,110 +9,140 @@
@dblclick.left="remove_rect" @dblclick.left="remove_rect"
> >
<CalendarDoor <CalendarDoor
v-for="(door, index) in model" v-for="(door, index) in doors"
:key="`door-${index}`" :key="`door-${index}`"
:door="door" :door="door"
force_visible force_visible
/> />
<SVGRect <SVGRect
v-if="state.kind !== 'idle'" v-if="preview_visible"
variant="success" variant="success"
:rectangle="preview" :rectangle="preview_rect"
visible visible
/> />
</ThouCanvas> </ThouCanvas>
</template> </template>
<script setup lang="ts"> <script lang="ts">
import { Door } from "@/lib/rects/door"; import { Door } from "@/lib/rects/door";
import { Rectangle } from "@/lib/rects/rectangle"; import { Rectangle } from "@/lib/rects/rectangle";
import { Vector2D } from "@/lib/rects/vector2d"; import { Vector2D } from "@/lib/rects/vector2d";
import { Options, Vue } from "vue-class-component";
import CalendarDoor from "../calendar/CalendarDoor.vue"; import CalendarDoor from "../calendar/CalendarDoor.vue";
import SVGRect from "../calendar/SVGRect.vue"; import SVGRect from "../calendar/SVGRect.vue";
import ThouCanvas from "../calendar/ThouCanvas.vue"; import ThouCanvas from "../calendar/ThouCanvas.vue";
type CanvasState = enum CanvasState {
| { kind: "idle" } Idle,
| { kind: "drawing" } Drawing,
| { kind: "dragging"; door: Door; origin: Vector2D }; Dragging,
}
const model = defineModel<Door[]>({ required: true }); @Options({
components: {
CalendarDoor,
SVGRect,
ThouCanvas,
},
props: {
doors: Array,
},
})
export default class extends Vue {
private readonly min_rect_area = 300;
private state = CanvasState.Idle;
public preview_rect = new Rectangle();
private drag_door?: Door;
private drag_origin = new Vector2D();
public doors!: Door[];
const MIN_RECT_AREA = 300; public get preview_visible(): boolean {
let state: CanvasState = { kind: "idle" }; return this.state !== CanvasState.Idle;
let preview = new Rectangle(); }
function pop_door(point: Vector2D): Door | undefined { private pop_door(point: Vector2D): Door | undefined {
const idx = model.value.findIndex((rect) => rect.position.contains(point)); const idx = this.doors.findIndex((rect) => rect.position.contains(point));
if (idx === -1) { if (idx === -1) {
return; return;
} }
return model.value.splice(idx, 1)[0]; return this.doors.splice(idx, 1)[0];
} }
function draw_start(event: MouseEvent, point: Vector2D) { public draw_start(event: MouseEvent, point: Vector2D) {
if (state.kind !== "idle") { if (this.preview_visible) {
return; return;
} }
preview = new Rectangle(point, point); this.state = CanvasState.Drawing;
state = { kind: "drawing" }; this.preview_rect = new Rectangle(point, point);
} }
function draw_finish() { public draw_finish() {
if (state.kind !== "drawing" || preview.area < MIN_RECT_AREA) { if (this.state !== CanvasState.Drawing || this.preview_rect === undefined) {
return; return;
} }
model.value.push(new Door(preview)); this.state = CanvasState.Idle;
state = { kind: "idle" }; if (this.preview_rect.area < this.min_rect_area) {
}
function drag_start(event: MouseEvent, point: Vector2D) {
if (state.kind !== "idle") {
return; return;
} }
const drag_door = pop_door(point); this.doors.push(new Door(this.preview_rect));
}
if (drag_door === undefined) { public drag_start(event: MouseEvent, point: Vector2D) {
if (this.preview_visible) {
return; return;
} }
preview = drag_door.position; this.drag_door = this.pop_door(point);
state = { kind: "dragging", door: drag_door, origin: point }; if (this.drag_door === undefined) {
}
function drag_finish() {
if (state.kind !== "dragging") {
return; return;
} }
model.value.push(new Door(preview, state.door.day)); this.state = CanvasState.Dragging;
this.drag_origin = point;
state = { kind: "idle" }; this.preview_rect = this.drag_door.position;
}
function on_mousemove(event: MouseEvent, point: Vector2D) {
if (state.kind === "drawing") {
preview = preview.update(undefined, point);
} else if (state.kind === "dragging") {
const movement = point.minus(state.origin);
preview = state.door.position.move(movement);
} }
}
function remove_rect(event: MouseEvent, point: Vector2D) { public drag_finish() {
if (state.kind !== "idle") { if (
this.state !== CanvasState.Dragging ||
this.preview_rect === undefined
) {
return; return;
} }
pop_door(point); this.state = CanvasState.Idle;
this.doors.push(new Door(this.preview_rect, this.drag_door!.day));
}
public on_mousemove(event: MouseEvent, point: Vector2D) {
if (this.preview_rect === undefined) {
return;
}
if (this.state === CanvasState.Drawing) {
this.preview_rect = this.preview_rect.update(undefined, point);
} else if (this.state === CanvasState.Dragging && this.drag_door) {
const movement = point.minus(this.drag_origin);
this.preview_rect = this.drag_door.position.move(movement);
}
}
public remove_rect(event: MouseEvent, point: Vector2D) {
if (this.preview_visible) {
return;
}
this.pop_door(point);
}
} }
</script> </script>