Compare commits
No commits in common. "835bf0345adbecb5af842002ff3323b37f74b9cb" and "96a374726218055f3f150c3d3a6bf51999b85062" have entirely different histories.
835bf0345a
...
96a3747262
6 changed files with 113 additions and 75 deletions
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue