Skip to content

Commit

Permalink
UI changes, bug fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
alvinsw committed May 17, 2024
1 parent d94367a commit 3e8a6e3
Show file tree
Hide file tree
Showing 11 changed files with 161 additions and 117 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "crate-o",
"version": "0.3.6",
"version": "0.3.7",
"description": "A VueJS UI component to create and edit Research Object Crate (RO-Crate) metadata",
"keywords": [
"RO-Crate",
Expand Down
4 changes: 2 additions & 2 deletions src/app/components/Help.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ import { ElRow, ElCol } from 'element-plus';
Closes without saving.
</p>
<h4 class="text-gray-500 dark:text-gray-400">
Profile
Mode
</h4>
<p class="text-gray-500 dark:text-gray-400">
Select a predefined profile or load one from your computer.
Select a predefined mode or load one from your computer.
</p>
</div>
</el-col>
Expand Down
8 changes: 4 additions & 4 deletions src/app/utils/profiles.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const profileUrls = [
'https://language-research-technology.github.io/ro-crate-editor-profiles/profiles/base-profile.json',
'https://language-research-technology.github.io/ro-crate-editor-profiles/profiles/schema.json',
'https://language-research-technology.github.io/ro-crate-editor-profiles/profiles/language-data-commons-collection-profile.json',
'https://language-research-technology.github.io/ro-crate-editor-profiles/profiles/software-profile.json'
'https://language-research-technology.github.io/ro-crate-modes/modes/base.json',
'https://language-research-technology.github.io/ro-crate-modes/modes/schema.json',
'https://language-research-technology.github.io/ro-crate-modes/modes/language-data-commons-collection.json',
'https://language-research-technology.github.io/ro-crate-modes/modes/software.json'
];
export const profiles = profileUrls.map(p => null);
const p = profileUrls.map((url, i) => fetch(url).then(r => r.ok ? r.json().then(json => profiles[i] = json) : null));
Expand Down
80 changes: 49 additions & 31 deletions src/app/views/CrateoView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import Help from "../components/Help.vue";
import SpreadSheet from "../components/SpreadSheet.vue";
import { Validator } from "../utils/profileValidator.js";
import { ROCrate } from "ro-crate";
import { ElRow, ElCol, ElMenu, ElMenuItem, ElDivider, ElSelect, ElOption, ElDialog, ElButton } from 'element-plus';
import { ElRow, ElCol, ElMenu, ElMenuItem, ElDivider, ElSelect, ElOption,
ElDialog, ElButton, ElCollapse, ElCollapseItem, ElAlert } from 'element-plus';
import { handleRoute } from '../../lib/DefaultRouteHandler.js'
import { CrateEditor } from '../../lib'
Expand Down Expand Up @@ -78,8 +79,6 @@ const commands = {
console.log('open');
try {
data.dirHandle = await window.showDirectoryPicker();
// reset crate
resetData();
data.loading = true;
try {
data.metadataHandle = await data.dirHandle.getFileHandle('ro-crate-metadata.json');
Expand All @@ -100,12 +99,13 @@ const commands = {
data.crate = crate;
//navigate();
//data.loading = false;
console.log('end open')
// reset crate
resetData();
} catch (error) {
console.error(error);
window.alert(error);
resetData();
}
console.log('end open')
},
async addFiles() {
Expand All @@ -115,6 +115,7 @@ const commands = {
},
async save() {
console.log('save!!!!!!!!!!!');
if (data.dirHandle) {
// create new crate metadata
data.metadataHandle = await data.dirHandle.getFileHandle('ro-crate-metadata.json', { create: true });
Expand All @@ -136,9 +137,9 @@ const commands = {
const content = JSON.stringify(crate, null, 2);
await writable.write(content);
await writable.close();
data.crate = crate;
data.entityId = '';
data.validationResult = validate(data.crate, profile.value);
//data.crate = crate;
//data.entityId = '';
data.validationResult = validate(crate, profile.value);
data.validationResultDialog = !!data.validationResult;
}
},
Expand Down Expand Up @@ -304,7 +305,7 @@ function selectProfile(v) {
data.selectedProfile = v;
}
}
const activeNames = ref(['1']);
</script>
<template>
Expand All @@ -326,22 +327,23 @@ function selectProfile(v) {
<el-menu-item index="close" :disabled="!data.dirHandle">
ⓧ Close
</el-menu-item>
<el-menu-item index="help" title="Help">
Help
</el-menu-item>
</el-menu>
<el-row class="text-large p-3" :gutter="10">
<el-col :xs="24" :sm="24" :md="12" :lg="12">
<el-row class="w-full p-1">
<el-select :model-value="data.selectedProfile" @update:model-value="selectProfile" placeholder="Open a directory first to select a mode" class="w-[30em]" :disabled="!data.dirHandle">
<el-select :model-value="data.selectedProfile" @update:model-value="selectProfile"
placeholder="Open a directory first to select a mode" class="w-[30em]" :disabled="!data.dirHandle">
<template #prefix>
<span class="font-bold">Mode:</span>
</template>
<el-option :value="-1">
<p class="font-bold italic">Load and add a new mode from your computer ...</p>
</el-option>
<el-option v-for="(profile, index) of data.profiles" v-if="profile" :label="profile.metadata.name" :value="index">
<el-option v-for="(profile, index) of data.profiles" v-if="profile" :label="profile.metadata.name"
:value="index">
<div class="border-b-1 mb-2">
<p>{{ profile.metadata.name }}</p>
<p class="text-slate-500 text-xs">{{ profile.metadata.description }}</p>
Expand All @@ -353,26 +355,32 @@ function selectProfile(v) {
<el-col v-if="data.dirHandle" :xs="24" :sm="24" :md="12" :lg="12">
<el-row class="p-1">
<span class="flex items-center">
Selected Directory:&nbsp;<span class="font-bold">{{ data.dirHandle.name }}</span>
<span class="font-bold text-slate-500">Selected Directory:</span>&nbsp;<span>{{ data.dirHandle.name
}}</span>
</span>
</el-row>
</el-col>
</el-row>
</div>
<template v-if="data.crate">
<div v-if="data.validationResultDialog" class="bg-orange-100 text-orange-700 px-4 py-3 relative" role="alert">
<strong class="block sm:inline font-bold">Saved with warnings</strong>
<div class="p-2" v-for="(obj, key) in data.validationResult">
<p>Entity:
<el-button size="small" type="default" @click="goTo({ id: key })"> {{ obj?.name?.[0] || key }}</el-button>
</p>
Property(s) :
<p v-for="(prop, keyProp) in obj.props" class="ml-5 py-1">
<el-button size="small" @click="goTo({ id: key, prop: keyProp })">{{ prop.name }}</el-button>
<span class="text-red-700">&nbsp;is {{ prop['type'] }}</span>
</p>
</div>
<span class="absolute top-0 bottom-0 right-0 px-4 py-3">
<el-alert class="validation-warnings" v-if="data.validationResultDialog" type="warning" @close="data.validationResultDialog = false">
<el-collapse class="ml-5 mr-10 min-w-96" role="alert">
<el-collapse-item title="Saved with warnings" name="validation-warnings">
<div class="p-2" v-for="(obj, key) in data.validationResult">
<p>Entity:
<el-button size="small" type="default" @click="goTo({ id: key })"> {{ obj?.name?.[0] || key }}</el-button>
</p>
Property(s) :
<p v-for="(prop, keyProp) in obj.props" class="ml-5 py-1">
<el-button size="small" @click="goTo({ id: key, prop: keyProp })">{{ prop.name }}</el-button>
<span class="text-red-700">&nbsp;is {{ prop['type'] }}</span>
</p>
</div>
</el-collapse-item>
</el-collapse>
</el-alert>
<!-- <strong class="block sm:inline font-bold">Saved with warnings</strong> -->
<!-- <span class="absolute top-0 bottom-0 right-0 px-4 py-3">
<el-button type="text" @click="data.validationResultDialog = false">
<svg class="fill-current h-6 w-6 text-red-500" role="button" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20">
Expand All @@ -381,18 +389,18 @@ function selectProfile(v) {
d="M14.348 14.849a1.2 1.2 0 0 1-1.697 0L10 11.819l-2.651 3.029a1.2 1.2 0 1 1-1.697-1.697l2.758-3.15-2.759-3.152a1.2 1.2 0 1 1 1.697-1.697L10 8.183l2.651-3.031a1.2 1.2 0 1 1 1.697 1.697l-2.758 3.152 2.758 3.15a1.2 1.2 0 0 1 0 1.698z" />
</svg>
</el-button>
</span>
</div>
</span> -->
<CrateEditor ref="editor" :crate="data.crate" :profile="profile" :entityId="data.entityId"
:propertyId="data.propertyId" :get-file="getFile" @update:entityId="updateEntityId" @update:crate="updateCrate"
@ready="() => data.loading = false" @data="detectProfile">
</CrateEditor>
<SpreadSheet v-model:crate="data.crate" :buffer="data.spreadSheetBuffer" />
</template>
<div v-else>
<welcome/>
<welcome />
</div>
<el-dialog v-if="data.profileErrorDialog" v-model="data.profileError" :title="'Error when loading Profile'" width="50%">
<el-dialog v-if="data.profileErrorDialog" v-model="data.profileError" :title="'Error when loading Mode'"
width="50%">
<div class="overflow-x-scroll h-96">
{{ data.selectedProfile?.metadata }}
<el-divider />
Expand Down Expand Up @@ -429,4 +437,14 @@ function selectProfile(v) {
.el-select-dropdown__item {
height: auto;
}
/* .validation-warnings .el-alert__content {
flex-grow: 1;
} */
.validation-warnings .el-collapse {
--el-collapse-header-bg-color: transparent;
--el-collapse-content-bg-color: transparent;
--el-collapse-header-font-size: 14px;
--el-collapse-header-text-color: inherit;
--el-collapse-content-text-color: inherit;
}
</style>
8 changes: 4 additions & 4 deletions src/lib/components/ControlAdd.vue
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ function typeLabel(type) {
<div v-if="!definition.max || !modelValue.length || definition.max > 1">
<!-- Add buttons -->
<el-select v-if="types.length > 1" :modelValue="data.selectedType" @clear="data.selectedType = ''"
placeholder="Choose a type" size="small" clearable filterable style="--el-select-width: 200px;">
placeholder="Choose a type" clearable filterable style="--el-select-width: 200px;">
<template #prefix>
<el-icon>
<Plus />
Expand All @@ -149,14 +149,14 @@ function typeLabel(type) {
{{ typeLabel(t) }}
</el-option>
</el-select>
<el-button v-else v-for="t of types" size="small" type="primary" :icon="data.selectedType === t ? Close : Plus"
<el-button v-else v-for="t of types" type="primary" :icon="data.selectedType === t ? Close : Plus"
:class="{ active: data.selectedType === t }" @click="add(t)">
{{ typeLabel(t) }}
</el-button>
<!-- search input -->
<template v-if="data.selectedType">
<el-select v-focus class="flex-grow min-w-[100px]" filterable remote clearable v-model="data.entity" value-key="@id"
:loading="data.loading" @change="addEntity" :remote-method="search" size="small" @keyup.enter="addNewEntity">
:loading="data.loading" @change="addEntity" :remote-method="search" @keyup.enter="addNewEntity">
<template v-for="group in data.options" :key="group.value">
<el-option-group v-if="group.options.length" :label="group.label">
<el-option v-for="item in group.options" :key="item['@id']" :label="createLabel(item)" :value="item">
Expand All @@ -166,7 +166,7 @@ function typeLabel(type) {
</el-option-group>
</template>
</el-select>
<el-button class="add-new-entity" size="small" type="success" @click="addNewEntity">
<el-button class="add-new-entity" type="success" @click="addNewEntity">
Create new {{ typeLabel(data.selectedType) }}<span v-if="data.keyword">:&nbsp;</span>
{{ data.keyword }}</el-button>
</template>
Expand Down
94 changes: 52 additions & 42 deletions src/lib/components/CrateEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ref, shallowReactive, reactive, watch, computed, provide, onUpdated, ne
import { HomeFilled, ArrowLeftBold, Delete } from '@element-plus/icons-vue';
import {
ElRow, ElCol, ElBreadcrumb, ElBreadcrumbItem, ElTabs, ElTabPane,
ElPageHeader, ElTooltip, ElLink, ElSelectV2, ElButton, ElLoading
ElPageHeader, ElTooltip, ElLink, ElSelectV2, ElButton, ElLoading, ElTag, ElIcon
} from 'element-plus';
import { $state } from './keys';
import { EditorState } from './EditorState';
Expand Down Expand Up @@ -96,6 +96,7 @@ watch(() => props.entityId, entityId => {
function initEntity(entityId) {
var id = entityId || data.rootDataset?.['@id'];
console.log('entityId=', entityId, ' id=', id);
if (state.crate) {
if (data.entity?.['@id'] !== id) {
const entity = state.crate.getEntity(id);
Expand All @@ -104,7 +105,8 @@ function initEntity(entityId) {
if (i > -1) data.history.splice(i + 1);
else data.history.push(entity);
data.entity = entity;
console.log(data.history);
//console.log(data.history);
//console.log('initEntity');
if (entityId !== id) emit('update:entityId', id);
}
}
Expand Down Expand Up @@ -212,53 +214,55 @@ function truncate(text) {
<template>
<div :key="forceKey">
<el-row class="bg-slate-300 p-2" v-if="data.rootDataset">
<el-col :span="17" class="p-2 flex items-center">
<el-breadcrumb separator="/">
<el-breadcrumb-item v-for="e, i in data.history">
<el-link :disabled="i === data.history.length - 1" :icon="i ? null : HomeFilled" href="/"
@click.prevent="showEntity(e)" :title="e.name?.[0] || e['@id']">
<span v-html="truncate(e.name?.[0] || (i ? e['@id'] : 'Root Dataset'))"></span>
</el-link>
</el-breadcrumb-item>
</el-breadcrumb>
</el-col>
<el-col :span="5" class="pt-1 pr-3">
<el-select-v2 placeholder="Create New Entity" class="flex-grow" filterable clearable :allow-create="false"
v-model="data.newEntityType" :options="newEntityTypes" @change="onSelectNewEntity"></el-select-v2>
</el-col>
</el-row>
<el-row v-loading="data.loading" class="crate-o">
<el-col :span="18" class="p-2">
<template v-if="data.entity">
<el-page-header :icon="null" class="bg-blue-100 border-t border-b border-blue-500 text-blue-700 px-4 py-3"
role="alert">
<template #title>
<span class="text-large font-600 mr-3"> {{ data.entity['name']?.[0] || data.entity['@id'] }} </span>
</template>
<template #content>
</template>
<template #extra>
<div class="flex items-center">
<el-col :span="18" class="p-2" id="currentEntity">
<el-row class="py-3 px-2 items-center bg-slate-200" v-if="data.rootDataset">
<el-col>
<div class="mb-3">
<el-breadcrumb separator=">">
<template v-for="e, i in data.history">
<el-breadcrumb-item>
<el-link :icon="i ? null : HomeFilled" href="/"
@click.prevent="showEntity(e)" :title="e.name?.[0] || e['@id']">
<span v-html="truncate(e.name?.[0] || (i ? e['@id'] : 'Root Dataset'))"></span>
</el-link>
</el-breadcrumb-item>
</template>
</el-breadcrumb>
</div>
<el-row v-if="data.entity">
<el-col :sm="24" :md="18" :lg="20">
<h2 class="text-2xl mr-3">
<span class="text-2xl font-bold text-slate-500">Current Entity: </span>
<el-icon style="font-size: 30px; top:4px;" v-if="data.rootDataset === data.entity"><HomeFilled/></el-icon>
{{ data.entity['name']?.[0] || data.entity['@id'] }}
</h2>
</el-col>
<el-col :sm="24" :md="6" :lg="4">
<el-tooltip v-if="data.rootDataset !== data.entity"
:content="'Delete entity ' + data.entity['name']?.[0] || data.entity['@id']" placement="bottom-start"
effect="light">
<el-button @click="deleteEntity" type="danger" plain :icon="Delete">Remove</el-button>
<el-button class="float-right" @click="deleteEntity" type="danger" plain :icon="Delete">Remove Entity</el-button>
</el-tooltip>
</div>
</template>
</el-page-header>
<Entity :model-value="data.entity" @update:model-value="updateEntity" :getFile="getFile"
:propertyId="propertyId">
</Entity>
</template>
<div v-else="">Entity with id `{{ entityId }}` does not exist in the crate.</div>
</el-col>
</el-row>
</el-col>
</el-row>
<el-row class="mt-3">
<template v-if="data.entity">
<Entity :model-value="data.entity" @update:model-value="updateEntity" :getFile="getFile"
:propertyId="propertyId">
</Entity>
</template>
<div v-else="">Entity with id `{{ entityId }}` does not exist in the crate.</div>
</el-row>
</el-col>
<el-col :span="6" class="h-screen p-2">
<el-col :span="6" class="h-screen p-2" id="entityNavigator">
<el-select-v2 placeholder="Create New Entity" class="flex-grow" filterable clearable :allow-create="false"
v-model="data.newEntityType" :options="newEntityTypes" @change="onSelectNewEntity"></el-select-v2>
<el-tabs class="w-full" v-model="data.activeTab">
<el-tab-pane label="All Entities" name="all" lazy>
<FilteredPaged :modelValue="Array.from(state.entities.value)" v-slot="{ value, index }">
Expand Down Expand Up @@ -294,4 +298,10 @@ label.el-form-item__label,
div.el-form-item__label {
align-items: center;
}
.el-breadcrumb .el-link {
color: #626aef;
font-weight: 600;
font-size: 90%;
}
</style>
Loading

0 comments on commit 3e8a6e3

Please sign in to comment.