Merge pull request #1713 from syuilo/without-vue-material
Without vue material
This commit is contained in:
		
						commit
						39b1978ff3
					
				
					 23 changed files with 1383 additions and 519 deletions
				
			
		| 
						 | 
					@ -211,7 +211,6 @@
 | 
				
			||||||
		"vue-js-modal": "1.3.13",
 | 
							"vue-js-modal": "1.3.13",
 | 
				
			||||||
		"vue-json-tree-view": "2.1.4",
 | 
							"vue-json-tree-view": "2.1.4",
 | 
				
			||||||
		"vue-loader": "15.2.1",
 | 
							"vue-loader": "15.2.1",
 | 
				
			||||||
		"vue-material": "^1.0.0-beta-10.2",
 | 
					 | 
				
			||||||
		"vue-router": "3.0.1",
 | 
							"vue-router": "3.0.1",
 | 
				
			||||||
		"vue-template-compiler": "2.5.16",
 | 
							"vue-template-compiler": "2.5.16",
 | 
				
			||||||
		"vuedraggable": "2.16.0",
 | 
							"vuedraggable": "2.16.0",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,11 +7,6 @@ html
 | 
				
			||||||
			cursor progress !important
 | 
								cursor progress !important
 | 
				
			||||||
 | 
					
 | 
				
			||||||
body
 | 
					body
 | 
				
			||||||
	// for md
 | 
					 | 
				
			||||||
	font-size 16px !important
 | 
					 | 
				
			||||||
	line-height initial !important
 | 
					 | 
				
			||||||
	letter-spacing initial !important
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	overflow-wrap break-word
 | 
						overflow-wrap break-word
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#error
 | 
					#error
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,6 +29,14 @@ import fileTypeIcon from './file-type-icon.vue';
 | 
				
			||||||
import Switch from './switch.vue';
 | 
					import Switch from './switch.vue';
 | 
				
			||||||
import Othello from './othello.vue';
 | 
					import Othello from './othello.vue';
 | 
				
			||||||
import welcomeTimeline from './welcome-timeline.vue';
 | 
					import welcomeTimeline from './welcome-timeline.vue';
 | 
				
			||||||
 | 
					import uiInput from './ui/input.vue';
 | 
				
			||||||
 | 
					import uiButton from './ui/button.vue';
 | 
				
			||||||
 | 
					import uiCard from './ui/card.vue';
 | 
				
			||||||
 | 
					import uiForm from './ui/form.vue';
 | 
				
			||||||
 | 
					import uiTextarea from './ui/textarea.vue';
 | 
				
			||||||
 | 
					import uiSwitch from './ui/switch.vue';
 | 
				
			||||||
 | 
					import uiRadio from './ui/radio.vue';
 | 
				
			||||||
 | 
					import uiSelect from './ui/select.vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Vue.component('mk-analog-clock', analogClock);
 | 
					Vue.component('mk-analog-clock', analogClock);
 | 
				
			||||||
Vue.component('mk-menu', menu);
 | 
					Vue.component('mk-menu', menu);
 | 
				
			||||||
| 
						 | 
					@ -59,3 +67,11 @@ Vue.component('mk-file-type-icon', fileTypeIcon);
 | 
				
			||||||
Vue.component('mk-switch', Switch);
 | 
					Vue.component('mk-switch', Switch);
 | 
				
			||||||
Vue.component('mk-othello', Othello);
 | 
					Vue.component('mk-othello', Othello);
 | 
				
			||||||
Vue.component('mk-welcome-timeline', welcomeTimeline);
 | 
					Vue.component('mk-welcome-timeline', welcomeTimeline);
 | 
				
			||||||
 | 
					Vue.component('ui-input', uiInput);
 | 
				
			||||||
 | 
					Vue.component('ui-button', uiButton);
 | 
				
			||||||
 | 
					Vue.component('ui-card', uiCard);
 | 
				
			||||||
 | 
					Vue.component('ui-form', uiForm);
 | 
				
			||||||
 | 
					Vue.component('ui-textarea', uiTextarea);
 | 
				
			||||||
 | 
					Vue.component('ui-switch', uiSwitch);
 | 
				
			||||||
 | 
					Vue.component('ui-radio', uiRadio);
 | 
				
			||||||
 | 
					Vue.component('ui-select', uiSelect);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,60 +1,58 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<form class="mk-signup" @submit.prevent="onSubmit" autocomplete="off">
 | 
					<form class="mk-signup" @submit.prevent="onSubmit" :autocomplete="Math.random()">
 | 
				
			||||||
	<label class="username">
 | 
						<ui-input v-model="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" :autocomplete="Math.random()" required @input="onChangeUsername">
 | 
				
			||||||
		<p class="caption">%fa:at%%i18n:@username%</p>
 | 
							<span>%i18n:@username%</span>
 | 
				
			||||||
		<input v-model="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" placeholder="a~z、A~Z、0~9、-" autocomplete="off" required @input="onChangeUsername"/>
 | 
							<span slot="prefix">@</span>
 | 
				
			||||||
		<p class="profile-page-url-preview" v-if="shouldShowProfileUrl">{{ `${url}/@${username}` }}</p>
 | 
							<span slot="suffix">@{{ host }}</span>
 | 
				
			||||||
		<p class="info" v-if="usernameState == 'wait'" style="color:#999">%fa:spinner .pulse .fw%%i18n:@checking%</p>
 | 
							<p slot="text" v-if="usernameState == 'wait'" style="color:#999">%fa:spinner .pulse .fw% %i18n:@checking%</p>
 | 
				
			||||||
		<p class="info" v-if="usernameState == 'ok'" style="color:#3CB7B5">%fa:check .fw%%i18n:@available%</p>
 | 
							<p slot="text" v-if="usernameState == 'ok'" style="color:#3CB7B5">%fa:check .fw% %i18n:@available%</p>
 | 
				
			||||||
		<p class="info" v-if="usernameState == 'unavailable'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:@unavailable%</p>
 | 
							<p slot="text" v-if="usernameState == 'unavailable'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@unavailable%</p>
 | 
				
			||||||
		<p class="info" v-if="usernameState == 'error'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:@error%</p>
 | 
							<p slot="text" v-if="usernameState == 'error'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@error%</p>
 | 
				
			||||||
		<p class="info" v-if="usernameState == 'invalid-format'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:@invalid-format%</p>
 | 
							<p slot="text" v-if="usernameState == 'invalid-format'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@invalid-format%</p>
 | 
				
			||||||
		<p class="info" v-if="usernameState == 'min-range'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:@too-short%</p>
 | 
							<p slot="text" v-if="usernameState == 'min-range'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@too-short%</p>
 | 
				
			||||||
		<p class="info" v-if="usernameState == 'max-range'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:@too-long%</p>
 | 
							<p slot="text" v-if="usernameState == 'max-range'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@too-long%</p>
 | 
				
			||||||
	</label>
 | 
						</ui-input>
 | 
				
			||||||
	<label class="password">
 | 
						<ui-input v-model="password" type="password" :autocomplete="Math.random()" required @input="onChangePassword" :with-password-meter="true">
 | 
				
			||||||
		<p class="caption">%fa:lock%%i18n:@password%</p>
 | 
							<span>%i18n:@password%</span>
 | 
				
			||||||
		<input v-model="password" type="password" placeholder="%i18n:@password-placeholder%" autocomplete="off" required @input="onChangePassword"/>
 | 
							<span slot="prefix">%fa:lock%</span>
 | 
				
			||||||
		<div class="meter" v-show="passwordStrength != ''" :data-strength="passwordStrength">
 | 
							<div slot="text">
 | 
				
			||||||
			<div class="value" ref="passwordMetar"></div>
 | 
								<p slot="text" v-if="passwordStrength == 'low'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@weak-password%</p>
 | 
				
			||||||
 | 
								<p slot="text" v-if="passwordStrength == 'medium'" style="color:#3CB7B5">%fa:check .fw% %i18n:@normal-password%</p>
 | 
				
			||||||
 | 
								<p slot="text" v-if="passwordStrength == 'high'" style="color:#3CB7B5">%fa:check .fw% %i18n:@strong-password%</p>
 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
		<p class="info" v-if="passwordStrength == 'low'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:@weak-password%</p>
 | 
						</ui-input>
 | 
				
			||||||
		<p class="info" v-if="passwordStrength == 'medium'" style="color:#3CB7B5">%fa:check .fw%%i18n:@normal-password%</p>
 | 
						<ui-input v-model="retypedPassword" type="password" :autocomplete="Math.random()" required @input="onChangePasswordRetype">
 | 
				
			||||||
		<p class="info" v-if="passwordStrength == 'high'" style="color:#3CB7B5">%fa:check .fw%%i18n:@strong-password%</p>
 | 
							<span>%i18n:@password% (%i18n:@retype%)</span>
 | 
				
			||||||
	</label>
 | 
							<span slot="prefix">%fa:lock%</span>
 | 
				
			||||||
	<label class="retype-password">
 | 
							<div slot="text">
 | 
				
			||||||
		<p class="caption">%fa:lock%%i18n:@password%(%i18n:@retype%)</p>
 | 
								<p slot="text" v-if="passwordRetypeState == 'match'" style="color:#3CB7B5">%fa:check .fw% %i18n:@password-matched%</p>
 | 
				
			||||||
		<input v-model="retypedPassword" type="password" placeholder="%i18n:@retype-placeholder%" autocomplete="off" required @input="onChangePasswordRetype"/>
 | 
								<p slot="text" v-if="passwordRetypeState == 'not-match'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@password-not-matched%</p>
 | 
				
			||||||
		<p class="info" v-if="passwordRetypeState == 'match'" style="color:#3CB7B5">%fa:check .fw%%i18n:@password-matched%</p>
 | 
							</div>
 | 
				
			||||||
		<p class="info" v-if="passwordRetypeState == 'not-match'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:@password-not-matched%</p>
 | 
						</ui-input>
 | 
				
			||||||
	</label>
 | 
						<div class="g-recaptcha" :data-sitekey="recaptchaSitekey" style="margin: 16px 0;"></div>
 | 
				
			||||||
	<label class="recaptcha">
 | 
						<label class="agree-tou" style="display: block; margin: 16px 0;">
 | 
				
			||||||
		<p class="caption"><template v-if="recaptchaed">%fa:toggle-on%</template><template v-if="!recaptchaed">%fa:toggle-off%</template>%i18n:@recaptcha%</p>
 | 
							<input name="agree-tou" type="checkbox" required/>
 | 
				
			||||||
		<div class="g-recaptcha" data-callback="onRecaptchaed" data-expired-callback="onRecaptchaExpired" :data-sitekey="recaptchaSitekey"></div>
 | 
					 | 
				
			||||||
	</label>
 | 
					 | 
				
			||||||
	<label class="agree-tou">
 | 
					 | 
				
			||||||
		<input name="agree-tou" type="checkbox" autocomplete="off" required/>
 | 
					 | 
				
			||||||
		<p><a :href="touUrl" target="_blank">利用規約</a>に同意する</p>
 | 
							<p><a :href="touUrl" target="_blank">利用規約</a>に同意する</p>
 | 
				
			||||||
	</label>
 | 
						</label>
 | 
				
			||||||
	<button type="submit">%i18n:@create%</button>
 | 
						<ui-button type="submit">%i18n:@create%</ui-button>
 | 
				
			||||||
</form>
 | 
					</form>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
import Vue from 'vue';
 | 
					import Vue from 'vue';
 | 
				
			||||||
const getPasswordStrength = require('syuilo-password-strength');
 | 
					const getPasswordStrength = require('syuilo-password-strength');
 | 
				
			||||||
import { url, docsUrl, lang, recaptchaSitekey } from '../../../config';
 | 
					import { host, url, docsUrl, lang, recaptchaSitekey } from '../../../config';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default Vue.extend({
 | 
					export default Vue.extend({
 | 
				
			||||||
	data() {
 | 
						data() {
 | 
				
			||||||
		return {
 | 
							return {
 | 
				
			||||||
 | 
								host,
 | 
				
			||||||
			username: '',
 | 
								username: '',
 | 
				
			||||||
			password: '',
 | 
								password: '',
 | 
				
			||||||
			retypedPassword: '',
 | 
								retypedPassword: '',
 | 
				
			||||||
			url,
 | 
								url,
 | 
				
			||||||
			touUrl: `${docsUrl}/${lang}/tou`,
 | 
								touUrl: `${docsUrl}/${lang}/tou`,
 | 
				
			||||||
			recaptchaSitekey,
 | 
								recaptchaSitekey,
 | 
				
			||||||
			recaptchaed: false,
 | 
					 | 
				
			||||||
			usernameState: null,
 | 
								usernameState: null,
 | 
				
			||||||
			passwordStrength: '',
 | 
								passwordStrength: '',
 | 
				
			||||||
			passwordRetypeState: null
 | 
								passwordRetypeState: null
 | 
				
			||||||
| 
						 | 
					@ -104,7 +102,6 @@ export default Vue.extend({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			const strength = getPasswordStrength(this.password);
 | 
								const strength = getPasswordStrength(this.password);
 | 
				
			||||||
			this.passwordStrength = strength > 0.7 ? 'high' : strength > 0.3 ? 'medium' : 'low';
 | 
								this.passwordStrength = strength > 0.7 ? 'high' : strength > 0.3 ? 'medium' : 'low';
 | 
				
			||||||
			(this.$refs.passwordMetar as any).style.width = `${strength * 100}%`;
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		onChangePasswordRetype() {
 | 
							onChangePasswordRetype() {
 | 
				
			||||||
			if (this.retypedPassword == '') {
 | 
								if (this.retypedPassword == '') {
 | 
				
			||||||
| 
						 | 
					@ -130,19 +127,9 @@ export default Vue.extend({
 | 
				
			||||||
				alert('%i18n:@some-error%');
 | 
									alert('%i18n:@some-error%');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				(window as any).grecaptcha.reset();
 | 
									(window as any).grecaptcha.reset();
 | 
				
			||||||
				this.recaptchaed = false;
 | 
					 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	created() {
 | 
					 | 
				
			||||||
		(window as any).onRecaptchaed = () => {
 | 
					 | 
				
			||||||
			this.recaptchaed = true;
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		(window as any).onRecaptchaExpired = () => {
 | 
					 | 
				
			||||||
			this.recaptchaed = false;
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	mounted() {
 | 
						mounted() {
 | 
				
			||||||
		const head = document.getElementsByTagName('head')[0];
 | 
							const head = document.getElementsByTagName('head')[0];
 | 
				
			||||||
		const script = document.createElement('script');
 | 
							const script = document.createElement('script');
 | 
				
			||||||
| 
						 | 
					@ -158,100 +145,6 @@ export default Vue.extend({
 | 
				
			||||||
.mk-signup
 | 
					.mk-signup
 | 
				
			||||||
	min-width 302px
 | 
						min-width 302px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	label
 | 
					 | 
				
			||||||
		display block
 | 
					 | 
				
			||||||
		margin 0 0 16px 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		> .caption
 | 
					 | 
				
			||||||
			margin 0 0 4px 0
 | 
					 | 
				
			||||||
			color #828888
 | 
					 | 
				
			||||||
			font-size 0.95em
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			> [data-fa]
 | 
					 | 
				
			||||||
				margin-right 0.25em
 | 
					 | 
				
			||||||
				color #96adac
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		> .info
 | 
					 | 
				
			||||||
			display block
 | 
					 | 
				
			||||||
			margin 4px 0
 | 
					 | 
				
			||||||
			font-size 0.8em
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			> [data-fa]
 | 
					 | 
				
			||||||
				margin-right 0.3em
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		&.username
 | 
					 | 
				
			||||||
			.profile-page-url-preview
 | 
					 | 
				
			||||||
				display block
 | 
					 | 
				
			||||||
				margin 4px 8px 0 4px
 | 
					 | 
				
			||||||
				font-size 0.8em
 | 
					 | 
				
			||||||
				color #888
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				&:empty
 | 
					 | 
				
			||||||
					display none
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				&:not(:empty) + .info
 | 
					 | 
				
			||||||
					margin-top 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		&.password
 | 
					 | 
				
			||||||
			.meter
 | 
					 | 
				
			||||||
				display block
 | 
					 | 
				
			||||||
				margin-top 8px
 | 
					 | 
				
			||||||
				width 100%
 | 
					 | 
				
			||||||
				height 8px
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				&[data-strength='']
 | 
					 | 
				
			||||||
					display none
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				&[data-strength='low']
 | 
					 | 
				
			||||||
					> .value
 | 
					 | 
				
			||||||
						background #d73612
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				&[data-strength='medium']
 | 
					 | 
				
			||||||
					> .value
 | 
					 | 
				
			||||||
						background #d7ca12
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				&[data-strength='high']
 | 
					 | 
				
			||||||
					> .value
 | 
					 | 
				
			||||||
						background #61bb22
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				> .value
 | 
					 | 
				
			||||||
					display block
 | 
					 | 
				
			||||||
					width 0%
 | 
					 | 
				
			||||||
					height 100%
 | 
					 | 
				
			||||||
					background transparent
 | 
					 | 
				
			||||||
					border-radius 4px
 | 
					 | 
				
			||||||
					transition all 0.1s ease
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	[type=text], [type=password]
 | 
					 | 
				
			||||||
		user-select text
 | 
					 | 
				
			||||||
		display inline-block
 | 
					 | 
				
			||||||
		cursor auto
 | 
					 | 
				
			||||||
		padding 0 12px
 | 
					 | 
				
			||||||
		margin 0
 | 
					 | 
				
			||||||
		width 100%
 | 
					 | 
				
			||||||
		line-height 44px
 | 
					 | 
				
			||||||
		font-size 1em
 | 
					 | 
				
			||||||
		color #333 !important
 | 
					 | 
				
			||||||
		background #fff !important
 | 
					 | 
				
			||||||
		outline none
 | 
					 | 
				
			||||||
		border solid 1px rgba(#000, 0.1)
 | 
					 | 
				
			||||||
		border-radius 4px
 | 
					 | 
				
			||||||
		box-shadow 0 0 0 114514px #fff inset
 | 
					 | 
				
			||||||
		transition all .3s ease
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		&:hover
 | 
					 | 
				
			||||||
			border-color rgba(#000, 0.2)
 | 
					 | 
				
			||||||
			transition all .1s ease
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		&:focus
 | 
					 | 
				
			||||||
			color $theme-color !important
 | 
					 | 
				
			||||||
			border-color $theme-color
 | 
					 | 
				
			||||||
			box-shadow 0 0 0 1024px #fff inset, 0 0 0 4px rgba($theme-color, 10%)
 | 
					 | 
				
			||||||
			transition all 0s ease
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		&:disabled
 | 
					 | 
				
			||||||
			opacity 0.5
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	.agree-tou
 | 
						.agree-tou
 | 
				
			||||||
		padding 4px
 | 
							padding 4px
 | 
				
			||||||
		border-radius 4px
 | 
							border-radius 4px
 | 
				
			||||||
| 
						 | 
					@ -269,19 +162,4 @@ export default Vue.extend({
 | 
				
			||||||
			display inline
 | 
								display inline
 | 
				
			||||||
			color #555
 | 
								color #555
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	button
 | 
					 | 
				
			||||||
		margin 0
 | 
					 | 
				
			||||||
		padding 16px
 | 
					 | 
				
			||||||
		width 100%
 | 
					 | 
				
			||||||
		font-size 1em
 | 
					 | 
				
			||||||
		color #fff
 | 
					 | 
				
			||||||
		background $theme-color
 | 
					 | 
				
			||||||
		border-radius 3px
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		&:hover
 | 
					 | 
				
			||||||
			background lighten($theme-color, 5%)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		&:active
 | 
					 | 
				
			||||||
			background darken($theme-color, 5%)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										82
									
								
								src/client/app/common/views/components/ui/button.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								src/client/app/common/views/components/ui/button.vue
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,82 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					<div class="ui-button" :class="[styl]">
 | 
				
			||||||
 | 
						<button :type="type" @click="$emit('click')">
 | 
				
			||||||
 | 
							<slot></slot>
 | 
				
			||||||
 | 
						</button>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
					import Vue from 'vue';
 | 
				
			||||||
 | 
					export default Vue.extend({
 | 
				
			||||||
 | 
						props: {
 | 
				
			||||||
 | 
							type: {
 | 
				
			||||||
 | 
								type: String,
 | 
				
			||||||
 | 
								required: false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						data() {
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								styl: 'fill'
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						inject: {
 | 
				
			||||||
 | 
							isCardChild: { default: false }
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						created() {
 | 
				
			||||||
 | 
							if (this.isCardChild) {
 | 
				
			||||||
 | 
								this.styl = 'line';
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="stylus" scoped>
 | 
				
			||||||
 | 
					@import '~const.styl'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					root(isDark, fill)
 | 
				
			||||||
 | 
						> button
 | 
				
			||||||
 | 
							display block
 | 
				
			||||||
 | 
							width 100%
 | 
				
			||||||
 | 
							margin 0
 | 
				
			||||||
 | 
							padding 0
 | 
				
			||||||
 | 
							font-weight bold
 | 
				
			||||||
 | 
							font-size 16px
 | 
				
			||||||
 | 
							line-height 44px
 | 
				
			||||||
 | 
							border none
 | 
				
			||||||
 | 
							border-radius 6px
 | 
				
			||||||
 | 
							outline none
 | 
				
			||||||
 | 
							box-shadow none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if fill
 | 
				
			||||||
 | 
								color $theme-color-foreground
 | 
				
			||||||
 | 
								background $theme-color
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&:hover
 | 
				
			||||||
 | 
									background lighten($theme-color, 5%)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&:active
 | 
				
			||||||
 | 
									background darken($theme-color, 5%)
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								color $theme-color
 | 
				
			||||||
 | 
								background none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&:hover
 | 
				
			||||||
 | 
									color darken($theme-color, 5%)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&:active
 | 
				
			||||||
 | 
									background rgba($theme-color, 0.3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.ui-button[data-darkmode]
 | 
				
			||||||
 | 
						&.fill
 | 
				
			||||||
 | 
							root(true, true)
 | 
				
			||||||
 | 
						&:not(.fill)
 | 
				
			||||||
 | 
							root(true, false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.ui-button:not([data-darkmode])
 | 
				
			||||||
 | 
						&.fill
 | 
				
			||||||
 | 
							root(false, true)
 | 
				
			||||||
 | 
						&:not(.fill)
 | 
				
			||||||
 | 
							root(false, false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										46
									
								
								src/client/app/common/views/components/ui/card.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/client/app/common/views/components/ui/card.vue
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,46 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					<div class="ui-card">
 | 
				
			||||||
 | 
						<header>
 | 
				
			||||||
 | 
							<slot name="title"></slot>
 | 
				
			||||||
 | 
						</header>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<slot></slot>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
					import Vue from 'vue';
 | 
				
			||||||
 | 
					export default Vue.extend({
 | 
				
			||||||
 | 
						provide() {
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								isCardChild: true
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="stylus" scoped>
 | 
				
			||||||
 | 
					@import '~const.styl'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					root(isDark)
 | 
				
			||||||
 | 
						margin 16px
 | 
				
			||||||
 | 
						padding 16px
 | 
				
			||||||
 | 
						color isDark ? #fff : #000
 | 
				
			||||||
 | 
						background isDark ? #282C37 : #fff
 | 
				
			||||||
 | 
						box-shadow 0 3px 1px -2px rgba(#000, 0.2), 0 2px 2px 0 rgba(#000, 0.14), 0 1px 5px 0 rgba(#000, 0.12)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@media (min-width 500px)
 | 
				
			||||||
 | 
							padding 32px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> header
 | 
				
			||||||
 | 
							font-weight normal
 | 
				
			||||||
 | 
							font-size 24px
 | 
				
			||||||
 | 
							color isDark ? #fff : #444
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.ui-card[data-darkmode]
 | 
				
			||||||
 | 
						root(true)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.ui-card:not([data-darkmode])
 | 
				
			||||||
 | 
						root(false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										30
									
								
								src/client/app/common/views/components/ui/form.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/client/app/common/views/components/ui/form.vue
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,30 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					<div class="ui-form">
 | 
				
			||||||
 | 
						<fieldset :disabled="disabled">
 | 
				
			||||||
 | 
							<slot></slot>
 | 
				
			||||||
 | 
						</fieldset>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
					import Vue from 'vue';
 | 
				
			||||||
 | 
					export default Vue.extend({
 | 
				
			||||||
 | 
						props: {
 | 
				
			||||||
 | 
							disabled: {
 | 
				
			||||||
 | 
								type: Boolean,
 | 
				
			||||||
 | 
								required: false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="stylus" scoped>
 | 
				
			||||||
 | 
					@import '~const.styl'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.ui-form
 | 
				
			||||||
 | 
						> fieldset
 | 
				
			||||||
 | 
							margin 0
 | 
				
			||||||
 | 
							padding 0
 | 
				
			||||||
 | 
							border none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										321
									
								
								src/client/app/common/views/components/ui/input.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										321
									
								
								src/client/app/common/views/components/ui/input.vue
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,321 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					<div class="ui-input" :class="[{ focused, filled }, styl]">
 | 
				
			||||||
 | 
						<div class="icon" ref="icon"><slot name="icon"></slot></div>
 | 
				
			||||||
 | 
						<div class="input" @click="focus" @mousedown="focus">
 | 
				
			||||||
 | 
							<div class="password-meter" v-if="withPasswordMeter" v-show="passwordStrength != ''" :data-strength="passwordStrength">
 | 
				
			||||||
 | 
								<div class="value" ref="passwordMetar"></div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<span class="label" ref="label"><slot></slot></span>
 | 
				
			||||||
 | 
							<div class="prefix" ref="prefix"><slot name="prefix"></slot></div>
 | 
				
			||||||
 | 
							<template v-if="type != 'file'">
 | 
				
			||||||
 | 
								<input ref="input"
 | 
				
			||||||
 | 
										:type="type"
 | 
				
			||||||
 | 
										:value="v"
 | 
				
			||||||
 | 
										:required="required"
 | 
				
			||||||
 | 
										:readonly="readonly"
 | 
				
			||||||
 | 
										:pattern="pattern"
 | 
				
			||||||
 | 
										:autocomplete="autocomplete"
 | 
				
			||||||
 | 
										@input="$emit('input', $event.target.value)"
 | 
				
			||||||
 | 
										@focus="focused = true"
 | 
				
			||||||
 | 
										@blur="focused = false">
 | 
				
			||||||
 | 
							</template>
 | 
				
			||||||
 | 
							<template v-else>
 | 
				
			||||||
 | 
								<input ref="input"
 | 
				
			||||||
 | 
										type="text"
 | 
				
			||||||
 | 
										:value="placeholder"
 | 
				
			||||||
 | 
										readonly
 | 
				
			||||||
 | 
										@click="chooseFile">
 | 
				
			||||||
 | 
								<input ref="file"
 | 
				
			||||||
 | 
										type="file"
 | 
				
			||||||
 | 
										:value="value"
 | 
				
			||||||
 | 
										@change="onChangeFile">
 | 
				
			||||||
 | 
							</template>
 | 
				
			||||||
 | 
							<div class="suffix"><slot name="suffix"></slot></div>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
						<div class="text"><slot name="text"></slot></div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
					import Vue from 'vue';
 | 
				
			||||||
 | 
					const getPasswordStrength = require('syuilo-password-strength');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Vue.extend({
 | 
				
			||||||
 | 
						props: {
 | 
				
			||||||
 | 
							value: {
 | 
				
			||||||
 | 
								required: false
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							type: {
 | 
				
			||||||
 | 
								type: String,
 | 
				
			||||||
 | 
								required: false
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							required: {
 | 
				
			||||||
 | 
								type: Boolean,
 | 
				
			||||||
 | 
								required: false
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							readonly: {
 | 
				
			||||||
 | 
								type: Boolean,
 | 
				
			||||||
 | 
								required: false
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							pattern: {
 | 
				
			||||||
 | 
								type: String,
 | 
				
			||||||
 | 
								required: false
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							autocomplete: {
 | 
				
			||||||
 | 
								required: false
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							withPasswordMeter: {
 | 
				
			||||||
 | 
								type: Boolean,
 | 
				
			||||||
 | 
								required: false,
 | 
				
			||||||
 | 
								default: false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						data() {
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								v: this.value,
 | 
				
			||||||
 | 
								focused: false,
 | 
				
			||||||
 | 
								passwordStrength: '',
 | 
				
			||||||
 | 
								styl: 'fill'
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						computed: {
 | 
				
			||||||
 | 
							filled(): boolean {
 | 
				
			||||||
 | 
								return this.v != '' && this.v != null;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							placeholder(): string {
 | 
				
			||||||
 | 
								if (this.type != 'file') return null;
 | 
				
			||||||
 | 
								if (this.v == null) return null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (typeof this.v == 'string') return this.v;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (Array.isArray(this.v)) {
 | 
				
			||||||
 | 
									return this.v.map(file => file.name).join(', ');
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									return this.v.name;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						watch: {
 | 
				
			||||||
 | 
							value(v) {
 | 
				
			||||||
 | 
								this.v = v;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							v(v) {
 | 
				
			||||||
 | 
								if (this.withPasswordMeter) {
 | 
				
			||||||
 | 
									if (v == '') {
 | 
				
			||||||
 | 
										this.passwordStrength = '';
 | 
				
			||||||
 | 
										return;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									const strength = getPasswordStrength(v);
 | 
				
			||||||
 | 
									this.passwordStrength = strength > 0.7 ? 'high' : strength > 0.3 ? 'medium' : 'low';
 | 
				
			||||||
 | 
									(this.$refs.passwordMetar as any).style.width = `${strength * 100}%`;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						inject: {
 | 
				
			||||||
 | 
							isCardChild: { default: false }
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						created() {
 | 
				
			||||||
 | 
							if (this.isCardChild) {
 | 
				
			||||||
 | 
								this.styl = 'line';
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						mounted() {
 | 
				
			||||||
 | 
							if (this.$refs.prefix) {
 | 
				
			||||||
 | 
								this.$refs.label.style.left = (this.$refs.prefix.offsetLeft + this.$refs.prefix.offsetWidth) + 'px';
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						methods: {
 | 
				
			||||||
 | 
							focus() {
 | 
				
			||||||
 | 
								this.$refs.input.focus();
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							chooseFile() {
 | 
				
			||||||
 | 
								this.$refs.file.click();
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							onChangeFile() {
 | 
				
			||||||
 | 
								this.v = Array.from((this.$refs.file as any).files);
 | 
				
			||||||
 | 
								this.$emit('input', this.v);
 | 
				
			||||||
 | 
								this.$emit('change', this.v);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="stylus" scoped>
 | 
				
			||||||
 | 
					@import '~const.styl'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					root(isDark, fill)
 | 
				
			||||||
 | 
						margin 32px 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> .icon
 | 
				
			||||||
 | 
							position absolute
 | 
				
			||||||
 | 
							top 0
 | 
				
			||||||
 | 
							left 0
 | 
				
			||||||
 | 
							width 24px
 | 
				
			||||||
 | 
							text-align center
 | 
				
			||||||
 | 
							line-height 32px
 | 
				
			||||||
 | 
							color isDark ? rgba(#fff, 0.7) : rgba(#000, 0.54)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&:not(:empty) + .input
 | 
				
			||||||
 | 
								margin-left 28px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> .input
 | 
				
			||||||
 | 
							display flex
 | 
				
			||||||
 | 
							cursor text
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if fill
 | 
				
			||||||
 | 
								padding 6px 12px
 | 
				
			||||||
 | 
								background rgba(#000, 0.035)
 | 
				
			||||||
 | 
								border-radius 6px
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								&:before
 | 
				
			||||||
 | 
									content ''
 | 
				
			||||||
 | 
									display block
 | 
				
			||||||
 | 
									position absolute
 | 
				
			||||||
 | 
									bottom 0
 | 
				
			||||||
 | 
									left 0
 | 
				
			||||||
 | 
									right 0
 | 
				
			||||||
 | 
									height 1px
 | 
				
			||||||
 | 
									background isDark ? rgba(#fff, 0.7) : rgba(#000, 0.42)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&:after
 | 
				
			||||||
 | 
									content ''
 | 
				
			||||||
 | 
									display block
 | 
				
			||||||
 | 
									position absolute
 | 
				
			||||||
 | 
									bottom 0
 | 
				
			||||||
 | 
									left 0
 | 
				
			||||||
 | 
									right 0
 | 
				
			||||||
 | 
									height 2px
 | 
				
			||||||
 | 
									background $theme-color
 | 
				
			||||||
 | 
									opacity 0
 | 
				
			||||||
 | 
									transform scaleX(0.12)
 | 
				
			||||||
 | 
									transition border 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1), transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)
 | 
				
			||||||
 | 
									will-change border opacity transform
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> .password-meter
 | 
				
			||||||
 | 
								position absolute
 | 
				
			||||||
 | 
								top 0
 | 
				
			||||||
 | 
								left 0
 | 
				
			||||||
 | 
								width 100%
 | 
				
			||||||
 | 
								height 100%
 | 
				
			||||||
 | 
								border-radius 6px
 | 
				
			||||||
 | 
								overflow hidden
 | 
				
			||||||
 | 
								opacity 0.3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&[data-strength='']
 | 
				
			||||||
 | 
									display none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&[data-strength='low']
 | 
				
			||||||
 | 
									> .value
 | 
				
			||||||
 | 
										background #d73612
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&[data-strength='medium']
 | 
				
			||||||
 | 
									> .value
 | 
				
			||||||
 | 
										background #d7ca12
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&[data-strength='high']
 | 
				
			||||||
 | 
									> .value
 | 
				
			||||||
 | 
										background #61bb22
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> .value
 | 
				
			||||||
 | 
									display block
 | 
				
			||||||
 | 
									width 0%
 | 
				
			||||||
 | 
									height 100%
 | 
				
			||||||
 | 
									background transparent
 | 
				
			||||||
 | 
									border-radius 6px
 | 
				
			||||||
 | 
									transition all 0.1s ease
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> .label
 | 
				
			||||||
 | 
								position absolute
 | 
				
			||||||
 | 
								top fill ? 6px : 0
 | 
				
			||||||
 | 
								left 0
 | 
				
			||||||
 | 
								pointer-events none
 | 
				
			||||||
 | 
								transition 0.4s cubic-bezier(0.25, 0.8, 0.25, 1)
 | 
				
			||||||
 | 
								transition-duration 0.3s
 | 
				
			||||||
 | 
								font-size 16px
 | 
				
			||||||
 | 
								line-height 32px
 | 
				
			||||||
 | 
								color isDark ? rgba(#fff, 0.7) : rgba(#000, 0.54)
 | 
				
			||||||
 | 
								pointer-events none
 | 
				
			||||||
 | 
								//will-change transform
 | 
				
			||||||
 | 
								transform-origin top left
 | 
				
			||||||
 | 
								transform scale(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> input
 | 
				
			||||||
 | 
								display block
 | 
				
			||||||
 | 
								flex 1
 | 
				
			||||||
 | 
								width 100%
 | 
				
			||||||
 | 
								padding 0
 | 
				
			||||||
 | 
								font inherit
 | 
				
			||||||
 | 
								font-weight fill ? bold : normal
 | 
				
			||||||
 | 
								font-size 16px
 | 
				
			||||||
 | 
								line-height 32px
 | 
				
			||||||
 | 
								color isDark ? #fff : #000
 | 
				
			||||||
 | 
								background transparent
 | 
				
			||||||
 | 
								border none
 | 
				
			||||||
 | 
								border-radius 0
 | 
				
			||||||
 | 
								outline none
 | 
				
			||||||
 | 
								box-shadow none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&[type='file']
 | 
				
			||||||
 | 
									display none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> .prefix
 | 
				
			||||||
 | 
							> .suffix
 | 
				
			||||||
 | 
								display block
 | 
				
			||||||
 | 
								align-self center
 | 
				
			||||||
 | 
								justify-self center
 | 
				
			||||||
 | 
								font-size 16px
 | 
				
			||||||
 | 
								line-height 32px
 | 
				
			||||||
 | 
								color isDark ? rgba(#fff, 0.7) : rgba(#000, 0.54)
 | 
				
			||||||
 | 
								pointer-events none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> *
 | 
				
			||||||
 | 
									display block
 | 
				
			||||||
 | 
									min-width 16px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> .prefix
 | 
				
			||||||
 | 
								padding-right 4px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> .suffix
 | 
				
			||||||
 | 
								padding-left 4px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> .text
 | 
				
			||||||
 | 
							margin 6px 0
 | 
				
			||||||
 | 
							font-size 13px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							*
 | 
				
			||||||
 | 
								margin 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&.focused
 | 
				
			||||||
 | 
							> .input
 | 
				
			||||||
 | 
								if fill
 | 
				
			||||||
 | 
									background rgba(#000, 0.05)
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									&:after
 | 
				
			||||||
 | 
										opacity 1
 | 
				
			||||||
 | 
										transform scaleX(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> .label
 | 
				
			||||||
 | 
									color $theme-color
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&.focused
 | 
				
			||||||
 | 
						&.filled
 | 
				
			||||||
 | 
							> .input
 | 
				
			||||||
 | 
								> .label
 | 
				
			||||||
 | 
									top fill ? -24px : -17px
 | 
				
			||||||
 | 
									left 0 !important
 | 
				
			||||||
 | 
									transform scale(0.75)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.ui-input[data-darkmode]
 | 
				
			||||||
 | 
						&.fill
 | 
				
			||||||
 | 
							root(true, true)
 | 
				
			||||||
 | 
						&:not(.fill)
 | 
				
			||||||
 | 
							root(true, false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.ui-input:not([data-darkmode])
 | 
				
			||||||
 | 
						&.fill
 | 
				
			||||||
 | 
							root(false, true)
 | 
				
			||||||
 | 
						&:not(.fill)
 | 
				
			||||||
 | 
							root(false, false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										120
									
								
								src/client/app/common/views/components/ui/radio.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								src/client/app/common/views/components/ui/radio.vue
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,120 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					<div
 | 
				
			||||||
 | 
						class="ui-radio"
 | 
				
			||||||
 | 
						:class="{ disabled, checked }"
 | 
				
			||||||
 | 
						:aria-checked="checked"
 | 
				
			||||||
 | 
						:aria-disabled="disabled"
 | 
				
			||||||
 | 
						@click="toggle"
 | 
				
			||||||
 | 
					>
 | 
				
			||||||
 | 
						<input type="radio"
 | 
				
			||||||
 | 
							:disabled="disabled"
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
						<span class="button">
 | 
				
			||||||
 | 
							<span></span>
 | 
				
			||||||
 | 
						</span>
 | 
				
			||||||
 | 
						<span class="label"><slot></slot></span>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
					import Vue from 'vue';
 | 
				
			||||||
 | 
					export default Vue.extend({
 | 
				
			||||||
 | 
						model: {
 | 
				
			||||||
 | 
							prop: 'model',
 | 
				
			||||||
 | 
							event: 'change'
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						props: {
 | 
				
			||||||
 | 
							model: {
 | 
				
			||||||
 | 
								type: String,
 | 
				
			||||||
 | 
								required: false
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							value: {
 | 
				
			||||||
 | 
								type: String,
 | 
				
			||||||
 | 
								required: false
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							disabled: {
 | 
				
			||||||
 | 
								type: Boolean,
 | 
				
			||||||
 | 
								default: false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						computed: {
 | 
				
			||||||
 | 
							checked(): boolean {
 | 
				
			||||||
 | 
								return this.model === this.value;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						methods: {
 | 
				
			||||||
 | 
							toggle() {
 | 
				
			||||||
 | 
								this.$emit('change', this.value);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="stylus" scoped>
 | 
				
			||||||
 | 
					@import '~const.styl'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					root(isDark)
 | 
				
			||||||
 | 
						display inline-block
 | 
				
			||||||
 | 
						margin 32px 32px 32px 0
 | 
				
			||||||
 | 
						cursor pointer
 | 
				
			||||||
 | 
						transition all 0.3s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> *
 | 
				
			||||||
 | 
							user-select none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&.disabled
 | 
				
			||||||
 | 
							opacity 0.6
 | 
				
			||||||
 | 
							cursor not-allowed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&.checked
 | 
				
			||||||
 | 
							> .button
 | 
				
			||||||
 | 
								border-color $theme-color
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&:after
 | 
				
			||||||
 | 
									background-color $theme-color
 | 
				
			||||||
 | 
									transform scale(1)
 | 
				
			||||||
 | 
									opacity 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> input
 | 
				
			||||||
 | 
							position absolute
 | 
				
			||||||
 | 
							width 0
 | 
				
			||||||
 | 
							height 0
 | 
				
			||||||
 | 
							opacity 0
 | 
				
			||||||
 | 
							margin 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> .button
 | 
				
			||||||
 | 
							position absolute
 | 
				
			||||||
 | 
							width 20px
 | 
				
			||||||
 | 
							height 20px
 | 
				
			||||||
 | 
							background none
 | 
				
			||||||
 | 
							border solid 2px isDark ? rgba(#fff, 0.7) : rgba(#000, 0.54)
 | 
				
			||||||
 | 
							border-radius 100%
 | 
				
			||||||
 | 
							transition inherit
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&:after
 | 
				
			||||||
 | 
								content ''
 | 
				
			||||||
 | 
								display block
 | 
				
			||||||
 | 
								position absolute
 | 
				
			||||||
 | 
								top 3px
 | 
				
			||||||
 | 
								right 3px
 | 
				
			||||||
 | 
								bottom 3px
 | 
				
			||||||
 | 
								left 3px
 | 
				
			||||||
 | 
								border-radius 100%
 | 
				
			||||||
 | 
								opacity 0
 | 
				
			||||||
 | 
								transform scale(0)
 | 
				
			||||||
 | 
								transition 0.4s cubic-bezier(0.25, 0.8, 0.25, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> .label
 | 
				
			||||||
 | 
							margin-left 28px
 | 
				
			||||||
 | 
							display block
 | 
				
			||||||
 | 
							font-size 16px
 | 
				
			||||||
 | 
							line-height 20px
 | 
				
			||||||
 | 
							cursor pointer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.ui-radio[data-darkmode]
 | 
				
			||||||
 | 
						root(true)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.ui-radio:not([data-darkmode])
 | 
				
			||||||
 | 
						root(false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										215
									
								
								src/client/app/common/views/components/ui/select.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								src/client/app/common/views/components/ui/select.vue
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,215 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					<div class="ui-select" :class="[{ focused, filled }, styl]">
 | 
				
			||||||
 | 
						<div class="icon" ref="icon"><slot name="icon"></slot></div>
 | 
				
			||||||
 | 
						<div class="input" @click="focus">
 | 
				
			||||||
 | 
							<span class="label" ref="label"><slot name="label"></slot></span>
 | 
				
			||||||
 | 
							<div class="prefix" ref="prefix"><slot name="prefix"></slot></div>
 | 
				
			||||||
 | 
							<select ref="input"
 | 
				
			||||||
 | 
									:value="v"
 | 
				
			||||||
 | 
									:required="required"
 | 
				
			||||||
 | 
									@input="$emit('input', $event.target.value)"
 | 
				
			||||||
 | 
									@focus="focused = true"
 | 
				
			||||||
 | 
									@blur="focused = false">
 | 
				
			||||||
 | 
								<slot></slot>
 | 
				
			||||||
 | 
							</select>
 | 
				
			||||||
 | 
							<div class="suffix"><slot name="suffix"></slot></div>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
						<div class="text"><slot name="text"></slot></div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
					import Vue from 'vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Vue.extend({
 | 
				
			||||||
 | 
						props: {
 | 
				
			||||||
 | 
							value: {
 | 
				
			||||||
 | 
								required: false
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							required: {
 | 
				
			||||||
 | 
								type: Boolean,
 | 
				
			||||||
 | 
								required: false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						data() {
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								v: this.value,
 | 
				
			||||||
 | 
								focused: false,
 | 
				
			||||||
 | 
								styl: 'fill'
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						computed: {
 | 
				
			||||||
 | 
							filled(): boolean {
 | 
				
			||||||
 | 
								return this.v != '' && this.v != null;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						watch: {
 | 
				
			||||||
 | 
							value(v) {
 | 
				
			||||||
 | 
								this.v = v;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						inject: {
 | 
				
			||||||
 | 
							isCardChild: { default: false }
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						created() {
 | 
				
			||||||
 | 
							if (this.isCardChild) {
 | 
				
			||||||
 | 
								this.styl = 'line';
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						mounted() {
 | 
				
			||||||
 | 
							if (this.$refs.prefix) {
 | 
				
			||||||
 | 
								this.$refs.label.style.left = (this.$refs.prefix.offsetLeft + this.$refs.prefix.offsetWidth) + 'px';
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						methods: {
 | 
				
			||||||
 | 
							focus() {
 | 
				
			||||||
 | 
								this.$refs.input.focus();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="stylus" scoped>
 | 
				
			||||||
 | 
					@import '~const.styl'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					root(isDark, fill)
 | 
				
			||||||
 | 
						margin 32px 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> .icon
 | 
				
			||||||
 | 
							position absolute
 | 
				
			||||||
 | 
							top 0
 | 
				
			||||||
 | 
							left 0
 | 
				
			||||||
 | 
							width 24px
 | 
				
			||||||
 | 
							text-align center
 | 
				
			||||||
 | 
							line-height 32px
 | 
				
			||||||
 | 
							color rgba(#000, 0.54)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&:not(:empty) + .input
 | 
				
			||||||
 | 
								margin-left 28px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> .input
 | 
				
			||||||
 | 
							display flex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if fill
 | 
				
			||||||
 | 
								padding 6px 12px
 | 
				
			||||||
 | 
								background rgba(#000, 0.035)
 | 
				
			||||||
 | 
								border-radius 6px
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								&:before
 | 
				
			||||||
 | 
									content ''
 | 
				
			||||||
 | 
									display block
 | 
				
			||||||
 | 
									position absolute
 | 
				
			||||||
 | 
									bottom 0
 | 
				
			||||||
 | 
									left 0
 | 
				
			||||||
 | 
									right 0
 | 
				
			||||||
 | 
									height 1px
 | 
				
			||||||
 | 
									background isDark ? rgba(#fff, 0.7) : rgba(#000, 0.42)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&:after
 | 
				
			||||||
 | 
									content ''
 | 
				
			||||||
 | 
									display block
 | 
				
			||||||
 | 
									position absolute
 | 
				
			||||||
 | 
									bottom 0
 | 
				
			||||||
 | 
									left 0
 | 
				
			||||||
 | 
									right 0
 | 
				
			||||||
 | 
									height 2px
 | 
				
			||||||
 | 
									background $theme-color
 | 
				
			||||||
 | 
									opacity 0
 | 
				
			||||||
 | 
									transform scaleX(0.12)
 | 
				
			||||||
 | 
									transition border 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1), transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)
 | 
				
			||||||
 | 
									will-change border opacity transform
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> .label
 | 
				
			||||||
 | 
								position absolute
 | 
				
			||||||
 | 
								top fill ? 6px : 0
 | 
				
			||||||
 | 
								left 0
 | 
				
			||||||
 | 
								pointer-events none
 | 
				
			||||||
 | 
								transition 0.4s cubic-bezier(0.25, 0.8, 0.25, 1)
 | 
				
			||||||
 | 
								transition-duration 0.3s
 | 
				
			||||||
 | 
								font-size 16px
 | 
				
			||||||
 | 
								line-height 32px
 | 
				
			||||||
 | 
								color rgba(#000, 0.54)
 | 
				
			||||||
 | 
								pointer-events none
 | 
				
			||||||
 | 
								//will-change transform
 | 
				
			||||||
 | 
								transform-origin top left
 | 
				
			||||||
 | 
								transform scale(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> select
 | 
				
			||||||
 | 
								display block
 | 
				
			||||||
 | 
								flex 1
 | 
				
			||||||
 | 
								width 100%
 | 
				
			||||||
 | 
								padding 0
 | 
				
			||||||
 | 
								font inherit
 | 
				
			||||||
 | 
								font-weight fill ? bold : normal
 | 
				
			||||||
 | 
								font-size 16px
 | 
				
			||||||
 | 
								height 32px
 | 
				
			||||||
 | 
								color isDark ? #fff : #000
 | 
				
			||||||
 | 
								background transparent
 | 
				
			||||||
 | 
								border none
 | 
				
			||||||
 | 
								border-radius 0
 | 
				
			||||||
 | 
								outline none
 | 
				
			||||||
 | 
								box-shadow none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								*
 | 
				
			||||||
 | 
									color #000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> .prefix
 | 
				
			||||||
 | 
							> .suffix
 | 
				
			||||||
 | 
								display block
 | 
				
			||||||
 | 
								align-self center
 | 
				
			||||||
 | 
								justify-self center
 | 
				
			||||||
 | 
								font-size 16px
 | 
				
			||||||
 | 
								line-height 32px
 | 
				
			||||||
 | 
								color rgba(#000, 0.54)
 | 
				
			||||||
 | 
								pointer-events none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> *
 | 
				
			||||||
 | 
									display block
 | 
				
			||||||
 | 
									min-width 16px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> .prefix
 | 
				
			||||||
 | 
								padding-right 4px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> .suffix
 | 
				
			||||||
 | 
								padding-left 4px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> .text
 | 
				
			||||||
 | 
							margin 6px 0
 | 
				
			||||||
 | 
							font-size 13px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							*
 | 
				
			||||||
 | 
								margin 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&.focused
 | 
				
			||||||
 | 
							> .input
 | 
				
			||||||
 | 
								if fill
 | 
				
			||||||
 | 
									background rgba(#000, 0.05)
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									&:after
 | 
				
			||||||
 | 
										opacity 1
 | 
				
			||||||
 | 
										transform scaleX(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> .label
 | 
				
			||||||
 | 
									color $theme-color
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&.focused
 | 
				
			||||||
 | 
						&.filled
 | 
				
			||||||
 | 
							> .input
 | 
				
			||||||
 | 
								> .label
 | 
				
			||||||
 | 
									top fill ? -24px : -17px
 | 
				
			||||||
 | 
									left 0 !important
 | 
				
			||||||
 | 
									transform scale(0.75)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.ui-select[data-darkmode]
 | 
				
			||||||
 | 
						&.fill
 | 
				
			||||||
 | 
							root(true, true)
 | 
				
			||||||
 | 
						&:not(.fill)
 | 
				
			||||||
 | 
							root(true, false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.ui-select:not([data-darkmode])
 | 
				
			||||||
 | 
						&.fill
 | 
				
			||||||
 | 
							root(false, true)
 | 
				
			||||||
 | 
						&:not(.fill)
 | 
				
			||||||
 | 
							root(false, false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										135
									
								
								src/client/app/common/views/components/ui/switch.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								src/client/app/common/views/components/ui/switch.vue
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,135 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					<div
 | 
				
			||||||
 | 
						class="ui-switch"
 | 
				
			||||||
 | 
						:class="{ disabled, checked }"
 | 
				
			||||||
 | 
						role="switch"
 | 
				
			||||||
 | 
						:aria-checked="checked"
 | 
				
			||||||
 | 
						:aria-disabled="disabled"
 | 
				
			||||||
 | 
						@click="toggle"
 | 
				
			||||||
 | 
					>
 | 
				
			||||||
 | 
						<input
 | 
				
			||||||
 | 
							type="checkbox"
 | 
				
			||||||
 | 
							ref="input"
 | 
				
			||||||
 | 
							:disabled="disabled"
 | 
				
			||||||
 | 
							@keydown.enter="toggle"
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
						<span class="button">
 | 
				
			||||||
 | 
							<span></span>
 | 
				
			||||||
 | 
						</span>
 | 
				
			||||||
 | 
						<span class="label">
 | 
				
			||||||
 | 
							<span :aria-hidden="!checked"><slot></slot></span>
 | 
				
			||||||
 | 
							<p :aria-hidden="!checked">
 | 
				
			||||||
 | 
								<slot name="text"></slot>
 | 
				
			||||||
 | 
							</p>
 | 
				
			||||||
 | 
						</span>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
					import Vue from 'vue';
 | 
				
			||||||
 | 
					export default Vue.extend({
 | 
				
			||||||
 | 
						model: {
 | 
				
			||||||
 | 
							prop: 'value',
 | 
				
			||||||
 | 
							event: 'change'
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						props: {
 | 
				
			||||||
 | 
							value: {
 | 
				
			||||||
 | 
								type: Boolean,
 | 
				
			||||||
 | 
								default: false
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							disabled: {
 | 
				
			||||||
 | 
								type: Boolean,
 | 
				
			||||||
 | 
								default: false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						computed: {
 | 
				
			||||||
 | 
							checked(): boolean {
 | 
				
			||||||
 | 
								return this.value;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						methods: {
 | 
				
			||||||
 | 
							toggle() {
 | 
				
			||||||
 | 
								this.$emit('change', !this.checked);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="stylus" scoped>
 | 
				
			||||||
 | 
					@import '~const.styl'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					root(isDark)
 | 
				
			||||||
 | 
						display flex
 | 
				
			||||||
 | 
						margin 32px 0
 | 
				
			||||||
 | 
						cursor pointer
 | 
				
			||||||
 | 
						transition all 0.3s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> *
 | 
				
			||||||
 | 
							user-select none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&.disabled
 | 
				
			||||||
 | 
							opacity 0.6
 | 
				
			||||||
 | 
							cursor not-allowed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&.checked
 | 
				
			||||||
 | 
							> .button
 | 
				
			||||||
 | 
								background-color rgba($theme-color, 0.4)
 | 
				
			||||||
 | 
								border-color rgba($theme-color, 0.4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> *
 | 
				
			||||||
 | 
									background-color $theme-color
 | 
				
			||||||
 | 
									transform translateX(14px)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> input
 | 
				
			||||||
 | 
							position absolute
 | 
				
			||||||
 | 
							width 0
 | 
				
			||||||
 | 
							height 0
 | 
				
			||||||
 | 
							opacity 0
 | 
				
			||||||
 | 
							margin 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> .button
 | 
				
			||||||
 | 
							display inline-block
 | 
				
			||||||
 | 
							margin 3px 0 0 0
 | 
				
			||||||
 | 
							width 34px
 | 
				
			||||||
 | 
							height 14px
 | 
				
			||||||
 | 
							background isDark ? rgba(#fff, 0.15) : rgba(#000, 0.25)
 | 
				
			||||||
 | 
							outline none
 | 
				
			||||||
 | 
							border-radius 14px
 | 
				
			||||||
 | 
							transition inherit
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> *
 | 
				
			||||||
 | 
								position absolute
 | 
				
			||||||
 | 
								top -3px
 | 
				
			||||||
 | 
								left 0
 | 
				
			||||||
 | 
								border-radius 100%
 | 
				
			||||||
 | 
								transition background-color 0.3s, transform 0.3s
 | 
				
			||||||
 | 
								width 20px
 | 
				
			||||||
 | 
								height 20px
 | 
				
			||||||
 | 
								background-color #fff
 | 
				
			||||||
 | 
								box-shadow 0 2px 1px -1px rgba(#000, 0.2), 0 1px 1px 0 rgba(#000, 0.14), 0 1px 3px 0 rgba(#000, 0.12)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> .label
 | 
				
			||||||
 | 
							margin-left 8px
 | 
				
			||||||
 | 
							display block
 | 
				
			||||||
 | 
							font-size 16px
 | 
				
			||||||
 | 
							cursor pointer
 | 
				
			||||||
 | 
							transition inherit
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> span
 | 
				
			||||||
 | 
								display block
 | 
				
			||||||
 | 
								line-height 20px
 | 
				
			||||||
 | 
								color isDark ? #c4ccd2 : rgba(#000, 0.75)
 | 
				
			||||||
 | 
								transition inherit
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> p
 | 
				
			||||||
 | 
								margin 0
 | 
				
			||||||
 | 
								//font-size 90%
 | 
				
			||||||
 | 
								color isDark ? #78858e : #9daab3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.ui-switch[data-darkmode]
 | 
				
			||||||
 | 
						root(true)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.ui-switch:not([data-darkmode])
 | 
				
			||||||
 | 
						root(false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										174
									
								
								src/client/app/common/views/components/ui/textarea.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								src/client/app/common/views/components/ui/textarea.vue
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,174 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					<div class="ui-textarea" :class="{ focused, filled }">
 | 
				
			||||||
 | 
						<div class="input">
 | 
				
			||||||
 | 
							<span class="label" ref="label"><slot></slot></span>
 | 
				
			||||||
 | 
							<textarea ref="input"
 | 
				
			||||||
 | 
									:value="value"
 | 
				
			||||||
 | 
									:required="required"
 | 
				
			||||||
 | 
									:readonly="readonly"
 | 
				
			||||||
 | 
									:pattern="pattern"
 | 
				
			||||||
 | 
									:autocomplete="autocomplete"
 | 
				
			||||||
 | 
									@input="$emit('input', $event.target.value)"
 | 
				
			||||||
 | 
									@focus="focused = true"
 | 
				
			||||||
 | 
									@blur="focused = false">
 | 
				
			||||||
 | 
							</textarea>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
						<div class="text"><slot name="text"></slot></div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
					import Vue from 'vue';
 | 
				
			||||||
 | 
					const getPasswordStrength = require('syuilo-password-strength');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Vue.extend({
 | 
				
			||||||
 | 
						props: {
 | 
				
			||||||
 | 
							value: {
 | 
				
			||||||
 | 
								required: false
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							required: {
 | 
				
			||||||
 | 
								type: Boolean,
 | 
				
			||||||
 | 
								required: false
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							readonly: {
 | 
				
			||||||
 | 
								type: Boolean,
 | 
				
			||||||
 | 
								required: false
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							pattern: {
 | 
				
			||||||
 | 
								type: String,
 | 
				
			||||||
 | 
								required: false
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							autocomplete: {
 | 
				
			||||||
 | 
								type: String,
 | 
				
			||||||
 | 
								required: false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						data() {
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								focused: false,
 | 
				
			||||||
 | 
								passwordStrength: ''
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						computed: {
 | 
				
			||||||
 | 
							filled(): boolean {
 | 
				
			||||||
 | 
								return this.value != '' && this.value != null;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						methods: {
 | 
				
			||||||
 | 
							focus() {
 | 
				
			||||||
 | 
								this.$refs.input.focus();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="stylus" scoped>
 | 
				
			||||||
 | 
					@import '~const.styl'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					root(isDark, fill)
 | 
				
			||||||
 | 
						margin 32px 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> .input
 | 
				
			||||||
 | 
							padding 12px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if fill
 | 
				
			||||||
 | 
								background rgba(#000, 0.035)
 | 
				
			||||||
 | 
								border-radius 6px
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								&:before
 | 
				
			||||||
 | 
									content ''
 | 
				
			||||||
 | 
									display block
 | 
				
			||||||
 | 
									position absolute
 | 
				
			||||||
 | 
									top 0
 | 
				
			||||||
 | 
									bottom 0
 | 
				
			||||||
 | 
									left 0
 | 
				
			||||||
 | 
									right 0
 | 
				
			||||||
 | 
									background none
 | 
				
			||||||
 | 
									border solid 1px isDark ? rgba(#fff, 0.7) : rgba(#000, 0.42)
 | 
				
			||||||
 | 
									border-radius 3px
 | 
				
			||||||
 | 
									pointer-events none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&:after
 | 
				
			||||||
 | 
									content ''
 | 
				
			||||||
 | 
									display block
 | 
				
			||||||
 | 
									position absolute
 | 
				
			||||||
 | 
									top 0
 | 
				
			||||||
 | 
									bottom 0
 | 
				
			||||||
 | 
									left 0
 | 
				
			||||||
 | 
									right 0
 | 
				
			||||||
 | 
									background none
 | 
				
			||||||
 | 
									border solid 2px $theme-color
 | 
				
			||||||
 | 
									border-radius 3px
 | 
				
			||||||
 | 
									opacity 0
 | 
				
			||||||
 | 
									transition opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1)
 | 
				
			||||||
 | 
									pointer-events none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> .label
 | 
				
			||||||
 | 
								position absolute
 | 
				
			||||||
 | 
								top 6px
 | 
				
			||||||
 | 
								left 12px
 | 
				
			||||||
 | 
								pointer-events none
 | 
				
			||||||
 | 
								transition 0.4s cubic-bezier(0.25, 0.8, 0.25, 1)
 | 
				
			||||||
 | 
								transition-duration 0.3s
 | 
				
			||||||
 | 
								font-size 16px
 | 
				
			||||||
 | 
								line-height 32px
 | 
				
			||||||
 | 
								color isDark ? rgba(#fff, 0.7) : rgba(#000, 0.54)
 | 
				
			||||||
 | 
								pointer-events none
 | 
				
			||||||
 | 
								//will-change transform
 | 
				
			||||||
 | 
								transform-origin top left
 | 
				
			||||||
 | 
								transform scale(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> textarea
 | 
				
			||||||
 | 
								display block
 | 
				
			||||||
 | 
								width 100%
 | 
				
			||||||
 | 
								min-height 100px
 | 
				
			||||||
 | 
								padding 0
 | 
				
			||||||
 | 
								font inherit
 | 
				
			||||||
 | 
								font-weight fill ? bold : normal
 | 
				
			||||||
 | 
								font-size 16px
 | 
				
			||||||
 | 
								color isDark ? #fff : #000
 | 
				
			||||||
 | 
								background transparent
 | 
				
			||||||
 | 
								border none
 | 
				
			||||||
 | 
								border-radius 0
 | 
				
			||||||
 | 
								outline none
 | 
				
			||||||
 | 
								box-shadow none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> .text
 | 
				
			||||||
 | 
							margin 6px 0
 | 
				
			||||||
 | 
							font-size 13px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							*
 | 
				
			||||||
 | 
								margin 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&.focused
 | 
				
			||||||
 | 
							> .input
 | 
				
			||||||
 | 
								if fill
 | 
				
			||||||
 | 
									background rgba(#000, 0.05)
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									&:after
 | 
				
			||||||
 | 
										opacity 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> .label
 | 
				
			||||||
 | 
									color $theme-color
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&.focused
 | 
				
			||||||
 | 
						&.filled
 | 
				
			||||||
 | 
							> .input
 | 
				
			||||||
 | 
								> .label
 | 
				
			||||||
 | 
									top -24px
 | 
				
			||||||
 | 
									left 0 !important
 | 
				
			||||||
 | 
									transform scale(0.75)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.ui-textarea[data-darkmode]
 | 
				
			||||||
 | 
						&.fill
 | 
				
			||||||
 | 
							root(true, true)
 | 
				
			||||||
 | 
						&:not(.fill)
 | 
				
			||||||
 | 
							root(true, false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.ui-textarea:not([data-darkmode])
 | 
				
			||||||
 | 
						&.fill
 | 
				
			||||||
 | 
							root(false, true)
 | 
				
			||||||
 | 
						&:not(.fill)
 | 
				
			||||||
 | 
							root(false, false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,8 @@
 | 
				
			||||||
declare const _HOST_: string;
 | 
					declare const _HOST_: string;
 | 
				
			||||||
declare const _HOSTNAME_: string;
 | 
					declare const _HOSTNAME_: string;
 | 
				
			||||||
declare const _URL_: string;
 | 
					declare const _URL_: string;
 | 
				
			||||||
 | 
					declare const _NAME_: string;
 | 
				
			||||||
 | 
					declare const _DESCRIPTION_: string;
 | 
				
			||||||
declare const _API_URL_: string;
 | 
					declare const _API_URL_: string;
 | 
				
			||||||
declare const _WS_URL_: string;
 | 
					declare const _WS_URL_: string;
 | 
				
			||||||
declare const _DOCS_URL_: string;
 | 
					declare const _DOCS_URL_: string;
 | 
				
			||||||
| 
						 | 
					@ -21,6 +23,8 @@ declare const _GOOGLE_MAPS_API_KEY_: string;
 | 
				
			||||||
export const host = _HOST_;
 | 
					export const host = _HOST_;
 | 
				
			||||||
export const hostname = _HOSTNAME_;
 | 
					export const hostname = _HOSTNAME_;
 | 
				
			||||||
export const url = _URL_;
 | 
					export const url = _URL_;
 | 
				
			||||||
 | 
					export const name = _NAME_;
 | 
				
			||||||
 | 
					export const description = _DESCRIPTION_;
 | 
				
			||||||
export const apiUrl = _API_URL_;
 | 
					export const apiUrl = _API_URL_;
 | 
				
			||||||
export const wsUrl = _WS_URL_;
 | 
					export const wsUrl = _WS_URL_;
 | 
				
			||||||
export const docsUrl = _DOCS_URL_;
 | 
					export const docsUrl = _DOCS_URL_;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,17 +2,11 @@
 | 
				
			||||||
 * Mobile Client
 | 
					 * Mobile Client
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Vue from 'vue';
 | 
					 | 
				
			||||||
import VueRouter from 'vue-router';
 | 
					import VueRouter from 'vue-router';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { MdCard, MdButton, MdField, MdMenu, MdList, MdSwitch, MdSubheader, MdDialog, MdDialogAlert, MdRadio } from 'vue-material/dist/components';
 | 
					 | 
				
			||||||
import 'vue-material/dist/vue-material.min.css';
 | 
					 | 
				
			||||||
import 'vue-material/dist/theme/default.css';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Style
 | 
					// Style
 | 
				
			||||||
import './style.styl';
 | 
					import './style.styl';
 | 
				
			||||||
import '../../element.scss';
 | 
					import '../../element.scss';
 | 
				
			||||||
import '../../md.scss';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import init from '../init';
 | 
					import init from '../init';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,17 +38,6 @@ import MkSettings from './views/pages/settings.vue';
 | 
				
			||||||
import MkOthello from './views/pages/othello.vue';
 | 
					import MkOthello from './views/pages/othello.vue';
 | 
				
			||||||
import MkTag from './views/pages/tag.vue';
 | 
					import MkTag from './views/pages/tag.vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Vue.use(MdCard);
 | 
					 | 
				
			||||||
Vue.use(MdButton);
 | 
					 | 
				
			||||||
Vue.use(MdField);
 | 
					 | 
				
			||||||
Vue.use(MdMenu);
 | 
					 | 
				
			||||||
Vue.use(MdList);
 | 
					 | 
				
			||||||
Vue.use(MdSwitch);
 | 
					 | 
				
			||||||
Vue.use(MdSubheader);
 | 
					 | 
				
			||||||
Vue.use(MdDialog);
 | 
					 | 
				
			||||||
Vue.use(MdDialogAlert);
 | 
					 | 
				
			||||||
Vue.use(MdRadio);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * init
 | 
					 * init
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,9 +10,6 @@ html
 | 
				
			||||||
	height 100%
 | 
						height 100%
 | 
				
			||||||
	background #ececed !important
 | 
						background #ececed !important
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// for md
 | 
					 | 
				
			||||||
	transition none !important
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	&[data-darkmode]
 | 
						&[data-darkmode]
 | 
				
			||||||
		background #191B22 !important
 | 
							background #191B22 !important
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,132 +1,84 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<mk-ui>
 | 
					<mk-ui>
 | 
				
			||||||
	<span slot="header">%fa:cog%%i18n:@settings%</span>
 | 
						<span slot="header">%fa:cog%%i18n:@settings%</span>
 | 
				
			||||||
	<main>
 | 
						<main :data-darkmode="$store.state.device.darkmode">
 | 
				
			||||||
		<p v-html="'%i18n:@signed-in-as%'.replace('{}', '<b>' + name + '</b>')"></p>
 | 
							<div class="signin-as" v-html="'%i18n:@signed-in-as%'.replace('{}', '<b>' + name + '</b>')"></div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		<div>
 | 
							<div>
 | 
				
			||||||
			<x-profile/>
 | 
								<x-profile/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<md-card>
 | 
								<ui-card>
 | 
				
			||||||
				<md-card-header>
 | 
									<div slot="title">%fa:palette% %i18n:@design%</div>
 | 
				
			||||||
					<div class="md-title">%fa:palette% %i18n:@design%</div>
 | 
					
 | 
				
			||||||
				</md-card-header>
 | 
									<ui-switch v-model="darkmode">%i18n:@dark-mode%</ui-switch>
 | 
				
			||||||
 | 
									<ui-switch v-model="$store.state.settings.circleIcons" @change="onChangeCircleIcons">%i18n:@circle-icons%</ui-switch>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				<md-card-content>
 | 
					 | 
				
			||||||
				<div>
 | 
									<div>
 | 
				
			||||||
						<md-switch v-model="darkmode">%i18n:@dark-mode%</md-switch>
 | 
										<div>%i18n:@timeline%</div>
 | 
				
			||||||
 | 
										<ui-switch v-model="$store.state.settings.showReplyTarget" @change="onChangeShowReplyTarget">%i18n:@show-reply-target%</ui-switch>
 | 
				
			||||||
 | 
										<ui-switch v-model="$store.state.settings.showMyRenotes" @change="onChangeShowMyRenotes">%i18n:@show-my-renotes%</ui-switch>
 | 
				
			||||||
 | 
										<ui-switch v-model="$store.state.settings.showRenotedMyNotes" @change="onChangeShowRenotedMyNotes">%i18n:@show-renoted-my-notes%</ui-switch>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				<div>
 | 
									<div>
 | 
				
			||||||
						<md-switch v-model="$store.state.settings.circleIcons" @change="onChangeCircleIcons">%i18n:@circle-icons%</md-switch>
 | 
										<div>%i18n:@post-style%</div>
 | 
				
			||||||
 | 
										<ui-radio v-model="postStyle" value="standard">%i18n:@post-style-standard%</ui-radio>
 | 
				
			||||||
 | 
										<ui-radio v-model="postStyle" value="smart">%i18n:@post-style-smart%</ui-radio>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
 | 
								</ui-card>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					<div>
 | 
								<ui-card>
 | 
				
			||||||
						<div class="md-body-2">%i18n:@timeline%</div>
 | 
									<div slot="title">%fa:cog% %i18n:@behavior%</div>
 | 
				
			||||||
 | 
									<ui-switch v-model="$store.state.settings.fetchOnScroll" @change="onChangeFetchOnScroll">%i18n:@fetch-on-scroll%</ui-switch>
 | 
				
			||||||
 | 
									<ui-switch v-model="$store.state.settings.disableViaMobile" @change="onChangeDisableViaMobile">%i18n:@disable-via-mobile%</ui-switch>
 | 
				
			||||||
 | 
									<ui-switch v-model="loadRawImages">%i18n:@load-raw-images%</ui-switch>
 | 
				
			||||||
 | 
									<ui-switch v-model="$store.state.settings.loadRemoteMedia" @change="onChangeLoadRemoteMedia">%i18n:@load-remote-media%</ui-switch>
 | 
				
			||||||
 | 
									<ui-switch v-model="lightmode">%i18n:@i-am-under-limited-internet%</ui-switch>
 | 
				
			||||||
 | 
								</ui-card>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						<div>
 | 
								<ui-card>
 | 
				
			||||||
							<md-switch v-model="$store.state.settings.showReplyTarget" @change="onChangeShowReplyTarget">%i18n:@show-reply-target%</md-switch>
 | 
									<div slot="title">%fa:language% %i18n:@lang%</div>
 | 
				
			||||||
						</div>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
						<div>
 | 
									<ui-select v-model="lang" placeholder="%i18n:@auto%">
 | 
				
			||||||
							<md-switch v-model="$store.state.settings.showMyRenotes" @change="onChangeShowMyRenotes">%i18n:@show-my-renotes%</md-switch>
 | 
										<optgroup label="%i18n:@recommended%">
 | 
				
			||||||
						</div>
 | 
											<option value="">%i18n:@auto%</option>
 | 
				
			||||||
 | 
										</optgroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						<div>
 | 
										<optgroup label="%i18n:@specify-language%">
 | 
				
			||||||
							<md-switch v-model="$store.state.settings.showRenotedMyNotes" @change="onChangeShowRenotedMyNotes">%i18n:@show-renoted-my-notes%</md-switch>
 | 
											<option v-for="x in langs" :value="x[0]" :key="x[0]">{{ x[1] }}</option>
 | 
				
			||||||
						</div>
 | 
										</optgroup>
 | 
				
			||||||
					</div>
 | 
									</ui-select>
 | 
				
			||||||
 | 
									<span>%fa:info-circle% %i18n:@lang-tip%</span>
 | 
				
			||||||
 | 
								</ui-card>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					<div>
 | 
								<ui-card>
 | 
				
			||||||
						<div class="md-body-2">%i18n:@post-style%</div>
 | 
									<div slot="title">%fa:B twitter% %i18n:@twitter%</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						<md-radio v-model="postStyle" value="standard">%i18n:@post-style-standard%</md-radio>
 | 
					 | 
				
			||||||
						<md-radio v-model="postStyle" value="smart">%i18n:@post-style-smart%</md-radio>
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
				</md-card-content>
 | 
					 | 
				
			||||||
			</md-card>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			<md-card>
 | 
					 | 
				
			||||||
				<md-card-header>
 | 
					 | 
				
			||||||
					<div class="md-title">%fa:cog% %i18n:@behavior%</div>
 | 
					 | 
				
			||||||
				</md-card-header>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				<md-card-content>
 | 
					 | 
				
			||||||
					<div>
 | 
					 | 
				
			||||||
						<md-switch v-model="$store.state.settings.fetchOnScroll" @change="onChangeFetchOnScroll">%i18n:@fetch-on-scroll%</md-switch>
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					<div>
 | 
					 | 
				
			||||||
						<md-switch v-model="$store.state.settings.disableViaMobile" @change="onChangeDisableViaMobile">%i18n:@disable-via-mobile%</md-switch>
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					<div>
 | 
					 | 
				
			||||||
						<md-switch v-model="loadRawImages">%i18n:@load-raw-images%</md-switch>
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					<div>
 | 
					 | 
				
			||||||
						<md-switch v-model="$store.state.settings.loadRemoteMedia" @change="onChangeLoadRemoteMedia">%i18n:@load-remote-media%</md-switch>
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					<div>
 | 
					 | 
				
			||||||
						<md-switch v-model="lightmode">%i18n:@i-am-under-limited-internet%</md-switch>
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
				</md-card-content>
 | 
					 | 
				
			||||||
			</md-card>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			<md-card>
 | 
					 | 
				
			||||||
				<md-card-header>
 | 
					 | 
				
			||||||
					<div class="md-title">%fa:language% %i18n:@lang%</div>
 | 
					 | 
				
			||||||
				</md-card-header>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				<md-card-content>
 | 
					 | 
				
			||||||
					<md-field>
 | 
					 | 
				
			||||||
						<md-select v-model="lang" placeholder="%i18n:@auto%">
 | 
					 | 
				
			||||||
							<md-optgroup label="%i18n:@recommended%">
 | 
					 | 
				
			||||||
								<md-option value="">%i18n:@auto%</md-option>
 | 
					 | 
				
			||||||
							</md-optgroup>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							<md-optgroup label="%i18n:@specify-language%">
 | 
					 | 
				
			||||||
								<md-option v-for="x in langs" :value="x[0]" :key="x[0]">{{ x[1] }}</md-option>
 | 
					 | 
				
			||||||
							</md-optgroup>
 | 
					 | 
				
			||||||
						</md-select>
 | 
					 | 
				
			||||||
					</md-field>
 | 
					 | 
				
			||||||
					<span class="md-helper-text">%fa:info-circle% %i18n:@lang-tip%</span>
 | 
					 | 
				
			||||||
				</md-card-content>
 | 
					 | 
				
			||||||
			</md-card>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			<md-card>
 | 
					 | 
				
			||||||
				<md-card-header>
 | 
					 | 
				
			||||||
					<div class="md-title">%fa:B twitter% %i18n:@twitter%</div>
 | 
					 | 
				
			||||||
				</md-card-header>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				<md-card-content>
 | 
					 | 
				
			||||||
				<p class="account" v-if="$store.state.i.twitter"><a :href="`https://twitter.com/${$store.state.i.twitter.screenName}`" target="_blank">@{{ $store.state.i.twitter.screenName }}</a></p>
 | 
									<p class="account" v-if="$store.state.i.twitter"><a :href="`https://twitter.com/${$store.state.i.twitter.screenName}`" target="_blank">@{{ $store.state.i.twitter.screenName }}</a></p>
 | 
				
			||||||
				<p>
 | 
									<p>
 | 
				
			||||||
					<a :href="`${apiUrl}/connect/twitter`" target="_blank">{{ $store.state.i.twitter ? '%i18n:@twitter-reconnect%' : '%i18n:@twitter-connect%' }}</a>
 | 
										<a :href="`${apiUrl}/connect/twitter`" target="_blank">{{ $store.state.i.twitter ? '%i18n:@twitter-reconnect%' : '%i18n:@twitter-connect%' }}</a>
 | 
				
			||||||
					<span v-if="$store.state.i.twitter"> or </span>
 | 
										<span v-if="$store.state.i.twitter"> or </span>
 | 
				
			||||||
					<a :href="`${apiUrl}/disconnect/twitter`" target="_blank" v-if="$store.state.i.twitter">%i18n:@twitter-disconnect%</a>
 | 
										<a :href="`${apiUrl}/disconnect/twitter`" target="_blank" v-if="$store.state.i.twitter">%i18n:@twitter-disconnect%</a>
 | 
				
			||||||
				</p>
 | 
									</p>
 | 
				
			||||||
				</md-card-content>
 | 
								</ui-card>
 | 
				
			||||||
			</md-card>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<md-card>
 | 
								<ui-card>
 | 
				
			||||||
				<md-card-header>
 | 
									<div slot="title">%fa:sync-alt% %i18n:@update%</div>
 | 
				
			||||||
					<div class="md-title">%fa:sync-alt% %i18n:@update%</div>
 | 
					 | 
				
			||||||
				</md-card-header>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				<md-card-content>
 | 
					 | 
				
			||||||
				<div>%i18n:@version% <i>{{ version }}</i></div>
 | 
									<div>%i18n:@version% <i>{{ version }}</i></div>
 | 
				
			||||||
				<template v-if="latestVersion !== undefined">
 | 
									<template v-if="latestVersion !== undefined">
 | 
				
			||||||
					<div>%i18n:@latest-version% <i>{{ latestVersion ? latestVersion : version }}</i></div>
 | 
										<div>%i18n:@latest-version% <i>{{ latestVersion ? latestVersion : version }}</i></div>
 | 
				
			||||||
				</template>
 | 
									</template>
 | 
				
			||||||
					<md-button class="md-raised md-primary" @click="checkForUpdate" :disabled="checkingForUpdate">
 | 
									<ui-button @click="checkForUpdate" :disabled="checkingForUpdate">
 | 
				
			||||||
					<template v-if="checkingForUpdate">%i18n:@update-checking%<mk-ellipsis/></template>
 | 
										<template v-if="checkingForUpdate">%i18n:@update-checking%<mk-ellipsis/></template>
 | 
				
			||||||
					<template v-else>%i18n:@check-for-updates%</template>
 | 
										<template v-else>%i18n:@check-for-updates%</template>
 | 
				
			||||||
					</md-button>
 | 
									</ui-button>
 | 
				
			||||||
				</md-card-content>
 | 
								</ui-card>
 | 
				
			||||||
			</md-card>
 | 
					 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
		<p><small>ver {{ version }} ({{ codename }})</small></p>
 | 
					
 | 
				
			||||||
 | 
							<footer>
 | 
				
			||||||
 | 
								<small>ver {{ version }} ({{ codename }})</small>
 | 
				
			||||||
 | 
							</footer>
 | 
				
			||||||
	</main>
 | 
						</main>
 | 
				
			||||||
</mk-ui>
 | 
					</mk-ui>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
| 
						 | 
					@ -267,20 +219,22 @@ export default Vue.extend({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style lang="stylus" scoped>
 | 
					<style lang="stylus" scoped>
 | 
				
			||||||
root(isDark)
 | 
					root(isDark)
 | 
				
			||||||
	padding 0 16px
 | 
					 | 
				
			||||||
	margin 0 auto
 | 
						margin 0 auto
 | 
				
			||||||
	max-width 500px
 | 
						max-width 500px
 | 
				
			||||||
	width 100%
 | 
						width 100%
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> div
 | 
						> .signin-as
 | 
				
			||||||
		> *
 | 
							margin 16px
 | 
				
			||||||
			margin-bottom 16px
 | 
							padding 16px
 | 
				
			||||||
 | 
					 | 
				
			||||||
	> p
 | 
					 | 
				
			||||||
		display block
 | 
					 | 
				
			||||||
		margin 24px
 | 
					 | 
				
			||||||
		text-align center
 | 
							text-align center
 | 
				
			||||||
		color isDark ? #cad2da : #a2a9b1
 | 
							color isDark ? #49ab63 : #2c662d
 | 
				
			||||||
 | 
							background isDark ? #273c34 : #fcfff5
 | 
				
			||||||
 | 
							box-shadow 0 3px 1px -2px rgba(#000, 0.2), 0 2px 2px 0 rgba(#000, 0.14), 0 1px 5px 0 rgba(#000, 0.12)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> footer
 | 
				
			||||||
 | 
							margin 16px
 | 
				
			||||||
 | 
							text-align center
 | 
				
			||||||
 | 
							color isDark ? #c9d2e0 : #888
 | 
				
			||||||
 | 
					
 | 
				
			||||||
main[data-darkmode]
 | 
					main[data-darkmode]
 | 
				
			||||||
	root(true)
 | 
						root(true)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,62 +1,49 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
	<md-card>
 | 
					<ui-card>
 | 
				
			||||||
		<md-card-header>
 | 
						<div slot="title">%fa:user% %i18n:@title%</div>
 | 
				
			||||||
			<div class="md-title">%fa:pencil-alt% %i18n:@title%</div>
 | 
					 | 
				
			||||||
		</md-card-header>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		<md-card-content>
 | 
						<ui-form :disabled="saving">
 | 
				
			||||||
			<md-field>
 | 
							<ui-input v-model="name" :max="30">
 | 
				
			||||||
				<label>%i18n:@name%</label>
 | 
								<span>%i18n:@name%</span>
 | 
				
			||||||
				<md-input v-model="name" :disabled="saving" md-counter="30"/>
 | 
							</ui-input>
 | 
				
			||||||
			</md-field>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<md-field>
 | 
							<ui-input v-model="username" readonly>
 | 
				
			||||||
				<label>%i18n:@account%</label>
 | 
								<span>%i18n:@account%</span>
 | 
				
			||||||
				<span class="md-prefix">@</span>
 | 
								<span slot="prefix">@</span>
 | 
				
			||||||
				<md-input v-model="username" readonly></md-input>
 | 
								<span slot="suffix">@{{ host }}</span>
 | 
				
			||||||
				<span class="md-suffix">@{{ host }}</span>
 | 
							</ui-input>
 | 
				
			||||||
			</md-field>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<md-field>
 | 
							<ui-input v-model="location">
 | 
				
			||||||
				<md-icon>%fa:map-marker-alt%</md-icon>
 | 
								<span>%i18n:@location%</span>
 | 
				
			||||||
				<label>%i18n:@location%</label>
 | 
								<span slot="prefix">%fa:map-marker-alt%</span>
 | 
				
			||||||
				<md-input v-model="location" :disabled="saving"/>
 | 
							</ui-input>
 | 
				
			||||||
			</md-field>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<md-field>
 | 
							<ui-input v-model="birthday" type="date">
 | 
				
			||||||
				<md-icon>%fa:birthday-cake%</md-icon>
 | 
								<span>%i18n:@birthday%</span>
 | 
				
			||||||
				<label>%i18n:@birthday%</label>
 | 
								<span slot="prefix">%fa:birthday-cake%</span>
 | 
				
			||||||
				<md-input type="date" v-model="birthday" :disabled="saving"/>
 | 
							</ui-input>
 | 
				
			||||||
			</md-field>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<md-field>
 | 
							<ui-textarea v-model="description" :max="500">
 | 
				
			||||||
				<label>%i18n:@description%</label>
 | 
								<span>%i18n:@description%</span>
 | 
				
			||||||
				<md-textarea v-model="description" :disabled="saving" md-counter="500"/>
 | 
							</ui-textarea>
 | 
				
			||||||
			</md-field>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<md-field>
 | 
							<ui-input type="file" @change="onAvatarChange">
 | 
				
			||||||
				<label>%i18n:@avatar%</label>
 | 
								<span>%i18n:@avatar%</span>
 | 
				
			||||||
				<md-file @md-change="onAvatarChange"/>
 | 
								<span slot="icon">%fa:image%</span>
 | 
				
			||||||
			</md-field>
 | 
								<span slot="text" v-if="avatarUploading">%i18n:@uploading%<mk-ellipsis/></span>
 | 
				
			||||||
 | 
							</ui-input>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<md-field>
 | 
							<ui-input type="file" @change="onBannerChange">
 | 
				
			||||||
				<label>%i18n:@banner%</label>
 | 
								<span>%i18n:@banner%</span>
 | 
				
			||||||
				<md-file @md-change="onBannerChange"/>
 | 
								<span slot="icon">%fa:image%</span>
 | 
				
			||||||
			</md-field>
 | 
								<span slot="text" v-if="bannerUploading">%i18n:@uploading%<mk-ellipsis/></span>
 | 
				
			||||||
 | 
							</ui-input>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<md-dialog-alert
 | 
							<ui-switch v-model="isCat">%i18n:@is-cat%</ui-switch>
 | 
				
			||||||
					:md-active.sync="uploading"
 | 
					 | 
				
			||||||
					md-content="%18n:!@uploading%"/>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<div>
 | 
							<ui-button @click="save">%i18n:@save%</ui-button>
 | 
				
			||||||
				<md-switch v-model="isCat">%i18n:@is-cat%</md-switch>
 | 
						</ui-form>
 | 
				
			||||||
			</div>
 | 
					</ui-card>
 | 
				
			||||||
		</md-card-content>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		<md-card-actions>
 | 
					 | 
				
			||||||
			<md-button class="md-primary" :disabled="saving" @click="save">%i18n:@save%</md-button>
 | 
					 | 
				
			||||||
		</md-card-actions>
 | 
					 | 
				
			||||||
	</md-card>
 | 
					 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
| 
						 | 
					@ -77,7 +64,8 @@ export default Vue.extend({
 | 
				
			||||||
			isBot: false,
 | 
								isBot: false,
 | 
				
			||||||
			isCat: false,
 | 
								isCat: false,
 | 
				
			||||||
			saving: false,
 | 
								saving: false,
 | 
				
			||||||
			uploading: false
 | 
								avatarUploading: false,
 | 
				
			||||||
 | 
								bannerUploading: false
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -95,7 +83,7 @@ export default Vue.extend({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	methods: {
 | 
						methods: {
 | 
				
			||||||
		onAvatarChange([file]) {
 | 
							onAvatarChange([file]) {
 | 
				
			||||||
			this.uploading = true;
 | 
								this.avatarUploading = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			const data = new FormData();
 | 
								const data = new FormData();
 | 
				
			||||||
			data.append('file', file);
 | 
								data.append('file', file);
 | 
				
			||||||
| 
						 | 
					@ -108,16 +96,16 @@ export default Vue.extend({
 | 
				
			||||||
			.then(response => response.json())
 | 
								.then(response => response.json())
 | 
				
			||||||
			.then(f => {
 | 
								.then(f => {
 | 
				
			||||||
				this.avatarId = f.id;
 | 
									this.avatarId = f.id;
 | 
				
			||||||
				this.uploading = false;
 | 
									this.avatarUploading = false;
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
			.catch(e => {
 | 
								.catch(e => {
 | 
				
			||||||
				this.uploading = false;
 | 
									this.avatarUploading = false;
 | 
				
			||||||
				alert('%18n:!@upload-failed%');
 | 
									alert('%18n:!@upload-failed%');
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onBannerChange([file]) {
 | 
							onBannerChange([file]) {
 | 
				
			||||||
			this.uploading = true;
 | 
								this.bannerUploading = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			const data = new FormData();
 | 
								const data = new FormData();
 | 
				
			||||||
			data.append('file', file);
 | 
								data.append('file', file);
 | 
				
			||||||
| 
						 | 
					@ -130,10 +118,10 @@ export default Vue.extend({
 | 
				
			||||||
			.then(response => response.json())
 | 
								.then(response => response.json())
 | 
				
			||||||
			.then(f => {
 | 
								.then(f => {
 | 
				
			||||||
				this.bannerId = f.id;
 | 
									this.bannerId = f.id;
 | 
				
			||||||
				this.uploading = false;
 | 
									this.bannerUploading = false;
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
			.catch(e => {
 | 
								.catch(e => {
 | 
				
			||||||
				this.uploading = false;
 | 
									this.bannerUploading = false;
 | 
				
			||||||
				alert('%18n:!@upload-failed%');
 | 
									alert('%18n:!@upload-failed%');
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,57 +1,26 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div class="signup">
 | 
					<div class="signup">
 | 
				
			||||||
	<h1>Misskeyをはじめる</h1>
 | 
						<h1>Misskeyをはじめる</h1>
 | 
				
			||||||
	<p>いつでも、どこからでもMisskeyを利用できます。もちろん、無料です。</p>
 | 
					 | 
				
			||||||
	<div class="form">
 | 
					 | 
				
			||||||
		<p>新規登録</p>
 | 
					 | 
				
			||||||
		<div>
 | 
					 | 
				
			||||||
	<mk-signup/>
 | 
						<mk-signup/>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
import Vue from 'vue';
 | 
					import Vue from 'vue';
 | 
				
			||||||
export default Vue.extend({
 | 
					export default Vue.extend({});
 | 
				
			||||||
	mounted() {
 | 
					 | 
				
			||||||
		document.documentElement.style.background = '#293946';
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style lang="stylus" scoped>
 | 
					<style lang="stylus" scoped>
 | 
				
			||||||
.signup
 | 
					.signup
 | 
				
			||||||
	padding 16px
 | 
						padding 32px
 | 
				
			||||||
	margin 0 auto
 | 
						margin 0 auto
 | 
				
			||||||
	max-width 500px
 | 
						max-width 500px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	h1
 | 
						h1
 | 
				
			||||||
		margin 0
 | 
							margin 0
 | 
				
			||||||
		padding 8px
 | 
							padding 8px 0 0 0
 | 
				
			||||||
		font-size 1.5em
 | 
							font-size 1.5em
 | 
				
			||||||
		font-weight normal
 | 
							font-weight bold
 | 
				
			||||||
		color #c3c6ca
 | 
							color #444
 | 
				
			||||||
 | 
					 | 
				
			||||||
		& + p
 | 
					 | 
				
			||||||
			margin 0 0 16px 0
 | 
					 | 
				
			||||||
			padding 0 8px 0 8px
 | 
					 | 
				
			||||||
			color #949fa9
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	.form
 | 
					 | 
				
			||||||
		background #fff
 | 
					 | 
				
			||||||
		border solid 1px rgba(#000, 0.2)
 | 
					 | 
				
			||||||
		border-radius 8px
 | 
					 | 
				
			||||||
		overflow hidden
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		> p
 | 
					 | 
				
			||||||
			margin 0
 | 
					 | 
				
			||||||
			padding 12px 20px
 | 
					 | 
				
			||||||
			color #555
 | 
					 | 
				
			||||||
			background #f5f5f5
 | 
					 | 
				
			||||||
			border-bottom solid 1px #ddd
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		> div
 | 
					 | 
				
			||||||
			padding 16px
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,29 +1,31 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div class="welcome">
 | 
					<div class="welcome">
 | 
				
			||||||
	<div>
 | 
						<div>
 | 
				
			||||||
		<h1><b>Misskey</b>へようこそ</h1>
 | 
							<img :src="$store.state.device.darkmode ? 'assets/title.dark.svg' : 'assets/title.light.svg'" alt="Misskey">
 | 
				
			||||||
		<p>Twitter風ミニブログSNS、Misskeyへようこそ。共有したいことを投稿したり、タイムラインでみんなの投稿を読むこともできます。<br><a href="/signup">アカウントを作成する</a></p>
 | 
							<p class="host">{{ host }}</p>
 | 
				
			||||||
		<div class="form">
 | 
							<div class="about">
 | 
				
			||||||
			<p>%fa:lock% ログイン</p>
 | 
								<h2>{{ name || 'unidentified' }}</h2>
 | 
				
			||||||
			<div>
 | 
								<p v-html="description || '%i18n:common.about%'"></p>
 | 
				
			||||||
 | 
								<router-link class="signup" to="/signup">新規登録</router-link>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<div class="login">
 | 
				
			||||||
			<form @submit.prevent="onSubmit">
 | 
								<form @submit.prevent="onSubmit">
 | 
				
			||||||
					<input v-model="username" type="text" pattern="^[a-zA-Z0-9_]+$" placeholder="ユーザー名" autofocus required @change="onUsernameChange"/>
 | 
									<ui-input v-model="username" type="text" pattern="^[a-zA-Z0-9_]+$" autofocus required @change="onUsernameChange">
 | 
				
			||||||
					<input v-model="password" type="password" placeholder="パスワード" required/>
 | 
										<span>ユーザー名</span>
 | 
				
			||||||
					<input v-if="user && user.twoFactorEnabled" v-model="token" type="number" placeholder="トークン" required/>
 | 
										<span slot="prefix">@</span>
 | 
				
			||||||
					<button type="submit" :disabled="signing">{{ signing ? 'ログインしています' : 'ログイン' }}</button>
 | 
										<span slot="suffix">@{{ host }}</span>
 | 
				
			||||||
 | 
									</ui-input>
 | 
				
			||||||
 | 
									<ui-input v-model="password" type="password" required>
 | 
				
			||||||
 | 
										<span>パスワード</span>
 | 
				
			||||||
 | 
										<span slot="prefix">%fa:lock%</span>
 | 
				
			||||||
 | 
									</ui-input>
 | 
				
			||||||
 | 
									<ui-input v-if="user && user.twoFactorEnabled" v-model="token" type="number" required/>
 | 
				
			||||||
 | 
									<ui-button type="submit" :disabled="signing">{{ signing ? 'ログインしています' : 'ログイン' }}</ui-button>
 | 
				
			||||||
			</form>
 | 
								</form>
 | 
				
			||||||
			<div>
 | 
								<div>
 | 
				
			||||||
				<a :href="`${apiUrl}/signin/twitter`">Twitterでログイン</a>
 | 
									<a :href="`${apiUrl}/signin/twitter`">Twitterでログイン</a>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
		<div class="tl">
 | 
					 | 
				
			||||||
			<p>%fa:comments R% タイムラインを見てみる</p>
 | 
					 | 
				
			||||||
			<mk-welcome-timeline/>
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
		<div class="users">
 | 
					 | 
				
			||||||
			<mk-avatar class="avatar" v-for="user in users" :key="user.id" :user="user"/>
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
		<footer>
 | 
							<footer>
 | 
				
			||||||
			<small>{{ copyright }}</small>
 | 
								<small>{{ copyright }}</small>
 | 
				
			||||||
		</footer>
 | 
							</footer>
 | 
				
			||||||
| 
						 | 
					@ -33,7 +35,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
import Vue from 'vue';
 | 
					import Vue from 'vue';
 | 
				
			||||||
import { apiUrl, copyright } from '../../../config';
 | 
					import { apiUrl, copyright, host, name, description } from '../../../config';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default Vue.extend({
 | 
					export default Vue.extend({
 | 
				
			||||||
	data() {
 | 
						data() {
 | 
				
			||||||
| 
						 | 
					@ -45,7 +47,10 @@ export default Vue.extend({
 | 
				
			||||||
			token: '',
 | 
								token: '',
 | 
				
			||||||
			apiUrl,
 | 
								apiUrl,
 | 
				
			||||||
			copyright,
 | 
								copyright,
 | 
				
			||||||
			users: []
 | 
								users: [],
 | 
				
			||||||
 | 
								host,
 | 
				
			||||||
 | 
								name,
 | 
				
			||||||
 | 
								description
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	mounted() {
 | 
						mounted() {
 | 
				
			||||||
| 
						 | 
					@ -84,56 +89,49 @@ export default Vue.extend({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style lang="stylus" scoped>
 | 
					<style lang="stylus" scoped>
 | 
				
			||||||
.welcome
 | 
					.welcome
 | 
				
			||||||
	background linear-gradient(to bottom, #1e1d65, #bd6659)
 | 
						text-align center
 | 
				
			||||||
 | 
						//background #fff
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> div
 | 
						> div
 | 
				
			||||||
		padding 16px
 | 
							padding 32px
 | 
				
			||||||
		margin 0 auto
 | 
							margin 0 auto
 | 
				
			||||||
		max-width 500px
 | 
							max-width 500px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		h1
 | 
							> img
 | 
				
			||||||
			margin 0
 | 
								display block
 | 
				
			||||||
			padding 8px
 | 
								max-width 200px
 | 
				
			||||||
			font-size 1.5em
 | 
								margin 0 auto
 | 
				
			||||||
			font-weight normal
 | 
					 | 
				
			||||||
			color #cacac3
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			& + p
 | 
							> .host
 | 
				
			||||||
				margin 0 0 16px 0
 | 
								display block
 | 
				
			||||||
				padding 0 8px 0 8px
 | 
								text-align center
 | 
				
			||||||
				color #949fa9
 | 
								padding 6px 12px
 | 
				
			||||||
 | 
								line-height 32px
 | 
				
			||||||
 | 
								font-weight bold
 | 
				
			||||||
 | 
								color #333
 | 
				
			||||||
 | 
								background rgba(#000, 0.035)
 | 
				
			||||||
 | 
								border-radius 6px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		.form
 | 
							> .about
 | 
				
			||||||
			margin-bottom 16px
 | 
								margin-top 16px
 | 
				
			||||||
 | 
								padding 16px
 | 
				
			||||||
 | 
								color #555
 | 
				
			||||||
			background #fff
 | 
								background #fff
 | 
				
			||||||
			border solid 1px rgba(#000, 0.2)
 | 
								border-radius 6px
 | 
				
			||||||
			border-radius 8px
 | 
					
 | 
				
			||||||
			overflow hidden
 | 
								> h2
 | 
				
			||||||
 | 
									margin 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			> p
 | 
								> p
 | 
				
			||||||
				margin 0
 | 
									margin 8px
 | 
				
			||||||
				padding 12px 20px
 | 
					 | 
				
			||||||
				color #555
 | 
					 | 
				
			||||||
				background #f5f5f5
 | 
					 | 
				
			||||||
				border-bottom solid 1px #ddd
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			> div
 | 
								> .signup
 | 
				
			||||||
 | 
									font-weight bold
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> .login
 | 
				
			||||||
 | 
								margin 16px 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			> form
 | 
								> form
 | 
				
			||||||
					padding 16px
 | 
					 | 
				
			||||||
					border-bottom solid 1px #ddd
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					input
 | 
					 | 
				
			||||||
						display block
 | 
					 | 
				
			||||||
						padding 12px
 | 
					 | 
				
			||||||
						margin 0 0 16px 0
 | 
					 | 
				
			||||||
						width 100%
 | 
					 | 
				
			||||||
						font-size 1em
 | 
					 | 
				
			||||||
						color rgba(#000, 0.7)
 | 
					 | 
				
			||||||
						background #fff
 | 
					 | 
				
			||||||
						outline none
 | 
					 | 
				
			||||||
						border solid 1px #ddd
 | 
					 | 
				
			||||||
						border-radius 4px
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				button
 | 
									button
 | 
				
			||||||
					display block
 | 
										display block
 | 
				
			||||||
| 
						 | 
					@ -156,40 +154,9 @@ export default Vue.extend({
 | 
				
			||||||
						border-color #444
 | 
											border-color #444
 | 
				
			||||||
						box-shadow 0 1px 3px rgba(#000, 0.075), inset 0 0 5px rgba(#000, 0.2)
 | 
											box-shadow 0 1px 3px rgba(#000, 0.075), inset 0 0 5px rgba(#000, 0.2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				> div
 | 
					 | 
				
			||||||
					padding 16px
 | 
					 | 
				
			||||||
					text-align center
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		> .tl
 | 
					 | 
				
			||||||
			background #fff
 | 
					 | 
				
			||||||
			border solid 1px rgba(#000, 0.2)
 | 
					 | 
				
			||||||
			border-radius 8px
 | 
					 | 
				
			||||||
			overflow hidden
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			> p
 | 
					 | 
				
			||||||
				margin 0
 | 
					 | 
				
			||||||
				padding 12px 20px
 | 
					 | 
				
			||||||
				color #555
 | 
					 | 
				
			||||||
				background #f5f5f5
 | 
					 | 
				
			||||||
				border-bottom solid 1px #ddd
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			> .mk-welcome-timeline
 | 
					 | 
				
			||||||
				max-height 300px
 | 
					 | 
				
			||||||
				overflow auto
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		> .users
 | 
					 | 
				
			||||||
			margin 12px 0 0 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			> *
 | 
					 | 
				
			||||||
				display inline-block
 | 
					 | 
				
			||||||
				margin 4px
 | 
					 | 
				
			||||||
				width 38px
 | 
					 | 
				
			||||||
				height 38px
 | 
					 | 
				
			||||||
				border-radius 6px
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		> footer
 | 
							> footer
 | 
				
			||||||
			text-align center
 | 
								text-align center
 | 
				
			||||||
			color #fff
 | 
								color #444
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			> small
 | 
								> small
 | 
				
			||||||
				display block
 | 
									display block
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,7 +56,7 @@ export default define({
 | 
				
			||||||
	left 92px
 | 
						left 92px
 | 
				
			||||||
	margin 0
 | 
						margin 0
 | 
				
			||||||
	line-height 100px
 | 
						line-height 100px
 | 
				
			||||||
	color #fff !important // !important is for md
 | 
						color #fff
 | 
				
			||||||
	font-weight bold
 | 
						font-weight bold
 | 
				
			||||||
	text-shadow 0 0 8px rgba(#000, 0.5)
 | 
						text-shadow 0 0 8px rgba(#000, 0.5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,13 +0,0 @@
 | 
				
			||||||
/* SEE: https://vuematerial.io/themes/configuration */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@import '../const.json';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@import "~vue-material/dist/theme/engine";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@include md-register-theme("default", (
 | 
					 | 
				
			||||||
	primary: $themeColor,
 | 
					 | 
				
			||||||
	accent: $themeColor
 | 
					 | 
				
			||||||
));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@import "~vue-material/dist/components/MdButton/theme";
 | 
					 | 
				
			||||||
@import "~vue-material/dist/components/MdField/theme";
 | 
					 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,8 @@ export type Source = {
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		url: string;
 | 
							url: string;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
						name?: string;
 | 
				
			||||||
 | 
						description?: string;
 | 
				
			||||||
	url: string;
 | 
						url: string;
 | 
				
			||||||
	port: number;
 | 
						port: number;
 | 
				
			||||||
	https?: { [x: string]: string };
 | 
						https?: { [x: string]: string };
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,6 +79,8 @@ const consts = {
 | 
				
			||||||
	_DEV_URL_: config.dev_url,
 | 
						_DEV_URL_: config.dev_url,
 | 
				
			||||||
	_LANG_: '%lang%',
 | 
						_LANG_: '%lang%',
 | 
				
			||||||
	_LANGS_: Object.keys(locales).map(l => [l, locales[l].meta.lang]),
 | 
						_LANGS_: Object.keys(locales).map(l => [l, locales[l].meta.lang]),
 | 
				
			||||||
 | 
						_NAME_: config.name,
 | 
				
			||||||
 | 
						_DESCRIPTION_: config.description,
 | 
				
			||||||
	_HOST_: config.host,
 | 
						_HOST_: config.host,
 | 
				
			||||||
	_HOSTNAME_: config.hostname,
 | 
						_HOSTNAME_: config.hostname,
 | 
				
			||||||
	_URL_: config.url,
 | 
						_URL_: config.url,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue