Add base public view (#39)

* Fix build error in TS in test

* Use public view in debug

* Render project background in art

* Add wide prop

* Fix TS errors

* Cleanup background styles + add tests

* Add minimal readme
This commit is contained in:
Rijk van Zanten
2020-02-14 14:23:55 -05:00
committed by GitHub
parent 8dad53e41c
commit 7cd1de564a
8 changed files with 169 additions and 45 deletions

View File

@@ -1,4 +1,4 @@
import { mount, createLocalVue, Wrapper } from '@vue/test-utils';
import { mount, createLocalVue } from '@vue/test-utils';
import VueCompositionAPI from '@vue/composition-api';
const localVue = createLocalVue();

View File

@@ -7,7 +7,12 @@
<script lang="ts">
import { createComponent, computed } from '@vue/composition-api';
export default createComponent({});
export default createComponent({
props: {},
setup() {
return {};
}
});
</script>
<style lang="scss" scoped>

View File

@@ -1,9 +1,20 @@
<template>
<div>Debug</div>
<public-view>
Hello!
</public-view>
</template>
<script lang="ts">
import { createComponent } from '@vue/composition-api';
import PublicView from '@/views/public/';
export default createComponent({});
export default createComponent({
components: {
PublicView
},
props: {},
setup() {
return {};
}
});
</script>

View File

@@ -2,7 +2,7 @@
z-index: 10000;
display: block !important;
background: var(--tooltip-background-color);
border-radius: var(--border-radius);
border-radius: 3px;
& .tooltip-inner {
padding: 5px 10px 6px;

View File

@@ -0,0 +1,18 @@
# Public View
## Props
| Prop | Description | Default |
|--------|---------------------------------------------------|---------|
| `wide` | Renders the container area with a wider max width | `false` |
## Events
n/a
## Slots
| Slot | Description | Data |
|-----------|----------------------------------------------------|------|
| _default_ | | -- |
| `notice` | Notice after all the content. Sticks to the bottom | -- |
## CSS Variables
n/a

View File

@@ -1,7 +1,8 @@
import VueCompositionAPI from '@vue/composition-api';
import { mount, createLocalVue } from '@vue/test-utils';
import { mount, createLocalVue, Wrapper } from '@vue/test-utils';
import { VTooltip } from 'v-tooltip';
import VIcon from '@/components/v-icon/';
import { useProjectsStore, ProjectWithKey } from '@/stores/projects';
const localVue = createLocalVue();
localVue.use(VueCompositionAPI);
@@ -10,8 +11,100 @@ localVue.component('v-icon', VIcon);
import PublicView from './public-view.vue';
const mockProject: ProjectWithKey = {
key: 'my-project',
api: {
version: '8.5.5',
requires2FA: false,
database: 'mysql',
project_name: 'Thumper',
project_logo: {
full_url:
'http://localhost:8080/uploads/my-project/originals/19acff06-4969-5c75-9cd5-dc3f27506de2.svg',
url: '/uploads/my-project/originals/19acff06-4969-5c75-9cd5-dc3f27506de2.svg'
},
project_color: '#4CAF50',
project_foreground: {
full_url:
'http://localhost:8080/uploads/my-project/originals/f28c49b0-2b4f-571e-bf62-593107cbf2ec.svg',
url: '/uploads/my-project/originals/f28c49b0-2b4f-571e-bf62-593107cbf2ec.svg'
},
project_background: {
full_url:
'http://localhost:8080/uploads/my-project/originals/03a06753-6794-4b9a-803b-3e1cd15e0742.jpg',
url: '/uploads/my-project/originals/03a06753-6794-4b9a-803b-3e1cd15e0742.jpg'
},
telemetry: true,
default_locale: 'en-US',
project_public_note:
'**Welcome to the Directus Public Demo!**\n\nYou can sign in with `admin@example.com` and `password`. Occasionally users break things, but dont worry… the whole server resets each hour.'
},
server: {
max_upload_size: 104857600,
general: {
php_version: '7.2.22-1+0~20190902.26+debian9~1.gbpd64eb7',
php_api: 'fpm-fcgi'
}
}
};
describe('Views / Public', () => {
it('Works', () => {
const component = mount(PublicView, { localVue });
let store = useProjectsStore({});
let component: Wrapper<Vue>;
beforeEach(() => {
store.reset();
component = mount(PublicView, { localVue });
});
describe('Background', () => {
it('Defaults background art to color when current project key is unknown', () => {
expect((component.vm as any).artStyles).toEqual({
background: '#263238'
});
});
it('Uses the project color when the current project key is set, but background image is not', () => {
store.state.projects = [
{
...mockProject,
api: {
...mockProject.api,
project_background: null
}
}
];
store.state.currentProjectKey = 'my-project';
expect((component.vm as any).artStyles).toEqual({
background: '#4CAF50'
});
});
it('Uses the default background color when the current project has an error', () => {
store.state.projects = [
{
key: 'my-project',
status: 500,
error: {
code: 250,
message: 'Test error'
}
}
];
store.state.currentProjectKey = 'my-project';
expect((component.vm as any).artStyles).toEqual({
background: '#263238'
});
});
it('Uses the background image when the project has one set', () => {
store.state.projects = [mockProject];
store.state.currentProjectKey = 'my-project';
expect((component.vm as any).artStyles).toEqual({
background: `url(${mockProject.api.project_background?.full_url})`
});
});
});
});

View File

@@ -2,14 +2,11 @@
<div class="public-view">
<div class="container">
<public-view-logo :version="version" />
<div class="content">
<div class="content" :class="{ wide }">
<slot />
</div>
<div class="notice">
<slot name="notice">
<v-icon name="person" />
Not Authenticated
</slot>
<slot name="notice" />
</div>
</div>
<div class="art" :style="artStyles"></div>
@@ -19,48 +16,46 @@
<script lang="ts">
import { version } from '../../../package.json';
import { createComponent, computed } from '@vue/composition-api';
import { ProjectArt } from './types';
import PublicViewLogo from './_logo.vue';
import { useProjectsStore, ProjectWithKey, ProjectError } from '@/stores/projects';
const defaultProjectArt: ProjectArt = {
color: '#263238',
background_image: null,
foreground_image: null,
note: null
};
export default createComponent({
components: {
PublicViewLogo
},
props: {
wide: {
type: Boolean,
default: false
}
},
setup() {
const projectsStore = useProjectsStore();
const projectArt = computed<ProjectArt>(() => {
const { currentProject } = projectsStore;
const backgroundStyles = computed<string>(() => {
const defaultColor = '#263238';
if (
currentProject.value === null ||
(currentProject.value as ProjectError).error !== undefined
) {
return defaultProjectArt;
let currentProject = projectsStore.currentProject.value;
if (currentProject === null) {
return defaultColor;
}
const project = currentProject.value as ProjectWithKey;
if ((currentProject as ProjectError).error !== undefined) {
return defaultColor;
}
return {
color: project.api.project_color,
background_image:
project.api.project_background?.full_url || defaultProjectArt.background_image,
foreground_image:
project.api.project_foreground?.full_url || defaultProjectArt.foreground_image,
note: project.api.project_public_note || null
};
currentProject = currentProject as ProjectWithKey;
if (currentProject.api.project_background?.full_url) {
return `url(${currentProject.api.project_background.full_url})`;
}
return currentProject.api.project_color;
});
const artStyles = computed(() => ({
background: projectArt.value.background_image || projectArt.value.color
background: backgroundStyles.value
}));
return { version, artStyles };
@@ -86,9 +81,13 @@ export default createComponent({
padding: 20px;
overflow-x: hidden;
overflow-y: auto;
background-color: var(--page-background-color);
background-color: var(--background-color);
box-shadow: 0 0 40px 0 rgba(0, 0, 0, 0.25);
&.wide {
max-width: 872px;
}
@include breakpoint(small) {
padding: 40px 80px;
}
@@ -103,5 +102,9 @@ export default createComponent({
display: block;
}
}
.notice {
color: var(--foreground-color-secondary);
}
}
</style>

View File

@@ -1,6 +0,0 @@
export type ProjectArt = {
color: string;
background_image: string | null;
foreground_image: string | null;
note: string | null;
};