442 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Vue
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			442 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Vue
		
	
	
		
			Executable File
		
	
	
| <template>
 | |
| 	<Dialog
 | |
| 		title="Add alert"
 | |
| 		@close="$emit('close')"
 | |
| 	>
 | |
| 		<form
 | |
| 			class="dialog-body"
 | |
| 			@submit.prevent="addAlert"
 | |
| 		>
 | |
| 			<div class="dialog-section">
 | |
| 				<h3 class="dialog-heading">
 | |
| 					When<span class="dialog-description">All to appear in the same scene</span>
 | |
| 				</h3>
 | |
| 
 | |
| 				<div class="alert-section">
 | |
| 					<h4
 | |
| 						v-if="actors.length > 1"
 | |
| 						class="alert-heading"
 | |
| 					>Actors</h4>
 | |
| 
 | |
| 					<h4
 | |
| 						v-else
 | |
| 						class="alert-heading"
 | |
| 					>Actor</h4>
 | |
| 
 | |
| 					<ul class="actors nolist">
 | |
| 						<li
 | |
| 							v-for="actor in actors"
 | |
| 							:key="`actor-${actor.id}`"
 | |
| 							class="actor"
 | |
| 						>
 | |
| 							<ActorPreview :actor="actor" />
 | |
| 
 | |
| 							<Icon
 | |
| 								icon="cross3"
 | |
| 								class="remove"
 | |
| 								@click.native="removeActor(actor)"
 | |
| 							/>
 | |
| 						</li>
 | |
| 
 | |
| 						<Tooltip>
 | |
| 							<li class="actor placeholder"><template v-if="actors.length === 0">Any actor</template>
 | |
| 								<Icon
 | |
| 									icon="plus3"
 | |
| 									class="add"
 | |
| 								/>
 | |
| 							</li>
 | |
| 
 | |
| 							<template #tooltip>
 | |
| 								<Search
 | |
| 									content="actors"
 | |
| 									@select="actor => addActor(actor)"
 | |
| 								/>
 | |
| 							</template>
 | |
| 						</Tooltip>
 | |
| 					</ul>
 | |
| 				</div>
 | |
| 
 | |
| 				<div class="alert-section">
 | |
| 					<h4
 | |
| 						v-if="actors.length > 1"
 | |
| 						class="alert-heading"
 | |
| 					>Do</h4>
 | |
| 
 | |
| 					<h4
 | |
| 						v-else
 | |
| 						class="alert-heading"
 | |
| 					>Does</h4>
 | |
| 
 | |
| 					<ul class="tags nolist">
 | |
| 						<li
 | |
| 							v-for="tag in tags"
 | |
| 							:key="`tag-${tag.id}`"
 | |
| 							class="tag"
 | |
| 						>{{ tag.name }}
 | |
| 							<Icon
 | |
| 								icon="cross3"
 | |
| 								class="remove"
 | |
| 								@click.native="removeTag(tag)"
 | |
| 							/>
 | |
| 						</li>
 | |
| 
 | |
| 						<Tooltip>
 | |
| 							<li class="tag placeholder"><template v-if="tags.length === 0">Any type of scene</template>
 | |
| 								<Icon
 | |
| 									icon="plus3"
 | |
| 									class="add"
 | |
| 								/>
 | |
| 							</li>
 | |
| 
 | |
| 							<template #tooltip>
 | |
| 								<Search
 | |
| 									content="tags"
 | |
| 									:defaults="['anal', 'blowbang', 'mfm', 'dp', 'gangbang', 'airtight']"
 | |
| 									@select="tag => addTag(tag)"
 | |
| 								/>
 | |
| 							</template>
 | |
| 						</Tooltip>
 | |
| 					</ul>
 | |
| 				</div>
 | |
| 
 | |
| 				<div class="alert-section">
 | |
| 					<h4 class="alert-heading">For</h4>
 | |
| 
 | |
| 					<div class="entities">
 | |
| 						<div
 | |
| 							v-if="entity"
 | |
| 							class="entity"
 | |
| 						>
 | |
| 							<Entity :entity="entity" />
 | |
| 
 | |
| 							<Icon
 | |
| 								icon="cross3"
 | |
| 								class="remove"
 | |
| 								@click.native="removeEntity(entity)"
 | |
| 							/>
 | |
| 						</div>
 | |
| 
 | |
| 						<Tooltip v-if="!entity">
 | |
| 							<div class="entity placeholder">
 | |
| 								Any channel
 | |
| 
 | |
| 								<Icon
 | |
| 									icon="plus3"
 | |
| 									class="add"
 | |
| 								/>
 | |
| 							</div>
 | |
| 
 | |
| 							<template #tooltip>
 | |
| 								<Search
 | |
| 									label="Search channels"
 | |
| 									content="entities"
 | |
| 									@select="entity => addEntity(entity)"
 | |
| 								/>
 | |
| 							</template>
 | |
| 						</Tooltip>
 | |
| 					</div>
 | |
| 				</div>
 | |
| 			</div>
 | |
| 
 | |
| 			<div class="dialog-section">
 | |
| 				<h3 class="dialog-heading">Then</h3>
 | |
| 
 | |
| 				<label class="alert-label">
 | |
| 					<Checkbox
 | |
| 						:checked="notify"
 | |
| 						@change="checked => notify = checked"
 | |
| 					/>Notify me in traxxx
 | |
| 				</label>
 | |
| 
 | |
| 				<!--
 | |
| 				<label class="alert-label">
 | |
| 					<Checkbox
 | |
| 						:checked="email"
 | |
| 						@change="checked => email = checked"
 | |
| 					/>Send me an e-mail
 | |
| 				</label>
 | |
| 				-->
 | |
| 
 | |
| 				<div class="stashes-container">
 | |
| 					<ul class="stashes nolist">
 | |
| 						<li
 | |
| 							v-for="stash in stashes"
 | |
| 							:key="`stash-${stash.id}`"
 | |
| 							class="stash"
 | |
| 						>{{ stash.name }}
 | |
| 
 | |
| 							<Icon
 | |
| 								icon="cross3"
 | |
| 								class="remove"
 | |
| 								@click.native="removeStash(stash)"
 | |
| 							/>
 | |
| 						</li>
 | |
| 
 | |
| 						<Tooltip>
 | |
| 							<li class="stash placeholder">
 | |
| 								Add to stash
 | |
| 								<Icon
 | |
| 									icon="plus3"
 | |
| 									class="add"
 | |
| 								/>
 | |
| 							</li>
 | |
| 
 | |
| 							<template #tooltip>
 | |
| 								<Search
 | |
| 									content="stashes"
 | |
| 									@select="stash => addStash(stash)"
 | |
| 								/>
 | |
| 							</template>
 | |
| 						</Tooltip>
 | |
| 					</ul>
 | |
| 				</div>
 | |
| 			</div>
 | |
| 
 | |
| 			<div class="dialog-actions right">
 | |
| 				<button
 | |
| 					:disabled="actors.length === 0 && tags.length === 0 && !entity"
 | |
| 					type="submit"
 | |
| 					class="button button-primary"
 | |
| 				>Add alert</button>
 | |
| 			</div>
 | |
| 		</form>
 | |
| 	</Dialog>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
| import ActorPreview from '../actors/preview.vue';
 | |
| import Entity from '../entities/tile.vue';
 | |
| import Checkbox from '../form/checkbox.vue';
 | |
| import Search from './search.vue';
 | |
| 
 | |
| async function addAlert() {
 | |
| 	await this.$store.dispatch('addAlert', {
 | |
| 		actors: this.actors.map((actor) => actor.id),
 | |
| 		tags: this.tags.map((tag) => tag.id),
 | |
| 		entity: this.entity?.id,
 | |
| 		notify: this.notify,
 | |
| 		email: this.email,
 | |
| 		stashes: this.stashes.map((stash) => stash.id),
 | |
| 	});
 | |
| 
 | |
| 	this.$emit('close', true);
 | |
| }
 | |
| 
 | |
| function addActor(actor) {
 | |
| 	if (!this.actors.some((selectedActor) => selectedActor.id === actor.id)) {
 | |
| 		this.actors = this.actors.concat(actor);
 | |
| 	}
 | |
| 
 | |
| 	this.events.emit('blur');
 | |
| }
 | |
| 
 | |
| function addEntity(entity) {
 | |
| 	this.entity = entity;
 | |
| 	this.events.emit('blur');
 | |
| }
 | |
| 
 | |
| function addTag(tag) {
 | |
| 	if (!this.tags.some((selectedTag) => selectedTag.id === tag.id)) {
 | |
| 		this.tags = this.tags.concat(tag);
 | |
| 	}
 | |
| 
 | |
| 	this.events.emit('blur');
 | |
| }
 | |
| 
 | |
| function removeActor(actor) {
 | |
| 	this.actors = this.actors.filter((listedActor) => listedActor.id !== actor.id);
 | |
| }
 | |
| 
 | |
| function removeEntity() {
 | |
| 	this.entity = null;
 | |
| }
 | |
| 
 | |
| function removeTag(tag) {
 | |
| 	this.tags = this.tags.filter((listedTag) => listedTag.id !== tag.id);
 | |
| }
 | |
| 
 | |
| function addStash(stash) {
 | |
| 	if (!this.stashes.some((selectedStash) => selectedStash.id === stash.id)) {
 | |
| 		this.stashes = this.stashes.concat(stash);
 | |
| 	}
 | |
| 
 | |
| 	this.events.emit('blur');
 | |
| }
 | |
| 
 | |
| function removeStash(stash) {
 | |
| 	this.stashes = this.stashes.filter((listedStash) => listedStash.id !== stash.id);
 | |
| }
 | |
| 
 | |
| export default {
 | |
| 	components: {
 | |
| 		ActorPreview,
 | |
| 		Checkbox,
 | |
| 		Entity,
 | |
| 		Search,
 | |
| 	},
 | |
| 	emits: ['close'],
 | |
| 	data() {
 | |
| 		return {
 | |
| 			actors: [],
 | |
| 			tags: [],
 | |
| 			entity: null,
 | |
| 			notify: true,
 | |
| 			email: false,
 | |
| 			stashes: [],
 | |
| 			availableStashes: this.$store.state.auth.user.stashes,
 | |
| 		};
 | |
| 	},
 | |
| 	methods: {
 | |
| 		addActor,
 | |
| 		addAlert,
 | |
| 		addEntity,
 | |
| 		addTag,
 | |
| 		addStash,
 | |
| 		removeActor,
 | |
| 		removeEntity,
 | |
| 		removeTag,
 | |
| 		removeStash,
 | |
| 	},
 | |
| };
 | |
| </script>
 | |
| 
 | |
| <style lang="scss" scoped>
 | |
| .dialog-section {
 | |
| 	width: 30rem;
 | |
| 	max-width: 100%;
 | |
| 
 | |
| 	&:first-child {
 | |
| 		border-bottom: solid 1px var(--shadow-hint);
 | |
| 		margin: 0 0 1rem 0;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| .dialog-heading {
 | |
| 	display: flex;
 | |
| 	justify-content: space-between;
 | |
| 	align-items: center;
 | |
| 	margin: 0 0 .25rem 0;
 | |
| 	color: var(--primary);
 | |
| }
 | |
| 
 | |
| .dialog-description {
 | |
| 	color: var(--shadow);
 | |
| 	font-size: .9rem;
 | |
| 	font-weight: normal;
 | |
| }
 | |
| 
 | |
| .alert-heading {
 | |
| 	margin: .75rem 0 .25rem 0;
 | |
| }
 | |
| 
 | |
| .actors,
 | |
| .entities,
 | |
| .tags {
 | |
| 	display: flex;
 | |
| 	align-items: center;
 | |
| 	flex-wrap: wrap;
 | |
| 	font-size: 0;
 | |
| }
 | |
| 
 | |
| .actors > .actor,
 | |
| .entity,
 | |
| .tag,
 | |
| .stash {
 | |
| 	position: relative;
 | |
| 	font-size: 1rem;
 | |
| 	margin: 0 .5rem .5rem 0;
 | |
| }
 | |
| 
 | |
| .entity .tile {
 | |
| 	width: 10rem;
 | |
| 	height: 2.5rem;
 | |
| }
 | |
| 
 | |
| .tag:not(.placeholder),
 | |
| .stash:not(.placeholder) {
 | |
| 	padding: .5rem .75rem;
 | |
| 	border: solid 1px var(--shadow-hint);
 | |
| 	margin: 0 .75rem 0 0;
 | |
| 	font-size: .9rem;
 | |
| 	font-weight: bold;
 | |
| }
 | |
| 
 | |
| .stashes {
 | |
| 	margin: 0 0 0 .25rem;
 | |
| 	color: var(--text);
 | |
| }
 | |
| 
 | |
| .remove {
 | |
| 	width: 1rem;
 | |
| 	height: 1rem;
 | |
| 	position: absolute;
 | |
| 	top: -.35rem;
 | |
| 	right: -.35rem;
 | |
| 	z-index: 1;
 | |
| 	border: solid 1px var(--darken-hint);
 | |
| 	border-radius: 50%;
 | |
| 	background: var(--background);
 | |
| 	fill: var(--shadow-weak);
 | |
| 	box-shadow: 0 0 1px var(--shadow);
 | |
| 
 | |
| 	&:hover {
 | |
| 		fill: var(--text-light);
 | |
| 		background: var(--primary);
 | |
| 		border: solid 1px var(--primary);
 | |
| 		cursor: pointer;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| .placeholder {
 | |
| 	display: inline-flex;
 | |
| 	align-items: center;
 | |
| 	color: var(--shadow-strong);
 | |
| 	padding: .75rem 0;
 | |
| 	margin: 0 0 .5rem 0;
 | |
| 	font-size: 1rem;
 | |
| 
 | |
| 	.add {
 | |
| 		fill: var(--shadow);
 | |
| 		margin: 0 0 0 .5rem;
 | |
| 	}
 | |
| 
 | |
| 	&:hover {
 | |
| 		color: var(--primary);
 | |
| 		cursor: pointer;
 | |
| 
 | |
| 		.add {
 | |
| 			fill: var(--primary);
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| .alert-label {
 | |
| 	display: flex;
 | |
| 	align-items: center;
 | |
| 	padding: .5rem 0;
 | |
| 	margin: 0 0 .25rem 0;
 | |
| 	cursor: pointer;
 | |
| }
 | |
| 
 | |
| .stashes-heading {
 | |
| 	display: flex;
 | |
| 	align-items: center;
 | |
| 	margin: 0 0 .5rem 0;
 | |
| 	font-size: 1rem;
 | |
| 
 | |
| 	.alert-label {
 | |
| 		display: inline-block;
 | |
| 		margin: 0;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| .tooltip-container {
 | |
| 	display: inline-block;
 | |
| }
 | |
| 
 | |
| .check-container {
 | |
| 	display: inline-block;
 | |
| 	margin: 0 .5rem 0 0;
 | |
| }
 | |
| </style>
 |