mirror of
https://github.com/directus/directus.git
synced 2026-02-19 10:14:33 -05:00
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:
@@ -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();
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 don’t 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})`
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
export type ProjectArt = {
|
||||
color: string;
|
||||
background_image: string | null;
|
||||
foreground_image: string | null;
|
||||
note: string | null;
|
||||
};
|
||||
Reference in New Issue
Block a user