SET @cnt = (SELECT COUNT(1) FROM image_size WHERE folder = '840x1190');
INSERT INTO `image_size`
(`id`, `folder`, `quality`, `xsize`, `ysize`,
`image_resize_id`, `diagonal`, `watermark__image_id`,
`watermark_xsize`, `watermark_ysize`,
`watermark_xpos`, `watermark_ypos`,
`crop_left`, `crop_top`, `trim`, `grayscale`,
`filter_color`, `filter_opacity`)
SELECT NULL, '840x1190', 95, 840, 1190,
0, NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL, NULL, 0, 0,
NULL, NULL
WHERE @cnt = 0;
<script setup>
import {reactive, watch} from "vue";
import BaseLabel from "./BaseLabel.vue";
import BaseInput from "./BaseInput.vue";
import BaseTextarea from "./BaseTextarea.vue";
import SecondaryButton from "./SecondaryButton.vue";
import BaseButton from "./BaseButton.vue";
import BaseCheckbox from "./BaseCheckbox.vue";
import BaseSwitch from "./BaseSwitch.vue";
const form = reactive({
name: null,
is_sellable: false,
is_available_online: false,
is_available_in_stores: false,
price: null,
description: null,
});
/**
* Separate watchers
*/
watch(
() => form.is_available_online,
isAvailableOnline => {
if (!isAvailableOnline && !form.is_available_in_stores) {
form.is_sellable = false;
}
}
);
watch(
() => form.is_available_in_stores,
isAvailableInStores => {
if (!isAvailableInStores && !form.is_available_online) {
form.is_sellable = false;
}
}
);
/**
* Watch multiple values in the same watch function
*/
watch(
() => [form.is_available_online, form.is_available_in_stores],
([isAvailableOnline, isAvailableInStores]) => {
if (!isAvailableOnline && !isAvailableInStores) {
form.is_sellable = false;
}
}
);
/**
* Combine watched values
*/
watch(
() => form.is_available_online || form.is_available_in_stores,
isSellable => (form.is_sellable = isSellable)
);
</script>
<template>
<form class="bg-white p-6 rounded-xl shadow">
<div class="space-y-6 sm:space-y-5">
<div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start">
<BaseLabel required>Name</BaseLabel>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<BaseInput
v-model="form.name"
placeholder="Enter product name"
type="text"
></BaseInput>
</div>
</div>
<div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start">
<BaseLabel>Can be sold?</BaseLabel>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<BaseSwitch v-model="form.is_sellable"></BaseSwitch>
</div>
</div>
<template v-if="form.is_sellable">
<div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start">
<BaseLabel>Available in online stores</BaseLabel>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<BaseCheckbox v-model:checked="form.is_available_online" />
</div>
</div>
<div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start">
<BaseLabel>Available in physical stores</BaseLabel>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<BaseCheckbox v-model:checked="form.is_available_in_stores" />
</div>
</div>
<div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start">
<BaseLabel>Price</BaseLabel>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<BaseInput
v-model="form.price"
placeholder="Enter price"
type="number"
></BaseInput>
</div>
</div>
</template>
<div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start">
<BaseLabel>Description</BaseLabel>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<BaseTextarea
v-model="form.description"
placeholder="Enter product description"
rows="3"
></BaseTextarea>
</div>
</div>
</div>
<div class="pt-5">
<div class="flex justify-end">
<SecondaryButton type="button">Cancel</SecondaryButton>
<BaseButton type="submit">Save</BaseButton>
</div>
</div>
</form>
</template>
<script setup>
import {ref, computed} from "vue";
const people = ref([
{id: 1, firstName: 'Constantin', lastName: 'Druc'},
{id: 2, firstName: 'Jack', lastName: 'Dorsey'},
{id: 3, firstName: 'Bill', lastName: 'Burr'},
{id: 4, firstName: 'Hugh', lastName: 'Jackman'},
{id: 5, firstName: 'Tracey', lastName: 'Johnes'},
]);
function fullName(firstName, lastName) {
console.log('fullName() was executed');
return firstName + ' ' + lastName;
}
</script>
<template>
<ul>
<li v-for="person in people" :key="person.id">
{{ fullName(person.firstName, person.lastName) }}
</li>
</ul>
</template>
<script setup>
import ShoppingCart from "./ShoppingCart.vue";
import {ref} from "vue";
const isOpened = ref(false);
</script>
<template>
<button @click="isOpened = true">Open cart</button>
<ShoppingCart :is-opened="isOpened" @toggle="(value) => isOpened = value"/>
</template>
<script setup>
import axios from "axios";
import Player from "@vimeo/player";
import {throttle} from "lodash";
import ForwardIcon from "./svgs/ForwardIcon";
import BackwardIcon from "./svgs/BackwardIcon";
import LoadingIcon from "./svgs/LoadingIcon";
import {computed, onMounted, onUnmounted, ref, useSlots} from "vue";
const props = defineProps({
lessonId: Number,
trackProgress: Boolean
});
const speedIndex = ref(1);
let player = null;
const speedOptions = [0.75, 1, 1.25, 1.5, 1.75, 2.0];
const currentSpeed = computed(() => speedOptions[speedIndex.value]);
if (window.localStorage.getItem('speedIndex')) {
speedIndex.value = parseInt(window.localStorage.getItem('speedIndex'));
}
onMounted(() => {
player = new Player(useSlots().default()[0].el);
player.on('play', () => player.setPlaybackRate(currentSpeed.value));
if (props.trackProgress) {
player.on('progress', throttle((event) => updateProgress(event.percent), 10000));
player.on('ended', () => updateProgress(1));
}
});
onUnmounted(() => {
player.off('play');
player.off('progress');
player.off('ended');
});
function updateProgress(percent) {
return axios.put(`/lessons/${props.lessonId}/progress`, {percent: percent});
}
function toggleSpeed() {
if (typeof speedOptions[speedIndex.value + 1] !== "undefined") {
speedIndex.value += 1;
} else {
speedIndex.value = 0;
}
window.localStorage.setItem('speedIndex', speedIndex.value);
player.setPlaybackRate(currentSpeed.value);
}
async function goForward(seconds) {
const currentTime = await player.getCurrentTime();
const totalDuration = await player.getDuration();
player.setCurrentTime(Math.min(totalDuration, (currentTime + seconds)));
}
async function goBack(seconds) {
const currentTime = await player.getCurrentTime();
player.setCurrentTime(Math.max(0, (currentTime - seconds)));
}
</script>
<template>
<div class="relative aspect-w-16 aspect-h-9">
<div class="flex absolute inset-0 justify-center items-center">
<LoadingIcon class="w-14 h-14 text-white animate-spin"></LoadingIcon>
</div>
<slot></slot>
</div>
<div class="flex justify-end">
<div class="grid grid-cols-5 w-full max-w-xl divide-x divide-gray-700">
<button
class="inline-flex justify-center items-center p-2 space-x-1 text-base font-medium text-white cursor-pointer hover:text-orange-600 focus:outline-none"
@click="toggleSpeed()">
<span class="hidden sm:inline-block">Speed:</span><span>{{ currentSpeed }}x</span>
</button>
<button
class="inline-flex justify-center items-center p-2 space-x-1 text-base font-medium text-white cursor-pointer hover:text-orange-600 focus:outline-none"
@click="goBack(5)">
<BackwardIcon class="w-4 h-4"/>
<span>5s</span>
</button>
<button
class="inline-flex justify-center items-center p-2 space-x-1 text-base font-medium text-white cursor-pointer hover:text-orange-600 focus:outline-none"
@click="goForward(5)">
<span>5s</span>
<ForwardIcon class="w-4 h-4"/>
</button>
<button
class="inline-flex justify-center items-center p-2 space-x-1 text-base font-medium text-white cursor-pointer hover:text-orange-600 focus:outline-none"
@click="goBack(10)">
<BackwardIcon class="w-4 h-4"/>
<span>10s</span>
</button>
<button
class="inline-flex justify-center items-center p-2 space-x-1 text-base font-medium text-white cursor-pointer hover:text-orange-600 focus:outline-none"
@click="goForward(10)">
<span>10s</span>
<ForwardIcon class="w-4 h-4"/>
</button>
</div>
</div>
</template>
import {onUnmounted} from "vue";
export default function (src) {
return new Promise((resolve, reject) => {
let script = document.querySelector(`script[src="${src}"]`);
if (!script) {
script = document.createElement("script");
script.src = src;
script.async = true;
script.setAttribute("data-status", "loading");
document.head.append(script);
}
if (script.getAttribute("data-status") === "loaded") {
resolve();
}
function onScriptLoad() {
resolve();
script.setAttribute("data-status", "loaded");
}
function onScriptError() {
reject();
script.setAttribute("data-status", "error");
}
script.addEventListener("load", onScriptLoad);
script.addEventListener("error", onScriptError);
onUnmounted(() => {
if (document.head.contains(script)) {
script.removeEventListener("load", onScriptLoad);
script.removeEventListener("error", onScriptError);
document.head.removeChild(script);
}
})
});
}
<template>
<form class="my-20 mx-auto max-w-2xl">
<h3 class="mb-2 mt-6 text-lg font-medium">Personal info</h3>
<div class="grid grid-cols-2 gap-6 mb-6">
<label class="block text-sm font-medium text-gray-700">
First name
<input
class="block mt-1 w-full text-sm placeholder-gray-400 rounded-md border-gray-300 focus:ring-blue-500 focus:border-blue-500"
type="text"
v-model="form.firstName"
placeholder="First name"
/>
</label>
<label class="block text-sm font-medium text-gray-700">
Last name
<input
class="block mt-1 w-full text-sm placeholder-gray-400 rounded-md border-gray-300 focus:ring-blue-500 focus:border-blue-500"
type="text"
v-model="form.lastName"
placeholder="Last name"
/>
</label>
<label class="block text-sm font-medium text-gray-700">
E-mail
<input
class="block mt-1 w-full text-sm placeholder-gray-400 rounded-md border-gray-300 focus:ring-blue-500 focus:border-blue-500"
type="email"
v-model="form.email"
placeholder="E-mail address"
/>
</label>
</div>
<AddressFieldGroup
label="Delivery address"
v-model:street="form.deliveryAddress.street"
v-model:streetNumber="form.deliveryAddress.streetNumber"
v-model:postcode="form.deliveryAddress.postcode"
v-model:city="form.deliveryAddress.city"
/>
<AddressFieldGroup
label="Billing address"
v-model:street="form.billingAddress.street"
v-model:streetNumber="form.billingAddress.streetNumber"
v-model:postcode="form.billingAddress.postcode"
v-model:city="form.billingAddress.city"
/>
</form>
</template>
<script>
import {ref} from 'vue';
import AddressFieldGroup from './AddressFieldGroup.vue';
export default {
components: {AddressFieldGroup},
setup() {
const form = ref({
firstName: '321321',
lastName: '321321',
email: '321321',
deliveryAddress: {
street: '321321',
streetNumber: '321',
postcode: '321',
city: '321',
},
billingAddress: {
street: '',
streetNumber: '',
postcode: '',
city: '',
},
});
return {
form,
};
},
};
</script>
<script>
export default {
data() {
return {
status: 'idle',
};
},
methods: {
copy(text) {
// create textarea
const el = document.createElement('textarea');
// assign value
el.value = text;
// style textarea
el.style.position = 'absolute';
el.style.left = '-90000px';
document.body.appendChild(el);
// select its contents
el.select();
// execute copy
document.execCommand("copy");
// remove textarea
document.body.removeChild(el);
this.status = "copied";
setTimeout(() => this.status = "idle", 1000);
},
},
render() {
return this.$slots.default({
status: this.status,
copy: this.copy
});
}
};
</script>
// Parallel
async function getData() {
const [user, posts] = await Promise.all([
fetchUserData(),
fetchPostsData()
]);
console.log(user, posts);
}
// non parallel
function getData() {
return Promise.all([fetchUser(), fetchPosts()])
.then(([user, posts]) => {
console.log(user, posts);
})
.catch((error) => {
console.error(error);
});
}
<script setup>
import { useSlots, onMounted, ref } from "vue";
const test = ref()
onMounted(() => {
// 1
console.log(test.value.children[0])
// 2 nebo bez refu primo ze slotu useSlots().default()[0].el
})
</script>
<template>
<!-- nejde ref umistit primo na slot, nutno to takto obalit, nebo viz druhy zpusob -->
<div ref="test">
<slot />
</div>
</template>