Skip to content

Commit

Permalink
refactor to enable multi view
Browse files Browse the repository at this point in the history
  • Loading branch information
rouk1 committed Oct 1, 2024
1 parent d9b0b7d commit c2f164e
Show file tree
Hide file tree
Showing 28 changed files with 431 additions and 463 deletions.
2 changes: 1 addition & 1 deletion frontend/src/ShareApp.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script setup lang="ts">
import Simplebar from "simplebar-vue";
import ReportCanvas from "@/components/ReportCanvas.vue";
import ReportCanvas from "@/components/ProjectViewCanvas.vue";
</script>

<template>
Expand Down
Binary file modified frontend/src/assets/fonts/icomoon.eot
Binary file not shown.
40 changes: 18 additions & 22 deletions frontend/src/assets/fonts/icomoon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/src/assets/fonts/icomoon.ttf
Binary file not shown.
Binary file modified frontend/src/assets/fonts/icomoon.woff
Binary file not shown.
42 changes: 13 additions & 29 deletions frontend/src/assets/styles/_icons.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@
text-transform: none;
}

.icon-trash::before {
.icon-branch::before {
content: "\e900";
}

.icon-more::before {
content: "\e901";
}

.icon-branch::before {
.icon-trash::before {
content: "\e902";
}

Expand Down Expand Up @@ -79,62 +79,46 @@
content: "\e90c";
}

.icon-xl::before {
content: "\e90d";
}

.icon-sm::before {
content: "\e90e";
}

.icon-xs::before {
content: "\e90f";
}

.icon-search::before {
content: "\e910";
content: "\e90d";
}

.icon-maximize::before {
content: "\e911";
content: "\e90e";
}

.icon-folder::before {
content: "\e912";
content: "\e90f";
}

.icon-plot::before {
content: "\e913";
content: "\e910";
}

.icon-text::before {
content: "\e914";
content: "\e911";
}

.icon-gift::before {
content: "\e915";
content: "\e912";
}

.icon-pie-chart::before {
content: "\e916";
}

.icon-equal::before {
content: "\e917";
content: "\e913";
}

.icon-chevron-left::before {
content: "\e918";
content: "\e914";
}

.icon-chevron-down::before {
content: "\e919";
content: "\e915";
}

.icon-chevron-right::before {
content: "\e91a";
content: "\e916";
}

.icon-chevron-up::before {
content: "\e91b";
content: "\e917";
}
1 change: 1 addition & 0 deletions frontend/src/assets/styles/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
@import url("./_typography.css");
@import url("./_animations.css");
@import url("./_icons.css");
@import url("simplebar-vue/dist/simplebar.min.css");
@import url("highlight.js/styles/atom-one-dark.css") screen and (prefers-color-scheme: dark);
@import url("highlight.js/styles/atom-one-light.css") screen and (prefers-color-scheme: light);

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/DropdownButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ onBeforeUnmount(() => {
& .items {
position: fixed;
z-index: 1000;
z-index: 9999;
display: flex;
overflow: visible;
width: max-content;
Expand Down
20 changes: 12 additions & 8 deletions frontend/src/components/EditableList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ const props = defineProps<{
actions?: EditableListAction[];
}>();
const emit = defineEmits<{ action: [payload: string, item: EditableListItemModel] }>();
const emit = defineEmits<{
action: [payload: string, item: EditableListItemModel];
select: [name: string];
}>();
const items = defineModel<EditableListItemModel[]>("items", { required: true });
const onAction = (payload: string, item: EditableListItemModel) => {
Expand All @@ -29,13 +32,14 @@ const onAction = (payload: string, item: EditableListItemModel) => {

<template>
<div class="editable-list">
<div class="editable-list-item" v-for="(item, index) in items" :key="item.name">
<EditableListItem
v-model="items[index]"
:actions="props.actions"
@action="onAction($event, item)"
/>
</div>
<EditableListItem
v-for="(item, index) in items"
:key="item.name"
v-model="items[index]"
:actions="props.actions"
@action="onAction($event, item)"
@select="emit('select', item.name)"
/>
</div>
</template>

Expand Down
9 changes: 6 additions & 3 deletions frontend/src/components/EditableListItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import type { EditableListAction, EditableListItemModel } from "@/components/Edi
const props = defineProps<{ actions?: EditableListAction[] }>();
const emit = defineEmits<{ action: [payload: string] }>();
const emit = defineEmits<{
action: [payload: string];
select: [name: string];
}>();
const item = defineModel<EditableListItemModel>({ required: true });
const label = ref<HTMLSpanElement>();
Expand Down Expand Up @@ -35,7 +38,7 @@ onMounted(() => {

<template>
<div class="editable-list-item">
<div class="label-container">
<div class="label-container" @click="emit('select', item.name)">
<span class="icon" v-if="item.icon" :class="item.icon" />
<span
class="label"
Expand Down Expand Up @@ -77,14 +80,14 @@ onMounted(() => {
.label {
min-width: 100px;
caret-color: var(--color-primary);
color: var(--text-color-highlight);
line-height: 2;
outline: none;
transition: font-weight var(--transition-duration) var(--transition-easing);
&[contenteditable="true"] {
background-color: var(--color-primary);
caret-color: var(--color-secondary);
color: var(--button-color);
cursor: text;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,26 @@ import HtmlSnippetWidget from "@/components/HtmlSnippetWidget.vue";
import ImageWidget from "@/components/ImageWidget.vue";
import MarkdownWidget from "@/components/MarkdownWidget.vue";
import PlotlyWidget from "@/components/PlotlyWidget.vue";
import ReportCard from "@/components/ReportCard.vue";
import ProjectViewCard from "@/components/ProjectViewCard.vue";
import VegaWidget from "@/components/VegaWidget.vue";
import type { KeyLayoutSize, KeyMoveDirection } from "@/models";
import { useReportStore } from "@/stores/report";
import { useProjectStore } from "@/stores/project";
const reportStore = useReportStore();
const props = defineProps({
showCardButtons: {
type: Boolean,
default: true,
},
});
const projectStore = useProjectStore();
const visibleItems = computed(() => {
const items = [];
let index = 0;
if (reportStore.items !== null) {
for (const { key, size } of reportStore.layout) {
const item = reportStore.items[key];
if (projectStore.items !== null && projectStore.currentView !== null) {
const v = projectStore.views[projectStore.currentView];
for (const key of v) {
const item = projectStore.items[key];
if (item) {
const mediaType = item.media_type || "";
let data;
Expand All @@ -45,7 +52,6 @@ const visibleItems = computed(() => {
const updatedAt = new Date(item.updated_at);
items.push({
key,
size,
mediaType,
data,
createdAt,
Expand All @@ -59,25 +65,12 @@ const visibleItems = computed(() => {
return items;
});
function onLayoutChange(key: string, size: KeyLayoutSize) {
reportStore.setKeyLayoutSize(key, size);
}
function onCardRemoved(key: string) {
reportStore.hideKey(key);
}
function onPositionChanged(key: string, direction: KeyMoveDirection) {
reportStore.moveKey(key, direction);
if (projectStore.currentView) {
projectStore.hideKey(projectStore.currentView, key);
}
}
const props = defineProps({
showCardButtons: {
type: Boolean,
default: true,
},
});
function getItemSubtitle(created_at: Date, updated_at: Date) {
const now = new Date();
return `Created ${formatDistance(created_at, now)} ago, updated ${formatDistance(updated_at, now)} ago`;
Expand All @@ -86,18 +79,13 @@ function getItemSubtitle(created_at: Date, updated_at: Date) {

<template>
<div class="canvas">
<ReportCard
v-for="{ key, size, mediaType, data, createdAt, updatedAt, index } in visibleItems"
<ProjectViewCard
v-for="{ key, mediaType, data, createdAt, updatedAt } in visibleItems"
:key="key"
:title="key.toString()"
:subtitle="getItemSubtitle(createdAt, updatedAt)"
:showButtons="props.showCardButtons"
:can-move-up="index > 0"
:can-move-down="index < reportStore.layout.length - 1"
:class="size"
class="canvas-element"
@layout-changed="onLayoutChange(key.toString(), $event)"
@position-changed="onPositionChanged(key.toString(), $event)"
@card-removed="onCardRemoved(key.toString())"
>
<DataFrameWidget
Expand All @@ -119,33 +107,21 @@ function getItemSubtitle(created_at: Date, updated_at: Date) {
:src="data"
/>
<HtmlSnippetWidget v-if="mediaType === 'text/html'" :src="data" />
</ReportCard>
</ProjectViewCard>
</div>
</template>

<style scoped>
.canvas {
display: grid;
display: flex;
flex-direction: column;
padding: var(--spacing-gap-normal);
background-color: var(--background-color-normal);
gap: var(--spacing-gap-normal);
grid-template-columns: 1fr 1fr 1fr;
transition: grid-column var(--transition-duration) var(--transition-easing);
& .canvas-element {
max-width: 100%;
&.small {
grid-column: span 1;
}
&.medium {
grid-column: span 2;
}
&.large {
grid-column: span 3;
}
}
}
</style>
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
<script setup lang="ts">
import type { KeyLayoutSize, KeyMoveDirection } from "@/models";
const props = defineProps<{
title: string;
subtitle?: string;
showButtons: boolean;
canMoveUp: boolean;
canMoveDown: boolean;
}>();
const emit = defineEmits<{
layoutChanged: [size: KeyLayoutSize];
positionChanged: [direction: KeyMoveDirection];
cardRemoved: [];
}>();
</script>
Expand All @@ -26,22 +20,7 @@ const emit = defineEmits<{
</div>
</div>
<div v-if="props.showButtons" class="buttons">
<button @click="emit('layoutChanged', 'small')">
<span class="icon-xs"></span>
</button>
<button @click="emit('layoutChanged', 'medium')">
<span class="icon-sm"></span>
</button>
<button @click="emit('layoutChanged', 'large')">
<span class="icon-xl"></span>
</button>
<button v-if="props.canMoveUp" @click="emit('positionChanged', 'up')">
<span class="icon-chevron-up"></span>
</button>
<button v-if="props.canMoveDown" @click="emit('positionChanged', 'down')">
<span class="icon-chevron-down"></span>
</button>
<button @click="emit('cardRemoved')">x</button>
<button @click="emit('cardRemoved')"><span class="icon-trash"></span></button>
</div>
</div>
<hr />
Expand Down
1 change: 0 additions & 1 deletion frontend/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import "simplebar-vue/dist/simplebar.min.css";
import "./assets/styles/main.css";

import { createPinia } from "pinia";
Expand Down
26 changes: 17 additions & 9 deletions frontend/src/models.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
export type KeyLayoutSize = "small" | "medium" | "large";
export type KeyMoveDirection = "up" | "down";

export type Layout = Array<{ key: string; size: KeyLayoutSize }>;

export interface ReportItem {
/**
* A project item is a single item in the project.
*
* It's contributed by a user python side.
*/
export interface ProjectItem {
media_type: string;
value: any;
updated_at: string;
created_at: string;
}

export interface Report {
items: { [key: string]: ReportItem };
layout: Layout;
/**
* A layout is a list of keys that are visible in a view
*/
export type Layout = string[];

/**
* A project is a collection of items and views
*/
export interface Project {
items: { [key: string]: ProjectItem };
views: { [key: string]: Layout };
}
Loading

0 comments on commit c2f164e

Please sign in to comment.