Update login page

This commit is contained in:
philipp lang 2021-04-10 19:45:11 +02:00
parent 58291d9d0e
commit 504238844b
15 changed files with 24330 additions and 5402 deletions

28717
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,31 +10,21 @@
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
}, },
"devDependencies": { "devDependencies": {
"axios": "^0.19", "laravel-mix": "^6.0.1",
"bootstrap": "^4.0.0", "lodash": "^4.17.21",
"cross-env": "^7.0", "vue": "^2.6.12",
"jquery": "^3.2", "vue-loader": "^15.9.6",
"laravel-mix": "^5.0.1", "vue-template-compiler": "^2.6.12"
"lodash": "^4.17.13",
"popper.js": "^1.12",
"resolve-url-loader": "^2.3.1",
"sass": "^1.20.1",
"sass-loader": "^8.0.0",
"vue": "^2.6.11",
"vue-template-compiler": "^2.6.10"
}, },
"dependencies": { "dependencies": {
"@inertiajs/inertia": "^0.1.7", "@inertiajs/inertia": "^0.8.6",
"@inertiajs/inertia-vue": "^0.1.2", "@inertiajs/inertia-vue": "^0.5.10",
"agnoster": "file:resources/js/libs/agnoster", "agnoster": "file:resources/js/libs/agnoster",
"font-awesome": "^4.7.0",
"js-modules": "file:resources/js/libs/js-modules", "js-modules": "file:resources/js/libs/js-modules",
"laravel-echo": "^1.7.0", "laravel-echo": "^1.10.0",
"postcss-import": "^12.0.1", "postcss-import": "^14.0.1",
"query-string": "^6.12.1", "query-string": "^7.0.0",
"socket.io-client": "^2.3.0", "socket.io-client": "^4.0.1",
"tailwindcss": "^1.2.0", "tailwindcss": "^2.1.1"
"vue-inputmask": "^0.2.1",
"vuex": "^3.1.3"
} }
} }

View File

@ -1,4 +1,5 @@
{ {
"/js/app.js": "/js/app.js", "/js/app.js": "/js/app.js",
"/img/dpsg.gif": "/img/dpsg.gif",
"/css/app.css": "/css/app.css" "/css/app.css": "/css/app.css"
} }

View File

@ -4,79 +4,79 @@
} }
.form-group { .form-group {
@apply .mb-4; @apply mb-4;
} }
.label-font {
@apply .form-control-font;
}
.form-control-font { .form-control-font {
@apply .leading-tight .text-gray-600 .text-sm; @apply leading-tight text-gray-600 text-sm;
} }
.label-placeholder { .label-placeholder {
position: relative; position: relative;
@apply .py-2 .cursor-text; @apply py-2 cursor-text;
top: 34px; top: 34px;
transition: color 0.2s, padding-bottom 0.2s, font-size 0.2s, top 0.2s; transition: color 02s, padding-bottom 02s, font-size 02s, top 02s;
} }
.field-wrapper.focused .label-placeholder, .label-placeholder-focused { .field-wrapperfocused label-placeholder, label-placeholder-focused {
top: 0; top: 0;
@apply .text-sm .text-gray-600; @apply text-sm text-gray-600;
padding-bottom: 10px; padding-bottom: 10px;
transition: color 0.2s, padding-bottom 0.2s, font-size 0.2s, top 0.2s; transition: color 02s, padding-bottom 02s, font-size 02s, top 02s;
} }
.form-control { .form-control {
@apply .py-2 .appearance-none .border-b .border-solid .form-control-font; @apply py-2 appearance-none border-b border-solid form-control-font;
-moz-appearance: none; -moz-appearance: none;
} }
.label-font {
@apply form-control-font;
}
.btn { .btn {
@apply .px-3 .py-2 .uppercase .no-underline .text-sm .rounded .text-white; @apply px-3 py-2 uppercase no-underline text-sm rounded text-white;
} }
.btn-sm { .btn-sm {
@apply .text-xs !important; @apply text-xs !important;
} }
.btn.p-0 { .btnp-0 {
padding: 0 !important; padding: 0 !important;
} }
.btn-primary { .btn-primary {
@apply .bg-primary; @apply bg-primary;
} }
.btn-primary:hover { .btn-primary:hover {
@apply .bg-primary-light; @apply bg-primary-light;
} }
.btn-danger { .btn-danger {
@apply .bg-danger; @apply bg-danger;
} }
.btn-danger:hover { .btn-danger:hover {
@apply .bg-danger-light; @apply bg-danger-light;
} }
.btn-default { .btn-default {
@apply .bg-gray-600; @apply bg-gray-600;
} }
.btn-primary-light { .btn-primary-light {
@apply .bg-primary-light; @apply bg-primary-light;
} }
.btn-default:hover { .btn-default:hover {
@apply .bg-gray-600; @apply bg-gray-600;
} }
.field-wrapper { .field-wrapper {
@apply .flex .flex-col; @apply flex flex-col;
} }
.toolbar-title { .toolbar-title {
@apply .font-bold .text-gray-700 .text-lg; @apply font-bold text-gray-700 text-lg;
} }
.subtitle { .subtitle {
@apply .subtitle .text-xl .font-semibold .mt-6 .font-thin .uppercase .text-gray-600; @apply text-xl font-semibold mt-6 font-thin uppercase text-gray-600;
} }
.mainnav > div > a { .mainnav > div > a {
@apply .py-2; @apply py-2;
} }

34
resources/js/app.js vendored
View File

@ -1,30 +1,22 @@
import Vue from 'vue'; import Vue from 'vue';
import { modules, init } from 'agnoster'; import { App, plugin } from '@inertiajs/inertia-vue'
import { Checkbox } from 'js-modules';
import { InertiaApp } from '@inertiajs/inertia-vue'
import store from './store.js';
import 'font-awesome/css/font-awesome.css'; import 'font-awesome/css/font-awesome.css';
import Echo from 'laravel-echo'; import Echo from 'laravel-echo';
window.io = require('socket.io-client'); window.io = require('socket.io-client');
Vue.use(modules); import FText from './components/FText.vue';
Vue.use(init);
Vue.use(InertiaApp);
Vue.component('checkbox', Checkbox);
const app = document.getElementById('app') Vue.use(plugin)
Vue.component('f-text', FText);
window.Echo = new Echo({ const el = document.getElementById('app')
broadcaster: 'socket.io',
host: window.location.hostname+':'+document.querySelector('meta[name=socketport]').getAttribute('content'),
});
new Vue({ new Vue({
render: h => h(InertiaApp, { render: h => h(App, {
props: { props: {
initialPage: JSON.parse(app.dataset.page), initialPage: JSON.parse(el.dataset.page),
resolveComponent: name => require(`./views/${name}`).default, resolveComponent: name => require(`./views/${name}`).default,
}, },
}), }),
store }).$mount(el);
}).$mount(app)

View File

@ -0,0 +1,137 @@
<template>
<label class="flex flex-col relative field-checkbox cursor-pointer" :for="id" :class="{[`size-${size}`]: true}">
<span v-if="label && inset" class="z-10 absolute top-0 left-0 -mt-2 px-1 ml-3 inset-bg font-semibold text-gray-700">{{ label }}</span>
<div class="relative flex items-start">
<input :id="id" type="checkbox" v-model="v" :disabled="disabled" class="invisible absolute" />
<span class="display-wrapper flex items-center">
<span class="relative cursor-pointer flex flex-none justify-center items-center display" :class="{'bg-terminoto-2': v === true, 'bg-white': v === false}">
<sprite src="check" class="w-4 h-4 check-icon text-white"></sprite>
</span>
</span>
<span v-if="label && !inset" class="text-sm leading-tight ml-3 text-gray-700 checkbox-label flex items-center">
<span>
<span v-text="label" v-if="!html"></span>
<span v-html="label" v-if="html"></span>
<span v-show="required" class="font-semibold text-red-700">*</span>
</span>
</span>
</div>
</label>
</template>
<script>
export default {
model: {
prop: 'items',
event: 'input'
},
props: {
html: {
type: Boolean,
default: false
},
required: {
type: Boolean,
default: false
},
inset: {
type: Boolean,
default: false
},
size: {
default: null,
required: false
},
id: {
required: true
},
disabled: {
type: Boolean,
default: false
},
value: {
default: false
},
label: {
default: false
},
items: {
default: undefined
},
size: {
default: null,
type: String
}
},
computed: {
v: {
set(v) {
if (this.disabled === true) {
return;
}
if (typeof this.items === 'boolean') {
this.$emit('input', v);
return;
}
var a = this.items.filter(i => i !== this.value);
if (v) {
a.push(this.value);
}
this.$emit('input', a);
},
get() {
if (typeof this.items === 'boolean') {
return this.items;
}
if (typeof this.items === 'undefined') {
return this.$emit('input', false);
}
return this.items.indexOf(this.value) !== -1;
}
}
},
created() {
if (typeof this.items === 'undefined') {
this.$emit('input', false);
}
}
};
</script>
<style lang="css">
:root {
--checkbox-width: 30px;
--margin: 0.2rem;
}
.field-checkbox {
input:checked + span {
transition: background 0.2s;
}
.display-wrapper, .checkbox-label {
min-height: 34px;
}
.display {
width: var(--checkbox-width);
height: var(--checkbox-width);
border-radius: 0.3rem;
border: solid 2px hsl(60.0, 1.8%, 10.8%);
.check-icon {
opacity: 0;
transition: opacity 0.2s;
}
}
input:checked + .display-wrapper .display .check-icon {
opacity: 1;
transition: opacity 0.2s;
}
}
</style>

View File

@ -0,0 +1,112 @@
<template>
<label class="flex flex-col relative" :for="id" :class="{['h-field-'+size]: inset === true}">
<div class="relative h-full flex flex-col">
<span v-if="label && !inset" class="font-semibold relative z-10 text-gray-700" :class="{
'text-xs': size == 'sm',
'text-sm': size === null
}">{{ label }}<span v-show="required" class="text-red-800">&nbsp;*</span></span>
<span v-if="label && inset" class="absolute z-10 top-0 left-0 -mt-2 px-1 ml-3 inset-bg font-semibold text-gray-700" :class="{
'text-xs': size == 'sm',
'text-sm': size === null
}" v-text="label"></span>
<div class="relative h-full" :class="{['h-field-'+size]: inset === false}">
<select :value="value" @change="trigger"
class="border-gray-400 border-solid bg-white w-full appearance-none outline-none h-full"
:class="{
'rounded-lg text-sm border-2 p-2 text-gray-800': size === null,
'rounded-lg py-2 px-2 text-xs border-2 text-gray-800': size == 'sm'
}"
>
<option v-if="placeholder" v-html="placeholder" :value="null"></option>
<option v-for="(option, key) in parsedOptions" :key="key"
v-html="option" :value="key"
></option>
</select>
<div class="absolute pointer-events-none top-0 right-0 -mx-1 flex items-center h-full mr-4 cursor-pointer">
<div v-if="hint" v-tooltip="hint" class="px-1">
<sprite src="info-button" class="w-5 h-5 text-indigo-200"></sprite>
</div>
<div class="px-1 relative">
<sprite class="w-3 h-3 fill-current" src="chevron-down"></sprite>
</div>
</div>
</div>
</div>
</label>
</template>
<script>
export default {
props: {
id: {},
inset: {
type: Boolean,
default: false
},
size: {
default: function() { return null; }
},
emptyLabel: {
default: false,
type: Boolean
},
value: {
default: undefined
},
label: {
default: null
},
required: {
type: Boolean,
default: false
},
placeholder: {
default: '--kein--',
type: String
},
def: {
required: false,
type: Number,
default: -1
},
hint: {},
options: {
default: function() { return []; }
}
},
computed: {
parsedOptions() {
return this.options;
}
},
methods: {
trigger(v) {
this.$emit('input', isNaN(parseInt(v.target.value))
? (v.target.value ? v.target.value : null)
: parseInt(v.target.value)
);
},
clear() {
this.$emit('input', null);
}
},
mounted() {
if (this.def !== -1 && typeof this.value === 'undefined') {
this.$emit('input', this.def);
return;
}
if (this.placeholder && typeof this.value === 'undefined') {
this.$emit('input', null);
}
}
};
</script>
<style scope>
.inset-bg {
background: linear-gradient(to bottom, hsl(247.5, 66.7%, 97.6%) 0%, hsl(247.5, 66.7%, 97.6%) 41%, hsl(0deg 0% 100%) 41%, hsl(180deg 0% 100%) 100%);
}
</style>

View File

@ -0,0 +1,219 @@
<template>
<label class="flex flex-col relative field-switch cursor-pointer" :for="id" :class="{[`size-${outerSize}`]: true}">
<span v-if="label && !inset" class="font-semibold leading-none text-gray-700" :class="{
'text-xs': size == 'sm',
'text-sm': size === null
}">{{ label }}</span>
<span v-if="label && inset" class="z-10 absolute top-0 left-0 -mt-2 px-1 ml-3 inset-bg font-semibold text-gray-700" :class="{
'text-xs': size == 'sm',
'text-sm': size === null
}">{{ label }}</span>
<div class="relative inner-field" :class="`h-field-${fieldSize}`">
<input :id="id" type="checkbox" v-model="v" :disabled="disabled" class="invisible absolute" />
<span class="relative cursor-pointer flex flex-grow display" :class="{'bg-primary': v === true, 'bg-gray-400': v === false}">
<span><sprite class="relative text-white flex-none" :class="{'w-2 h-2': size === 'sm' || size == 'xs', 'w-6 h-6': size === null}" src="check"></sprite></span>
<span><sprite class="relative text-white flex-none" :class="{'w-2 h-2': size === 'sm' || size == 'xs', 'w-6 h-6': size === null}" src="close"></sprite></span>
<var class="absolute overlay bg-white rounded top-0"></var>
</span>
</div>
</label>
</template>
<script>
export default {
model: {
prop: 'items',
event: 'input'
},
props: {
inset: {
type: Boolean,
default: false
},
size: {
default: null,
required: false
},
id: {
required: true
},
disabled: {
type: Boolean,
default: false
},
value: {
default: false
},
label: {
default: false
},
items: {
default: undefined
},
size: {
default: null,
type: String
}
},
computed: {
v: {
set(v) {
if (this.disabled === true) {
return;
}
if (typeof this.items === 'boolean') {
this.$emit('input', v);
return;
}
var a = this.items.filter(i => i !== this.value);
if (v) {
a.push(this.value);
}
this.$emit('input', a);
},
get() {
if (typeof this.items === 'boolean') {
return this.items;
}
if (typeof this.items === 'undefined') {
return this.$emit('input', false);
}
return this.items.indexOf(this.value) !== -1;
}
},
fieldSize() {
var sizes = ['xxs', 'xs', 'sm', 'md', 'lg'];
var sizeIndex = sizes.findIndex(s => s === this.size);
return sizes[this.inset ? sizeIndex : sizeIndex - 1];
},
outerSize() {
var sizes = ['xxs', 'xs', 'sm', 'md', 'lg'];
var sizeIndex = sizes.findIndex(s => s === this.size);
if (!this.label || this.inset) { sizeIndex--; }
return sizes[sizeIndex];
}
}
};
</script>
<style lang="css">
:root {
--margin: 0.2rem;
--n-width: 2.5rem;
--sm-width: 35px;
--sm-margin: 0.2rem;
--xs-width: 23px;
--xs-margin: 0.2rem;
}
.field-switch {
input:checked + span {
transition: background 0.3s;
}
.display {
width: calc(var(--n-width) * 2);
height: var(--n-width);
border-radius: 0.3rem;
var {
width: calc(var(--n-width) - var(--margin) * 2);
height: calc(var(--n-width) - var(--margin) * 2);
top: var(--margin);
left: var(--margin);
transition: left 0.3s;
}
& > span:nth-of-type(1) {
position: absolute;
width: calc(var(--n-width) - var(--margin));
height: calc(var(--n-width) - var(--margin) * 2);
top: var(--margin);
left: var(--margin);
display: flex;
justify-content: center;
align-items: center;
}
& > span:nth-of-type(2) {
position: absolute;
width: calc(var(--n-width) - var(--margin));
height: calc(var(--n-width) - var(--margin) * 2);
top: var(--margin);
left: calc(100% - var(--n-width));
display: flex;
justify-content: center;
align-items: center;
}
}
input:checked + .display var {
left: calc(var(--n-width) + var(--margin));
transition: left 0.3s;
}
/* --------------------------------- small size ---------------------------------- */
.inner-field.h-field-sm {
input:checked + .display var {
left: calc(var(--sm-width) + var(--sm-margin));
}
.display {
width: calc(var(--sm-width) * 2);
height: var(--sm-width);
var {
width: calc(var(--sm-width) - var(--sm-margin) * 2);
height: calc(var(--sm-width) - var(--sm-margin) * 2);
top: var(--sm-margin);
left: var(--sm-margin);
}
& > span:nth-of-type(1) {
width: calc(var(--sm-width) - var(--sm-margin));
height: calc(var(--sm-width) - var(--sm-margin) * 2);
top: var(--sm-margin);
left: var(--sm-margin);
}
& > span:nth-of-type(2) {
width: calc(var(--sm-width) - var(--sm-margin));
height: calc(var(--sm-width) - var(--sm-margin) * 2);
top: var(--sm-margin);
left: calc(100% - var(--sm-width));
}
}
}
/* ------------------------------ very small size -------------------------------- */
.inner-field.h-field-xs {
input:checked + .display var {
left: calc(var(--xs-width) + var(--xs-margin));
}
.display {
width: calc(var(--xs-width) * 2);
height: var(--xs-width);
var {
width: calc(var(--xs-width) - var(--xs-margin) * 2);
height: calc(var(--xs-width) - var(--xs-margin) * 2);
top: var(--xs-margin);
left: var(--xs-margin);
}
& > span:nth-of-type(1) {
width: calc(var(--xs-width) - var(--xs-margin));
height: calc(var(--xs-width) - var(--xs-margin) * 2);
top: var(--xs-margin);
left: var(--xs-margin);
}
& > span:nth-of-type(2) {
width: calc(var(--xs-width) - var(--xs-margin));
height: calc(var(--xs-width) - var(--xs-margin) * 2);
top: var(--xs-margin);
left: calc(100% - var(--xs-width));
}
}
}
}
</style>

View File

@ -0,0 +1,245 @@
<template>
<label class="flex flex-col relative" :for="id" :class="{['h-field-'+size]: inset === true}">
<div class="relative h-full flex flex-col">
<span v-if="label && !inset" class="font-semibold relative z-10 text-gray-700" :class="{
'text-xs': size == 'sm',
'text-sm': size === null
}">{{ label }}<span v-show="required" class="text-red-800">&nbsp;*</span></span>
<span v-if="label && inset" class="absolute z-10 top-0 left-0 -mt-2 px-1 ml-3 inset-bg font-semibold text-gray-700" :class="{
'text-xs': size == 'sm',
'text-sm': size === null
}" v-text="label"></span>
<div class="relative h-full" :class="{['h-field-'+size]: inset === false}">
<input :type="type" :name="name" :value="transformedValue" @input="onInput" @change="onChange" :disabled="disabled" :placeholder="placeholder"
@focus="onFocus" @blur="onBlur"
class="border-gray-400 border-solid bg-white w-full appearance-none outline-none h-full"
:class="{
'rounded-lg text-sm border-2 p-2 text-gray-800': size === null,
'rounded-lg py-2 px-2 text-xs border-2 text-gray-800': size == 'sm'
}"
/>
<div class="absolute top-0 right-0 -mx-1 flex items-center h-full cursor-pointer">
<div v-if="hint" class="absolute top-0 right-0 h-full items-center mr-2 flex w-6" v-tooltip="hint">
<sprite src="info-button" class="w-5 h-5 text-indigo-200"></sprite>
</div>
</div>
</div>
</div>
</label>
</template>
<script>
import wNumb from 'wnumb';
var numb = {
natural: wNumb({
mark: ',',
thousand: '.',
decimals: 0,
decoder(a) {
return a * 100;
},
encoder(a) {
return a / 100;
}
}),
naturalRaw: wNumb({
mark: '',
thousand: '',
decimals: 0,
decoder(a) {
return a * 100;
},
encoder(a) {
return a / 100;
}
}),
area: wNumb({
mark: ',',
thousand: '.',
decimals: 2,
decoder(a) {
return a * 100;
},
encoder(a) {
return a / 100;
}
}),
twoDecimalRaw: wNumb({
mark: ',',
thousand: '',
decimals: 2,
decoder(a) {
return a * 100;
},
encoder(a) {
return a / 100;
}
})
};
var transformers = {
none: {
display: {
to(v) { return v; },
from(v) { return v; }
},
edit: {
to(v) { return v; },
from(v) { return v; }
}
},
natural: {
display: {
to(v) { return isNaN(parseInt(v)) ? '' : numb.natural.to(v); },
from(v) { return v === '' ? null : numb.natural.from(v); }
},
edit: {
to(v) { return isNaN(parseInt(v)) ? '' : numb.naturalRaw.to(v); },
from(v) { return v === '' ? null : numb.naturalRaw.from(v); }
}
},
area: {
display: {
to(v) { return v === null ? '' : numb.area.to(v); },
from(v) { return v === '' ? null : numb.area.from(v); }
},
edit: {
to(v) {
if (v === null) { return ''; }
if (Math.round(v / 100) * 100 === v) { return numb.naturalRaw.to(v); }
return numb.twoDecimalRaw.to(v);
},
from(v) {
if (v === '') { return null; }
if (v.indexOf(',') === -1) { return numb.naturalRaw.from(v); }
return numb.twoDecimalRaw.from(v);
}
}
},
currency: {
display: {
to(v) { return v === null ? '' : numb.area.to(v); },
from(v) { return v === '' ? null : numb.area.from(v); }
},
edit: {
to(v) {
if (v === null) { return ''; }
if (Math.round(v / 100) * 100 === v) { return numb.naturalRaw.to(v); }
return numb.twoDecimalRaw.to(v);
},
from(v) {
if (v === '') { return null; }
if (v.indexOf(',') === -1) { return numb.naturalRaw.from(v); }
return numb.twoDecimalRaw.from(v);
}
}
}
};
export default {
data: function() {
return {
focus: false
};
},
props: {
name: {
default: function() {
return '';
}
},
placeholder: {
default: function() {
return '';
}
},
default: {},
mode: {
default: function() { return 'none'; }
},
required: {
type: Boolean,
default: false
},
inset: {
default: function() {
return null;
}
},
size: {
default: null
},
id: {
required: true
},
hint: {
default: null
},
value: {
default: undefined
},
mask: {
default: undefined
},
label: {
default: false
},
type: {
required: false,
default: function() { return 'text'; }
},
disabled: {
default: false,
type: Boolean
}
},
methods: {
onFocus() {
this.focus = true;
},
onBlur() {
this.focus = false;
},
onChange(v) {
if (this.mode !== 'none') {
this.transformedValue = v.target.value;
}
},
onInput(v) {
if (this.mode === 'none') {
this.transformedValue = v.target.value;
}
}
},
computed: {
transformedValue: {
get() {
return transformers[this.mode][this.focus ? 'edit' : 'display'].to(this.value);
},
set(v) {
this.$emit('input', transformers[this.mode][this.focus ? 'edit' : 'display'].from(v));
}
},
insetClass() {
if (this.inset === '') { return 'bg-inset'; }
if (this.inset === undefined) { return null; }
return `bg-${this.inset}`;
}
},
created() {
if (typeof this.value === 'undefined') {
this.$emit('input', this.default === undefined ? '' : this.default);
}
}
};
</script>
<style scope>
.bg-inset {
background: linear-gradient(to bottom, hsl(247.5, 66.7%, 97.6%) 0%, hsl(247.5, 66.7%, 97.6%) 41%, hsl(0deg 0% 100%) 41%, hsl(180deg 0% 100%) 100%);
}
</style>

View File

@ -0,0 +1,88 @@
<template>
<label class="flex flex-col relative">
<span v-if="label && !inset" class="font-semibold text-gray-700" :class="{
'text-xs': size == 'sm',
'text-sm': size === null
}">{{ label }}<span v-show="required" class="text-red-800">&nbsp;*</span></span>
<span v-if="label && inset" class="absolute top-0 left-0 -mt-2 px-1 ml-3 inset-bg font-semibold text-gray-700" :class="{
'text-xs': size == 'sm',
'text-sm': size === null
}">{{ label }}<span v-show="required" class="text-red-800">&nbsp;*</span></span>
<textarea v-text="value" @input="trigger" :placeholder="placeholder"
class="h-full outline-none border-gray-400 border-solid" :rows="rows"
:class="{
'rounded-lg text-sm border-2 p-2 text-gray-800': size === null,
'rounded-lg py-2 px-2 text-xs border-2 text-gray-800': size == 'sm'
}"
></textarea>
<div v-if="hint" v-tooltip="hint" class="absolute right-0 top-0 mr-2 mt-2">
<sprite src="info-button" class="w-5 h-5 text-indigo-200"></sprite>
</div>
</label>
</template>
<script>
export default {
data: function() {
return {
focus: false
};
},
props: {
required: {
type: Boolean,
default: false
},
inset: {
default: false,
type: Boolean
},
size: {
default: null
},
rows: {
default: function() {
return 4;
}
},
id: {
required: true
},
hint: {
default: null
},
value: {
default: undefined
},
mask: {
default: undefined
},
label: {
default: false
},
type: {
required: false,
default: function() { return 'text'; }
},
placeholder: {
default: ''
}
},
methods: {
trigger(v) {
this.$emit('input', v.target.value);
}
},
created() {
if (typeof this.value === 'undefined') {
this.$emit('input', '');
}
}
};
</script>
<style scope>
.inset-bg {
background: linear-gradient(to bottom, hsl(247.5, 66.7%, 97.6%) 0%, hsl(247.5, 66.7%, 97.6%) 41%, hsl(0deg 0% 100%) 41%, hsl(180deg 0% 100%) 100%);
}
</style>

View File

@ -1,35 +1,12 @@
<template> <template>
<div class="app font-sans flex flex-col flex-grow"> <div class="font-sans flex flex-col flex-grow">
<notification :errors="$page.errors"></notification> <div>
<process></process> dfsfdsf
<wrapper </div>
admin-toolbar="adminToolbar"
profile-toolbar="profileToolbar"
search-background="bg-primary-600"
>
<template slot="mainnav">
<mainnav name="main" sm></mainnav>
</template>
<template slot="main">
<slot />
</template>
</wrapper>
</div> </div>
</template> </template>
<script> <script>
import Notification from 'agnoster/components/Notification.vue';
import Process from 'agnoster/components/Progress.vue';
import Wrapper from 'agnoster/components/Wrapper.vue';
import Mainnav from 'agnoster/components/Mainnav.vue';
export default { export default {
computed: {
title() {
return this.$store.getters.title;
}
},
components: { Notification, Wrapper, Mainnav, Process }
}; };
</script> </script>

View File

@ -1,26 +1,14 @@
<template> <template>
<div id="app" class="font-sans flex flex-col flex-grow"> <div id="app" class="bg-gray-200 font-sans flex flex-col flex-grow items-center justify-center">
<notification :errors="$page.errors"></notification> <div class="w-96 bg-white rounded-xl overflow-hidden shadow-lg">
<fullpage> <slot></slot>
<div slot="brand-icon" slot-scope="{ cls }" :class="cls" class="py-2 flex justify-between items-center w-full"> </div>
<span class="text-primary-200 text-lg">Login über NaMi</span>
<img src="img/dpsg.gif" class="w-24">
</div>
<slot />
</fullpage>
</div> </div>
</template> </template>
<script> <script>
import Notification from 'agnoster/components/Notification.vue';
import Fullpage from 'agnoster/components/Fullpage.vue';
export default { export default {
computed: { computed: {
title() { }
return this.$store.getters.title;
}
},
components: { Notification, Fullpage }
}; };
</script> </script>

View File

@ -1,22 +1,15 @@
<template> <template>
<form @submit.prevent="submit"> <form @submit.prevent="submit">
<grid fullsize> <div class="h-24 px-10 bg-primary flex justify-between items-center w-full">
<item> <span class="text-primary-200 text-lg">Login über NaMi</span>
<f-text label="Mitgliedsnummer" v-model="values.mglnr"></f-text> <img src="/img/dpsg.gif" class="w-24">
</item> </div>
<div class="p-10 grid gap-5">
<item> <f-text id="mglnr" label="Mitgliedsnummer" v-model="values.mglnr"></f-text>
<f-password label="Passwort" v-model="values.password"></f-password> <f-text id="password" type="password" label="Passwort" v-model="values.password"></f-text>
</item> <f-text id="groupid" name="groupid" label="Gruppierungsnummer" v-model="values.groupid"></f-text>
<button type="submit" class="btn btn-primary">Login</button>
<item> </div>
<f-text label="Gruppierungsnummer" v-model="values.groupid"></f-text>
</item>
<item>
<f-submit data-cy="submit" primary>Login</f-submit>
</item>
</grid>
</form> </form>
</template> </template>
@ -28,11 +21,7 @@ export default {
data: function() { data: function() {
return { return {
values: { values: {}
mglnr: 90166,
password: 'ibm0g',
groupid: 100105
}
}; };
}, },
methods: { methods: {

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html class="h-full">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
@ -7,7 +7,7 @@
<link href="{{ mix('/css/app.css') }}" rel="stylesheet" /> <link href="{{ mix('/css/app.css') }}" rel="stylesheet" />
<script src="{{ mix('/js/app.js') }}" defer></script> <script src="{{ mix('/js/app.js') }}" defer></script>
</head> </head>
<body> <body class="min-h-full flex flex-col">
@inertia @inertia
</body> </body>
</html> </html>

3
webpack.mix.js vendored
View File

@ -1,6 +1,7 @@
const mix = require('laravel-mix'); const mix = require('laravel-mix');
const tailwindcss = require('tailwindcss'); const tailwindcss = require('tailwindcss');
const atImport = require("postcss-import"); const atImport = require("postcss-import");
const nested = require('postcss-nested');
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@ -14,9 +15,11 @@ const atImport = require("postcss-import");
*/ */
mix.js('resources/js/app.js', 'public/js') mix.js('resources/js/app.js', 'public/js')
.vue({ version: 2 })
.postCss('resources/css/app.css', 'public/css', [ .postCss('resources/css/app.css', 'public/css', [
atImport(), atImport(),
tailwindcss('./tailwind.config.js'), tailwindcss('./tailwind.config.js'),
nested(),
]) ])
.copy('resources/img', 'public/img') .copy('resources/img', 'public/img')
.sourceMaps(); .sourceMaps();