Skip to content

PKP Sciflow TEST : initial integration of editor via component demo #573

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@sciflow:registry=https://gitlab.com/api/v4/projects/67023583/packages/npm/
//gitlab.com/api/v4/projects/67023583/packages/npm/:_authToken="${NPM_TOKEN}"
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@
"@highlightjs/vue-plugin": "^2.1.2",
"@lk77/vue3-color": "^3.0.6",
"@storybook/test": "^8.6.12",
"@sciflow/component-demo": "^0.0.1-1668088552",
"@tinymce/tinymce-vue": "^6.1.0",
"@vue-a11y/announcer": "^3.1.5",
"@vueuse/core": "^10.11.1",
2 changes: 2 additions & 0 deletions src/pages/workflow/WorkflowPageOJS.vue
Original file line number Diff line number Diff line change
@@ -23,6 +23,7 @@ import WorkflowListingEmails from './components/primary/WorkflowListingEmails.vu
import WorkflowPaymentDropdown from './components/header/WorkflowPaymentDropdown.vue';
import WorkflowPublicationForm from './components/publication/WorkflowPublicationForm.vue';
import WorkflowPublicationJats from './components/publication/WorkflowPublicationJats.vue';
import WorkflowPublicationEditor from './components/publication/WorkflowPublicationEditor.vue';
import WorkflowPublicationVersionControl from './components/publication/WorkflowPublicationVersionControl.vue';
import WorkflowChangeSubmissionLanguage from './components/publication/WorkflowChangeSubmissionLanguage.vue';
import WorkflowPrimaryBasicMetadata from './components/primary/WorkflowPrimaryBasicMetadata.vue';
@@ -54,6 +55,7 @@ const Components = markRaw({
WorkflowPrimaryBasicMetadata,
WorkflowPublicationForm,
WorkflowPublicationJats,
WorkflowPublicationEditor,
WorkflowPublicationVersionControl,
WorkflowChangeSubmissionLanguage,
WorkflowSubmissionStatus,
Original file line number Diff line number Diff line change
@@ -0,0 +1,407 @@
<template>
<div class="fulltext-editor">
<sfo-editor v-if="isEditorReady">
<h1 data-type="abstract">Abstract</h1>
<p>Power your CMS with a modern academic editing experience.</p>
</sfo-editor>
</div>
</template>

<script setup>
import {onMounted, ref} from 'vue';
// Track if editor is ready
const isEditorReady = ref(false);
// Load required scripts dynamically
async function loadEditorScripts() {
try {
// Use the global helper to load scripts
await pkp.loadSciflowEditor();
// Wait for custom element to be defined
await customElements.whenDefined('sfo-editor');
isEditorReady.value = true;
// Setup editor after next tick to ensure template is rendered
setTimeout(() => {
const editor = document.querySelector('sfo-editor');
if (editor) {
editor.addEventListener('document', (event) => {
const doc = event.detail?.toJSON();
console.log('[Editor Component] Document changed', {doc});
});
}
}, 0);
} catch (error) {
console.error('Failed to load editor:', error);
}
}
onMounted(() => {
loadEditorScripts();
});
</script>
<style>
/* Import required fonts */
@import url('https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400..700;1,400..700&family=Noto+Sans+Arabic:wght@100..900&family=Noto+Sans:ital,wght@0,100..900;1,100..900&family=Noto+Serif:ital,wght@0,100..900;1,100..900&family=Roboto+Condensed:ital,wght@0,100..900;1,100..900&family=Roboto:ital,wght@0,100..900;1,100..900&display=swap');
@import url('https://fonts.googleapis.com/icon?family=Material+Icons');
@import url('https://unpkg.com/basscss@8.0.2/css/basscss.min.css');
.fulltext-editor {
width: 100%;
height: 100%;
}
.demo-bg {
background: #fff;
background: linear-gradient(180deg, #fff 15%, #07659e80 31%, #fff 93%);
}
.demo-bg .demo {
border-radius: 2rem;
background: #fff;
}
.logo img {
max-height: 8rem;
}
.scroll {
max-height: 60vh;
padding: 0;
overflow-y: auto;
overflow-x: none;
display: block;
}
#json-content {
max-width: 100%;
height: 100%;
overflow-y: auto;
font-size: 0.85rem;
}
.title {
font-size: 6rem;
font-weight: 400;
font-family: Roboto Condensed, Roboto, serif;
}
.subtitle {
font-weight: lighter;
}
.colored-text {
background: #3f5efb;
background: radial-gradient(circle, #3f5efb, #fc466b 35%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
sfo-editor {
display: block;
border-radius: 0.5rem;
padding: 2rem;
}
html {
--mat-sys-background: #faf9fd;
--mat-sys-error: #ba1a1a;
--mat-sys-error-container: #ffdad6;
--mat-sys-inverse-on-surface: #f2f0f4;
--mat-sys-inverse-primary: #abc7ff;
--mat-sys-inverse-surface: #2f3033;
--mat-sys-on-background: #1a1b1f;
--mat-sys-on-error: #ffffff;
--mat-sys-on-error-container: #410002;
--mat-sys-on-primary: #ffffff;
--mat-sys-on-primary-container: #001b3f;
--mat-sys-on-primary-fixed: #001b3f;
--mat-sys-on-primary-fixed-variant: #00458f;
--mat-sys-on-secondary: #ffffff;
--mat-sys-on-secondary-container: #131c2b;
--mat-sys-on-secondary-fixed: #131c2b;
--mat-sys-on-secondary-fixed-variant: #3e4759;
--mat-sys-on-surface: #1a1b1f;
--mat-sys-on-surface-variant: #44474e;
--mat-sys-on-tertiary: #ffffff;
--mat-sys-on-tertiary-container: #00006e;
--mat-sys-on-tertiary-fixed: #00006e;
--mat-sys-on-tertiary-fixed-variant: #0000ef;
--mat-sys-outline: #74777f;
--mat-sys-outline-variant: #c4c6d0;
--mat-sys-primary: #005cbb;
--mat-sys-primary-container: #d7e3ff;
--mat-sys-primary-fixed: #d7e3ff;
--mat-sys-primary-fixed-dim: #abc7ff;
--mat-sys-scrim: #000000;
--mat-sys-secondary: #565e71;
--mat-sys-secondary-container: #dae2f9;
--mat-sys-secondary-fixed: #dae2f9;
--mat-sys-secondary-fixed-dim: #bec6dc;
--mat-sys-shadow: #000000;
--mat-sys-surface: #faf9fd;
--mat-sys-surface-bright: #faf9fd;
--mat-sys-surface-container: #efedf0;
--mat-sys-surface-container-high: #e9e7eb;
--mat-sys-surface-container-highest: #e3e2e6;
--mat-sys-surface-container-low: #f4f3f6;
--mat-sys-surface-container-lowest: #ffffff;
--mat-sys-surface-dim: #dbd9dd;
--mat-sys-surface-tint: #005cbb;
--mat-sys-surface-variant: #e0e2ec;
--mat-sys-tertiary: #343dff;
--mat-sys-tertiary-container: #e0e0ff;
--mat-sys-tertiary-fixed: #e0e0ff;
--mat-sys-tertiary-fixed-dim: #bec2ff;
--mat-sys-neutral-variant20: #2d3038;
--mat-sys-neutral10: #1a1b1f;
}
html {
--mat-sys-level0: 0px 0px 0px 0px rgba(0, 0, 0, 0.2),
0px 0px 0px 0px rgba(0, 0, 0, 0.14), 0px 0px 0px 0px rgba(0, 0, 0, 0.12);
}
html {
--mat-sys-level1: 0px 2px 1px -1px rgba(0, 0, 0, 0.2),
0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12);
}
html {
--mat-sys-level2: 0px 3px 3px -2px rgba(0, 0, 0, 0.2),
0px 3px 4px 0px rgba(0, 0, 0, 0.14), 0px 1px 8px 0px rgba(0, 0, 0, 0.12);
}
html {
--mat-sys-level3: 0px 3px 5px -1px rgba(0, 0, 0, 0.2),
0px 6px 10px 0px rgba(0, 0, 0, 0.14),
0px 1px 18px 0px rgba(0, 0, 0, 0.12);
}
html {
--mat-sys-level4: 0px 5px 5px -3px rgba(0, 0, 0, 0.2),
0px 8px 10px 1px rgba(0, 0, 0, 0.14),
0px 3px 14px 2px rgba(0, 0, 0, 0.12);
}
html {
--mat-sys-level5: 0px 7px 8px -4px rgba(0, 0, 0, 0.2),
0px 12px 17px 2px rgba(0, 0, 0, 0.14),
0px 5px 22px 4px rgba(0, 0, 0, 0.12);
}
html {
--mat-sys-body-large: 400 1rem / 1.5rem Roboto;
--mat-sys-body-large-font: Roboto;
--mat-sys-body-large-line-height: 1.5rem;
--mat-sys-body-large-size: 1rem;
--mat-sys-body-large-tracking: 0.031rem;
--mat-sys-body-large-weight: 400;
--mat-sys-body-medium: 400 0.875rem / 1.25rem Roboto;
--mat-sys-body-medium-font: Roboto;
--mat-sys-body-medium-line-height: 1.25rem;
--mat-sys-body-medium-size: 0.875rem;
--mat-sys-body-medium-tracking: 0.016rem;
--mat-sys-body-medium-weight: 400;
--mat-sys-body-small: 400 0.75rem / 1rem Roboto;
--mat-sys-body-small-font: Roboto;
--mat-sys-body-small-line-height: 1rem;
--mat-sys-body-small-size: 0.75rem;
--mat-sys-body-small-tracking: 0.025rem;
--mat-sys-body-small-weight: 400;
--mat-sys-display-large: 400 3.562rem / 4rem Roboto;
--mat-sys-display-large-font: Roboto;
--mat-sys-display-large-line-height: 4rem;
--mat-sys-display-large-size: 3.562rem;
--mat-sys-display-large-tracking: -0.016rem;
--mat-sys-display-large-weight: 400;
--mat-sys-display-medium: 400 2.812rem / 3.25rem Roboto;
--mat-sys-display-medium-font: Roboto;
--mat-sys-display-medium-line-height: 3.25rem;
--mat-sys-display-medium-size: 2.812rem;
--mat-sys-display-medium-tracking: 0;
--mat-sys-display-medium-weight: 400;
--mat-sys-display-small: 400 2.25rem / 2.75rem Roboto;
--mat-sys-display-small-font: Roboto;
--mat-sys-display-small-line-height: 2.75rem;
--mat-sys-display-small-size: 2.25rem;
--mat-sys-display-small-tracking: 0;
--mat-sys-display-small-weight: 400;
--mat-sys-headline-large: 400 2rem / 2.5rem Roboto;
--mat-sys-headline-large-font: Roboto;
--mat-sys-headline-large-line-height: 2.5rem;
--mat-sys-headline-large-size: 2rem;
--mat-sys-headline-large-tracking: 0;
--mat-sys-headline-large-weight: 400;
--mat-sys-headline-medium: 400 1.75rem / 2.25rem Roboto;
--mat-sys-headline-medium-font: Roboto;
--mat-sys-headline-medium-line-height: 2.25rem;
--mat-sys-headline-medium-size: 1.75rem;
--mat-sys-headline-medium-tracking: 0;
--mat-sys-headline-medium-weight: 400;
--mat-sys-headline-small: 400 1.5rem / 2rem Roboto;
--mat-sys-headline-small-font: Roboto;
--mat-sys-headline-small-line-height: 2rem;
--mat-sys-headline-small-size: 1.5rem;
--mat-sys-headline-small-tracking: 0;
--mat-sys-headline-small-weight: 400;
--mat-sys-label-large: 500 0.875rem / 1.25rem Roboto;
--mat-sys-label-large-font: Roboto;
--mat-sys-label-large-line-height: 1.25rem;
--mat-sys-label-large-size: 0.875rem;
--mat-sys-label-large-tracking: 0.006rem;
--mat-sys-label-large-weight: 500;
--mat-sys-label-large-weight-prominent: 700;
--mat-sys-label-medium: 500 0.75rem / 1rem Roboto;
--mat-sys-label-medium-font: Roboto;
--mat-sys-label-medium-line-height: 1rem;
--mat-sys-label-medium-size: 0.75rem;
--mat-sys-label-medium-tracking: 0.031rem;
--mat-sys-label-medium-weight: 500;
--mat-sys-label-medium-weight-prominent: 700;
--mat-sys-label-small: 500 0.688rem / 1rem Roboto;
--mat-sys-label-small-font: Roboto;
--mat-sys-label-small-line-height: 1rem;
--mat-sys-label-small-size: 0.688rem;
--mat-sys-label-small-tracking: 0.031rem;
--mat-sys-label-small-weight: 500;
--mat-sys-title-large: 400 1.375rem / 1.75rem Roboto;
--mat-sys-title-large-font: Roboto;
--mat-sys-title-large-line-height: 1.75rem;
--mat-sys-title-large-size: 1.375rem;
--mat-sys-title-large-tracking: 0;
--mat-sys-title-large-weight: 400;
--mat-sys-title-medium: 500 1rem / 1.5rem Roboto;
--mat-sys-title-medium-font: Roboto;
--mat-sys-title-medium-line-height: 1.5rem;
--mat-sys-title-medium-size: 1rem;
--mat-sys-title-medium-tracking: 0.009rem;
--mat-sys-title-medium-weight: 500;
--mat-sys-title-small: 500 0.875rem / 1.25rem Roboto;
--mat-sys-title-small-font: Roboto;
--mat-sys-title-small-line-height: 1.25rem;
--mat-sys-title-small-size: 0.875rem;
--mat-sys-title-small-tracking: 0.006rem;
--mat-sys-title-small-weight: 500;
}
html {
--mat-sys-corner-extra-large: 28px;
--mat-sys-corner-extra-large-top: 28px 28px 0 0;
--mat-sys-corner-extra-small: 4px;
--mat-sys-corner-extra-small-top: 4px 4px 0 0;
--mat-sys-corner-full: 9999px;
--mat-sys-corner-large: 16px;
--mat-sys-corner-large-end: 0 16px 16px 0;
--mat-sys-corner-large-start: 16px 0 0 16px;
--mat-sys-corner-large-top: 16px 16px 0 0;
--mat-sys-corner-medium: 12px;
--mat-sys-corner-none: 0;
--mat-sys-corner-small: 8px;
}
html {
--mat-sys-dragged-state-layer-opacity: 0.16;
--mat-sys-focus-state-layer-opacity: 0.12;
--mat-sys-hover-state-layer-opacity: 0.08;
--mat-sys-pressed-state-layer-opacity: 0.12;
}
.ProseMirror {
font-family: Noto Sans, serif;
font-size: 120%;
border-radius: 0.5rem;
padding: 0.125rem 8rem 0.125rem 1rem;
outline: none;
margin: 0.5rem;
}
.ProseMirror .ProseMirror-selectednode {
filter: invert(0.6);
border-radius: 0.25rem;
}
.ProseMirror h1,
.ProseMirror h2,
.ProseMirror h3,
.ProseMirror h4,
.ProseMirror h5,
.ProseMirror h6 {
background: unset;
color: unset;
-webkit-background-clip: unset;
-webkit-text-fill-color: unset;
font-family: Noto Sans, serif;
font-size: 1.2rem;
}
.ProseMirror h2,
.ProseMirror h3,
.ProseMirror h4,
.ProseMirror h5,
.ProseMirror h6 {
font-size: 1.1rem;
font-weight: 700;
}
.ProseMirror h1 {
border-bottom: thin solid #007b6a;
}
.ProseMirror cite,
.ProseMirror math {
border-bottom: 2px dashed rgba(108, 248, 0, 0.6235294118);
}
.ProseMirror h1[data-type]:before {
opacity: 0.5;
padding-right: 0.25em;
content: "h1";
}
.ProseMirror h2[data-type]:before {
opacity: 0.5;
padding-right: 0.25em;
content: "h2";
}
.ProseMirror h3[data-type]:before {
opacity: 0.5;
padding-right: 0.25em;
content: "h3";
}
.ProseMirror h1[data-type]:after {
position: absolute;
right: 0;
opacity: 0.5;
font-size: 0.9rem;
content: attr(data-type) " ";
}
.ProseMirror {
position: relative;
}
.ProseMirror {
word-wrap: break-word;
white-space: pre-wrap;
white-space: break-spaces;
-webkit-font-variant-ligatures: none;
font-variant-ligatures: none;
font-feature-settings: "liga" 0;
}
.ProseMirror pre {
white-space: pre-wrap;
}
.ProseMirror li {
position: relative;
}
.ProseMirror-hideselection *::selection {
background: transparent;
}
.ProseMirror-hideselection *::-moz-selection {
background: transparent;
}
.ProseMirror-hideselection {
caret-color: transparent;
}
.ProseMirror [draggable][contenteditable="false"] {
-webkit-user-select: text;
user-select: text;
}
.ProseMirror-selectednode {
outline: 2px solid #8cf;
}
li.ProseMirror-selectednode {
outline: none;
}
li.ProseMirror-selectednode:after {
content: "";
position: absolute;
inset: -2px -2px -2px -32px;
border: 2px solid #8cf;
pointer-events: none;
}
img.ProseMirror-separator {
display: inline !important;
border: none !important;
margin: 0 !important;
}
</style>
Original file line number Diff line number Diff line change
@@ -959,6 +959,25 @@ export const PublicationConfig = {
];
},
},
editors: {
getPrimaryItems: ({
submission,
selectedPublication,
pageInitConfig,
permissions,
}) => {
return [
{
component: 'WorkflowPublicationEditor',
props: {
canEdit: permissions.canEditPublication,
submission,
publication: selectedPublication,
},
},
];
},
},
galleys: {
getPrimaryItems: ({submission, selectedPublication, permissions}) => {
return [
Original file line number Diff line number Diff line change
@@ -250,6 +250,13 @@ export function useWorkflowNavigationConfigOJS(pageInitConfig) {
}),
);

items.push(
getPublicationItem({
name: 'editors',
label: 'Fulltext Editor',
}),
);

if (permissions.canAccessProduction) {
items.push(
getPublicationItem({