forked from FoundKeyGang/FoundKey
remove ads from client
This commit is contained in:
parent
0e3a9d1e0d
commit
79ec9641d2
10 changed files with 4 additions and 378 deletions
|
@ -1,13 +1,12 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, h, PropType, TransitionGroup } from 'vue';
|
import { defineComponent, h, PropType, TransitionGroup } from 'vue';
|
||||||
import MkAd from '@/components/global/ad.vue';
|
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
import { defaultStore } from '@/store';
|
import { defaultStore } from '@/store';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
items: {
|
items: {
|
||||||
type: Array as PropType<{ id: string; createdAt: string; _shouldInsertAd_: boolean; }[]>,
|
type: Array as PropType<{ id: string; createdAt: string; }[]>,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
direction: {
|
direction: {
|
||||||
|
@ -25,11 +24,6 @@ export default defineComponent({
|
||||||
required: false,
|
required: false,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
ad: {
|
|
||||||
type: Boolean,
|
|
||||||
required: false,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
setup(props, { slots, expose }) {
|
setup(props, { slots, expose }) {
|
||||||
|
@ -78,15 +72,7 @@ export default defineComponent({
|
||||||
|
|
||||||
return [el, separator];
|
return [el, separator];
|
||||||
} else {
|
} else {
|
||||||
if (props.ad && item._shouldInsertAd_) {
|
return el;
|
||||||
return [h(MkAd, {
|
|
||||||
class: 'a', // advertiseの意(ブロッカー対策)
|
|
||||||
key: item.id + ':ad',
|
|
||||||
prefer: ['horizontal', 'horizontal-big'],
|
|
||||||
}), el];
|
|
||||||
} else {
|
|
||||||
return el;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,200 +0,0 @@
|
||||||
<template>
|
|
||||||
<div v-if="ad" class="qiivuoyo">
|
|
||||||
<div v-if="!showMenu" class="main" :class="ad.place">
|
|
||||||
<a :href="ad.url" target="_blank">
|
|
||||||
<img :src="ad.imageUrl">
|
|
||||||
<button class="_button menu" @click.prevent.stop="toggleMenu"><span class="fas fa-info-circle"></span></button>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div v-else class="menu">
|
|
||||||
<div class="body">
|
|
||||||
<div>Ads by {{ host }}</div>
|
|
||||||
<!--<MkButton class="button" primary>{{ $ts._ad.like }}</MkButton>-->
|
|
||||||
<MkButton v-if="ad.ratio !== 0" class="button" @click="reduceFrequency">{{ $ts._ad.reduceFrequencyOfThisAd }}</MkButton>
|
|
||||||
<button class="_textButton" @click="toggleMenu">{{ $ts._ad.back }}</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-else></div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent, ref } from 'vue';
|
|
||||||
import { instance } from '@/instance';
|
|
||||||
import { host } from '@/config';
|
|
||||||
import MkButton from '@/components/ui/button.vue';
|
|
||||||
import { defaultStore } from '@/store';
|
|
||||||
import * as os from '@/os';
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
components: {
|
|
||||||
MkButton
|
|
||||||
},
|
|
||||||
|
|
||||||
props: {
|
|
||||||
prefer: {
|
|
||||||
type: Array,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
specify: {
|
|
||||||
type: Object,
|
|
||||||
required: false
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
setup(props) {
|
|
||||||
const showMenu = ref(false);
|
|
||||||
const toggleMenu = () => {
|
|
||||||
showMenu.value = !showMenu.value;
|
|
||||||
};
|
|
||||||
|
|
||||||
const choseAd = (): (typeof instance)['ads'][number] | null => {
|
|
||||||
if (props.specify) {
|
|
||||||
return props.specify as (typeof instance)['ads'][number];
|
|
||||||
}
|
|
||||||
|
|
||||||
const allAds = instance.ads.map(ad => defaultStore.state.mutedAds.includes(ad.id) ? {
|
|
||||||
...ad,
|
|
||||||
ratio: 0
|
|
||||||
} : ad);
|
|
||||||
|
|
||||||
let ads = allAds.filter(ad => props.prefer.includes(ad.place));
|
|
||||||
|
|
||||||
if (ads.length === 0) {
|
|
||||||
ads = allAds.filter(ad => ad.place === 'square');
|
|
||||||
}
|
|
||||||
|
|
||||||
const lowPriorityAds = ads.filter(ad => ad.ratio === 0);
|
|
||||||
ads = ads.filter(ad => ad.ratio !== 0);
|
|
||||||
|
|
||||||
if (ads.length === 0) {
|
|
||||||
if (lowPriorityAds.length !== 0) {
|
|
||||||
return lowPriorityAds[Math.floor(Math.random() * lowPriorityAds.length)];
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const totalFactor = ads.reduce((a, b) => a + b.ratio, 0);
|
|
||||||
const r = Math.random() * totalFactor;
|
|
||||||
|
|
||||||
let stackedFactor = 0;
|
|
||||||
for (const ad of ads) {
|
|
||||||
if (r >= stackedFactor && r <= stackedFactor + ad.ratio) {
|
|
||||||
return ad;
|
|
||||||
} else {
|
|
||||||
stackedFactor += ad.ratio;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const chosen = ref(choseAd());
|
|
||||||
|
|
||||||
const reduceFrequency = () => {
|
|
||||||
if (chosen.value == null) return;
|
|
||||||
if (defaultStore.state.mutedAds.includes(chosen.value.id)) return;
|
|
||||||
defaultStore.push('mutedAds', chosen.value.id);
|
|
||||||
os.success();
|
|
||||||
chosen.value = choseAd();
|
|
||||||
showMenu.value = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
ad: chosen,
|
|
||||||
showMenu,
|
|
||||||
toggleMenu,
|
|
||||||
host,
|
|
||||||
reduceFrequency,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.qiivuoyo {
|
|
||||||
background-size: auto auto;
|
|
||||||
background-image: repeating-linear-gradient(45deg, transparent, transparent 8px, var(--ad) 8px, var(--ad) 14px );
|
|
||||||
|
|
||||||
> .main {
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
> a {
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
vertical-align: bottom;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
> img {
|
|
||||||
filter: contrast(120%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> img {
|
|
||||||
display: block;
|
|
||||||
object-fit: contain;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .menu {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
background: var(--panel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.square {
|
|
||||||
> a ,
|
|
||||||
> a > img {
|
|
||||||
max-width: min(300px, 100%);
|
|
||||||
max-height: 300px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.horizontal {
|
|
||||||
padding: 8px;
|
|
||||||
|
|
||||||
> a ,
|
|
||||||
> a > img {
|
|
||||||
max-width: min(600px, 100%);
|
|
||||||
max-height: 80px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.horizontal-big {
|
|
||||||
padding: 8px;
|
|
||||||
|
|
||||||
> a ,
|
|
||||||
> a > img {
|
|
||||||
max-width: min(600px, 100%);
|
|
||||||
max-height: 250px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.vertical {
|
|
||||||
> a ,
|
|
||||||
> a > img {
|
|
||||||
max-width: min(100px, 100%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .menu {
|
|
||||||
padding: 8px;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
> .body {
|
|
||||||
padding: 8px;
|
|
||||||
margin: 0 auto;
|
|
||||||
max-width: 400px;
|
|
||||||
border: solid 1px var(--divider);
|
|
||||||
|
|
||||||
> .button {
|
|
||||||
margin: 8px auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -13,7 +13,6 @@ import I18n from './global/i18n';
|
||||||
import RouterView from './global/router-view.vue';
|
import RouterView from './global/router-view.vue';
|
||||||
import MkLoading from './global/loading.vue';
|
import MkLoading from './global/loading.vue';
|
||||||
import MkError from './global/error.vue';
|
import MkError from './global/error.vue';
|
||||||
import MkAd from './global/ad.vue';
|
|
||||||
import MkPageHeader from './global/page-header.vue';
|
import MkPageHeader from './global/page-header.vue';
|
||||||
import MkSpacer from './global/spacer.vue';
|
import MkSpacer from './global/spacer.vue';
|
||||||
import MkStickyContainer from './global/sticky-container.vue';
|
import MkStickyContainer from './global/sticky-container.vue';
|
||||||
|
@ -32,7 +31,6 @@ export default function(app: App) {
|
||||||
app.component('MkUrl', MkUrl);
|
app.component('MkUrl', MkUrl);
|
||||||
app.component('MkLoading', MkLoading);
|
app.component('MkLoading', MkLoading);
|
||||||
app.component('MkError', MkError);
|
app.component('MkError', MkError);
|
||||||
app.component('MkAd', MkAd);
|
|
||||||
app.component('MkPageHeader', MkPageHeader);
|
app.component('MkPageHeader', MkPageHeader);
|
||||||
app.component('MkSpacer', MkSpacer);
|
app.component('MkSpacer', MkSpacer);
|
||||||
app.component('MkStickyContainer', MkStickyContainer);
|
app.component('MkStickyContainer', MkStickyContainer);
|
||||||
|
@ -53,7 +51,6 @@ declare module '@vue/runtime-core' {
|
||||||
MkUrl: typeof MkUrl;
|
MkUrl: typeof MkUrl;
|
||||||
MkLoading: typeof MkLoading;
|
MkLoading: typeof MkLoading;
|
||||||
MkError: typeof MkError;
|
MkError: typeof MkError;
|
||||||
MkAd: typeof MkAd;
|
|
||||||
MkPageHeader: typeof MkPageHeader;
|
MkPageHeader: typeof MkPageHeader;
|
||||||
MkSpacer: typeof MkSpacer;
|
MkSpacer: typeof MkSpacer;
|
||||||
MkStickyContainer: typeof MkStickyContainer;
|
MkStickyContainer: typeof MkStickyContainer;
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
<template #default="{ items: notes }">
|
<template #default="{ items: notes }">
|
||||||
<div class="giivymft" :class="{ noGap }">
|
<div class="giivymft" :class="{ noGap }">
|
||||||
<XList ref="notes" v-slot="{ item: note }" :items="notes" :direction="pagination.reversed ? 'up' : 'down'" :reversed="pagination.reversed" :no-gap="noGap" :ad="true" class="notes">
|
<XList ref="notes" v-slot="{ item: note }" :items="notes" :direction="pagination.reversed ? 'up' : 'down'" :reversed="pagination.reversed" :no-gap="noGap" class="notes">
|
||||||
<XNote :key="note._featuredId_ || note._prId_ || note.id" class="qtqtichx" :note="note"/>
|
<XNote :key="note._featuredId_ || note._prId_ || note.id" class="qtqtichx" :note="note"/>
|
||||||
</XList>
|
</XList>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -93,14 +93,6 @@ const init = async (): Promise<void> => {
|
||||||
...params,
|
...params,
|
||||||
limit: props.pagination.noPaging ? (props.pagination.limit || 10) : (props.pagination.limit || 10) + 1,
|
limit: props.pagination.noPaging ? (props.pagination.limit || 10) : (props.pagination.limit || 10) + 1,
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
for (let i = 0; i < res.length; i++) {
|
|
||||||
const item = res[i];
|
|
||||||
if (props.pagination.reversed) {
|
|
||||||
if (i === res.length - 2) item._shouldInsertAd_ = true;
|
|
||||||
} else {
|
|
||||||
if (i === 3) item._shouldInsertAd_ = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!props.pagination.noPaging && (res.length > (props.pagination.limit || 10))) {
|
if (!props.pagination.noPaging && (res.length > (props.pagination.limit || 10))) {
|
||||||
res.pop();
|
res.pop();
|
||||||
items.value = props.pagination.reversed ? [...res].reverse() : res;
|
items.value = props.pagination.reversed ? [...res].reverse() : res;
|
||||||
|
@ -137,14 +129,6 @@ const fetchMore = async (): Promise<void> => {
|
||||||
untilId: props.pagination.reversed ? items.value[0].id : items.value[items.value.length - 1].id,
|
untilId: props.pagination.reversed ? items.value[0].id : items.value[items.value.length - 1].id,
|
||||||
}),
|
}),
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
for (let i = 0; i < res.length; i++) {
|
|
||||||
const item = res[i];
|
|
||||||
if (props.pagination.reversed) {
|
|
||||||
if (i === res.length - 9) item._shouldInsertAd_ = true;
|
|
||||||
} else {
|
|
||||||
if (i === 10) item._shouldInsertAd_ = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (res.length > SECOND_FETCH_LIMIT) {
|
if (res.length > SECOND_FETCH_LIMIT) {
|
||||||
res.pop();
|
res.pop();
|
||||||
items.value = props.pagination.reversed ? [...res].reverse().concat(items.value) : items.value.concat(res);
|
items.value = props.pagination.reversed ? [...res].reverse().concat(items.value) : items.value.concat(res);
|
||||||
|
|
|
@ -1,133 +0,0 @@
|
||||||
<template>
|
|
||||||
<MkStickyContainer>
|
|
||||||
<template #header><XHeader :actions="headerActions" :tabs="headerTabs"/></template>
|
|
||||||
<MkSpacer :content-max="900">
|
|
||||||
<div class="uqshojas">
|
|
||||||
<div v-for="ad in ads" class="_panel _formRoot ad">
|
|
||||||
<MkAd v-if="ad.url" :specify="ad"/>
|
|
||||||
<MkInput v-model="ad.url" type="url" class="_formBlock">
|
|
||||||
<template #label>URL</template>
|
|
||||||
</MkInput>
|
|
||||||
<MkInput v-model="ad.imageUrl" class="_formBlock">
|
|
||||||
<template #label>{{ i18n.ts.imageUrl }}</template>
|
|
||||||
</MkInput>
|
|
||||||
<FormRadios v-model="ad.place" class="_formBlock">
|
|
||||||
<template #label>Form</template>
|
|
||||||
<option value="square">square</option>
|
|
||||||
<option value="horizontal">horizontal</option>
|
|
||||||
<option value="horizontal-big">horizontal-big</option>
|
|
||||||
</FormRadios>
|
|
||||||
<!--
|
|
||||||
<div style="margin: 32px 0;">
|
|
||||||
{{ i18n.ts.priority }}
|
|
||||||
<MkRadio v-model="ad.priority" value="high">{{ i18n.ts.high }}</MkRadio>
|
|
||||||
<MkRadio v-model="ad.priority" value="middle">{{ i18n.ts.middle }}</MkRadio>
|
|
||||||
<MkRadio v-model="ad.priority" value="low">{{ i18n.ts.low }}</MkRadio>
|
|
||||||
</div>
|
|
||||||
-->
|
|
||||||
<FormSplit>
|
|
||||||
<MkInput v-model="ad.ratio" type="number">
|
|
||||||
<template #label>{{ i18n.ts.ratio }}</template>
|
|
||||||
</MkInput>
|
|
||||||
<MkInput v-model="ad.expiresAt" type="date">
|
|
||||||
<template #label>{{ i18n.ts.expiration }}</template>
|
|
||||||
</MkInput>
|
|
||||||
</FormSplit>
|
|
||||||
<MkTextarea v-model="ad.memo" class="_formBlock">
|
|
||||||
<template #label>{{ i18n.ts.memo }}</template>
|
|
||||||
</MkTextarea>
|
|
||||||
<div class="buttons _formBlock">
|
|
||||||
<MkButton class="button" inline primary style="margin-right: 12px;" @click="save(ad)"><i class="fas fa-save"></i> {{ i18n.ts.save }}</MkButton>
|
|
||||||
<MkButton class="button" inline danger @click="remove(ad)"><i class="fas fa-trash-alt"></i> {{ i18n.ts.remove }}</MkButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</MkSpacer>
|
|
||||||
</MkStickyContainer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { } from 'vue';
|
|
||||||
import XHeader from './_header_.vue';
|
|
||||||
import MkButton from '@/components/ui/button.vue';
|
|
||||||
import MkInput from '@/components/form/input.vue';
|
|
||||||
import MkTextarea from '@/components/form/textarea.vue';
|
|
||||||
import FormRadios from '@/components/form/radios.vue';
|
|
||||||
import FormSplit from '@/components/form/split.vue';
|
|
||||||
import * as os from '@/os';
|
|
||||||
import { i18n } from '@/i18n';
|
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata';
|
|
||||||
|
|
||||||
let ads: any[] = $ref([]);
|
|
||||||
|
|
||||||
os.api('admin/ad/list').then(adsResponse => {
|
|
||||||
ads = adsResponse;
|
|
||||||
});
|
|
||||||
|
|
||||||
function add() {
|
|
||||||
ads.unshift({
|
|
||||||
id: null,
|
|
||||||
memo: '',
|
|
||||||
place: 'square',
|
|
||||||
priority: 'middle',
|
|
||||||
ratio: 1,
|
|
||||||
url: '',
|
|
||||||
imageUrl: null,
|
|
||||||
expiresAt: null,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function remove(ad) {
|
|
||||||
os.confirm({
|
|
||||||
type: 'warning',
|
|
||||||
text: i18n.t('removeAreYouSure', { x: ad.url }),
|
|
||||||
}).then(({ canceled }) => {
|
|
||||||
if (canceled) return;
|
|
||||||
ads = ads.filter(x => x !== ad);
|
|
||||||
os.apiWithDialog('admin/ad/delete', {
|
|
||||||
id: ad.id,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function save(ad) {
|
|
||||||
if (ad.id == null) {
|
|
||||||
os.apiWithDialog('admin/ad/create', {
|
|
||||||
...ad,
|
|
||||||
expiresAt: new Date(ad.expiresAt).getTime(),
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
os.apiWithDialog('admin/ad/update', {
|
|
||||||
...ad,
|
|
||||||
expiresAt: new Date(ad.expiresAt).getTime(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const headerActions = $computed(() => [{
|
|
||||||
asFullButton: true,
|
|
||||||
icon: 'fas fa-plus',
|
|
||||||
text: i18n.ts.add,
|
|
||||||
handler: add,
|
|
||||||
}]);
|
|
||||||
|
|
||||||
const headerTabs = $computed(() => []);
|
|
||||||
|
|
||||||
definePageMetadata({
|
|
||||||
title: i18n.ts.ads,
|
|
||||||
icon: 'fas fa-audio-description',
|
|
||||||
bg: 'var(--bg)',
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.uqshojas {
|
|
||||||
> .ad {
|
|
||||||
padding: 32px;
|
|
||||||
|
|
||||||
&:not(:last-child) {
|
|
||||||
margin-bottom: var(--margin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -126,11 +126,6 @@ const menuDef = $computed(() => [{
|
||||||
text: i18n.ts.announcements,
|
text: i18n.ts.announcements,
|
||||||
to: '/admin/announcements',
|
to: '/admin/announcements',
|
||||||
active: props.initialPage === 'announcements',
|
active: props.initialPage === 'announcements',
|
||||||
}, {
|
|
||||||
icon: 'fas fa-audio-description',
|
|
||||||
text: i18n.ts.ads,
|
|
||||||
to: '/admin/ads',
|
|
||||||
active: props.initialPage === 'ads',
|
|
||||||
}, {
|
}, {
|
||||||
icon: 'fas fa-exclamation-circle',
|
icon: 'fas fa-exclamation-circle',
|
||||||
text: i18n.ts.abuseReports,
|
text: i18n.ts.abuseReports,
|
||||||
|
@ -205,7 +200,6 @@ const component = $computed(() => {
|
||||||
case 'queue': return defineAsyncComponent(() => import('./queue.vue'));
|
case 'queue': return defineAsyncComponent(() => import('./queue.vue'));
|
||||||
case 'files': return defineAsyncComponent(() => import('./files.vue'));
|
case 'files': return defineAsyncComponent(() => import('./files.vue'));
|
||||||
case 'announcements': return defineAsyncComponent(() => import('./announcements.vue'));
|
case 'announcements': return defineAsyncComponent(() => import('./announcements.vue'));
|
||||||
case 'ads': return defineAsyncComponent(() => import('./ads.vue'));
|
|
||||||
case 'database': return defineAsyncComponent(() => import('./database.vue'));
|
case 'database': return defineAsyncComponent(() => import('./database.vue'));
|
||||||
case 'abuses': return defineAsyncComponent(() => import('./abuses.vue'));
|
case 'abuses': return defineAsyncComponent(() => import('./abuses.vue'));
|
||||||
case 'settings': return defineAsyncComponent(() => import('./settings.vue'));
|
case 'settings': return defineAsyncComponent(() => import('./settings.vue'));
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #default="{ items }">
|
<template #default="{ items }">
|
||||||
<XList v-slot="{ item }" :items="items" :direction="'down'" :no-gap="false" :ad="false">
|
<XList v-slot="{ item }" :items="items" :direction="'down'" :no-gap="false">
|
||||||
<XNote :key="item.id" :note="item.note" :class="$style.note"/>
|
<XNote :key="item.id" :note="item.note" :class="$style.note"/>
|
||||||
</XList>
|
</XList>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -47,7 +47,6 @@
|
||||||
<div><i class="far fa-clock"></i> {{ $ts.createdAt }}: <MkTime :time="page.createdAt" mode="detail"/></div>
|
<div><i class="far fa-clock"></i> {{ $ts.createdAt }}: <MkTime :time="page.createdAt" mode="detail"/></div>
|
||||||
<div v-if="page.createdAt != page.updatedAt"><i class="far fa-clock"></i> {{ $ts.updatedAt }}: <MkTime :time="page.updatedAt" mode="detail"/></div>
|
<div v-if="page.createdAt != page.updatedAt"><i class="far fa-clock"></i> {{ $ts.updatedAt }}: <MkTime :time="page.updatedAt" mode="detail"/></div>
|
||||||
</div>
|
</div>
|
||||||
<MkAd :prefer="['horizontal', 'horizontal-big']"/>
|
|
||||||
<MkContainer :max-height="300" :foldable="true" class="other">
|
<MkContainer :max-height="300" :foldable="true" class="other">
|
||||||
<template #header><i class="fas fa-clock"></i> {{ $ts.recentPosts }}</template>
|
<template #header><i class="fas fa-clock"></i> {{ $ts.recentPosts }}</template>
|
||||||
<MkPagination v-slot="{items}" :pagination="otherPostsPagination">
|
<MkPagination v-slot="{items}" :pagination="otherPostsPagination">
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="ddiqwdnk">
|
<div class="ddiqwdnk">
|
||||||
<XWidgets class="widgets" :edit="editMode" :widgets="$store.reactiveState.widgets.value.filter(w => w.place === place)" @add-widget="addWidget" @remove-widget="removeWidget" @update-widget="updateWidget" @update-widgets="updateWidgets" @exit="editMode = false"/>
|
<XWidgets class="widgets" :edit="editMode" :widgets="$store.reactiveState.widgets.value.filter(w => w.place === place)" @add-widget="addWidget" @remove-widget="removeWidget" @update-widget="updateWidget" @update-widgets="updateWidgets" @exit="editMode = false"/>
|
||||||
<MkAd class="a" :prefer="['square']"/>
|
|
||||||
|
|
||||||
<button v-if="editMode" class="_textButton edit" style="font-size: 0.9em;" @click="editMode = false"><i class="fas fa-check"></i> {{ $ts.editWidgetsExit }}</button>
|
<button v-if="editMode" class="_textButton edit" style="font-size: 0.9em;" @click="editMode = false"><i class="fas fa-check"></i> {{ $ts.editWidgetsExit }}</button>
|
||||||
<button v-else class="_textButton edit" style="font-size: 0.9em;" @click="editMode = true"><i class="fas fa-pencil-alt"></i> {{ $ts.editWidgets }}</button>
|
<button v-else class="_textButton edit" style="font-size: 0.9em;" @click="editMode = true"><i class="fas fa-pencil-alt"></i> {{ $ts.editWidgets }}</button>
|
||||||
|
|
Loading…
Reference in a new issue