Skip to content

[6.x] Publish Forms (continued) #11851

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

Merged
merged 10 commits into from
Jun 9, 2025
6 changes: 3 additions & 3 deletions resources/js/bootstrap/globals.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { marked } from 'marked';
import { translate, translateChoice } from '../translations/translator';
import uid from 'uniqid';
import PreviewHtml from '../components/fieldtypes/replicator/PreviewHtml';
import renderMarkdown from '@statamic/util/markdown.js';

export function cp_url(url) {
url = Statamic.$config.get('cpUrl') + '/' + url;
Expand Down Expand Up @@ -80,8 +80,8 @@ export function field_width_class(width) {
return `${widths[width] || 'field-w-100'}`;
}

export function markdown(value) {
return marked(value);
export function markdown(value, options = {}) {
return renderMarkdown(value, options);
}

export function __(string, replacements) {
Expand Down
5 changes: 3 additions & 2 deletions resources/js/bootstrap/statamic.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import Permission from '../components/Permission';
import autosize from 'autosize';
import DateFormatter from '@statamic/components/DateFormatter.js';
import wait from '@statamic/util/wait.js';
import markdown from '@statamic/util/markdown.js';

let bootingCallbacks = [];
let bootedCallbacks = [];
Expand Down Expand Up @@ -187,8 +188,8 @@ export default {
__n(key, number, replacements) {
return __n(key, number, replacements);
},
$markdown(value) {
return markdown(value);
$markdown(value, options = {}) {
return markdown(value, options);
},
cp_url(url) {
return cp_url(url);
Expand Down
2 changes: 1 addition & 1 deletion resources/js/components/fieldtypes/ToggleFieldtype.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div class="flex items-center gap-2">
<Switch :model-value="value" @update:model-value="update" :id="fieldId" :disabled="isReadOnly" />
<Heading v-if="inlineLabel" v-html="$markdown(__(inlineLabel))" />
<Heading v-if="inlineLabel" v-html="$markdown(__(inlineLabel), { openLinksInNewTabs: true })" />
</div>
</template>

Expand Down
3 changes: 3 additions & 0 deletions resources/js/components/ui/Field.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { cva } from 'cva';
import { computed } from 'vue';
import { Description, Label } from '@statamic/components/ui/index.js';
import markdown from '@statamic/util/markdown.js';

defineOptions({
inheritAttrs: false,
Expand Down Expand Up @@ -80,6 +81,8 @@ const classes = computed(() =>
},
})({ ...props }),
);

const instructions = computed(() => props.instructions ? markdown(props.instructions, { openLinksInNewTabs: true }) : null);
</script>

<template>
Expand Down
16 changes: 14 additions & 2 deletions resources/js/components/ui/Publish/Field.vue
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,18 @@ const shouldShowField = computed(() => {
return new ShowField(store, values.value, extraValues.value).showField(props.config, fullPath.value);
});

const shouldShowLabelText = computed(() => !props.config.hide_display);

const shouldShowLabel = computed(
() =>
shouldShowLabelText.value || // Need to see the text
isReadOnly.value || // Need to see the "Read Only" text
isRequired.value || // Need to see the asterisk
isLocked.value || // Need to see the avatar
isLocalizable.value || // Need to see the icon
isSyncable.value, // Need to see the icon
);

const isLocalizable = computed(() => props.config.localizable);

const isReadOnly = computed(() => {
Expand Down Expand Up @@ -104,8 +116,8 @@ function desync() {
:disabled="isReadOnly"
>
<template #label>
<Label :for="fieldId" :required="isRequired">
{{ __(config.display) }}
<Label v-if="shouldShowLabel" :for="fieldId" :required="isRequired">
<template v-if="shouldShowLabelText">{{ __(config.display) }}</template>
<button v-if="!isReadOnly && isSyncable" v-show="isSynced" @click="desync">
<Tooltip :text="__('messages.field_synced_with_origin')">
<Icon name="synced" class="text-gray-400" />
Expand Down
13 changes: 12 additions & 1 deletion resources/js/components/ui/Publish/Form.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Container from './Container.vue';
import Tabs from './Tabs.vue';
import { Header, Button } from '@statamic/ui';
import uniqid from 'uniqid';
import { ref, useTemplateRef } from 'vue';
import { onMounted, onUnmounted, ref, useTemplateRef } from 'vue';
import { SavePipeline } from '@statamic/exports.js';
const { Pipeline, Request, BeforeSaveHooks, AfterSaveHooks } = SavePipeline;

Expand Down Expand Up @@ -55,6 +55,17 @@ function save() {
Statamic.$toast.success('Saved');
});
}

let saveKeyBinding;

onMounted(() => {
saveKeyBinding = Statamic.$keys.bindGlobal(['mod+s'], (e) => {
e.preventDefault();
save();
});
});

onUnmounted(() => saveKeyBinding.destroy());
</script>

<template>
Expand Down
17 changes: 15 additions & 2 deletions resources/js/components/ui/Publish/Sections.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,31 @@ import { injectTabContext } from './TabProvider.vue';
import { CardPanel } from '@statamic/ui';
import FieldsProvider from './FieldsProvider.vue';
import Fields from './Fields.vue';
import ShowField from '@statamic/components/field-conditions/ShowField.js';
import { injectContainerContext } from './Container.vue';
import markdown from '@statamic/util/markdown.js';

const { blueprint, store } = injectContainerContext();
const tab = injectTabContext();
const sections = tab.sections;
const visibleSections = sections.filter(section => {
return section.fields.some((field) => {
return new ShowField(store, store.values, store.extraValues).showField(field, field.handle);
});
});

function renderInstructions(instructions) {
return instructions ? markdown(instructions, { openLinksInNewTabs: true }) : '';
}
</script>

<template>
<div>
<CardPanel
v-for="(section, i) in sections"
v-for="(section, i) in visibleSections"
:key="i"
:heading="section.display"
:subheading="section.instructions"
:subheading="renderInstructions(section.instructions)"
class="mb-6"
>
<FieldsProvider :fields="section.fields">
Expand Down
16 changes: 13 additions & 3 deletions resources/js/components/ui/Publish/Tabs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { injectContainerContext } from './Container.vue';
import Sections from '@statamic/components/ui/Publish/Sections.vue';
import { ref, computed, useSlots } from 'vue';
import ElementContainer from '@statamic/components/ElementContainer.vue';
import ShowField from '@statamic/components/field-conditions/ShowField.js';

const slots = useSlots();
const { blueprint, store } = injectContainerContext();
Expand All @@ -14,6 +15,15 @@ const sidebarTab = computed(() => tabs.value.find((tab) => tab.handle === 'sideb
const mainTabs = computed(() =>
shouldShowSidebar.value && sidebarTab.value ? tabs.value.filter((tab) => tab.handle !== 'sidebar') : tabs.value,
);
const visibleMainTabs = computed(() => {
return mainTabs.value.filter((tab) => {
return tab.sections.some((section) => {
return section.fields.some((field) => {
return new ShowField(store, store.values, store.extraValues).showField(field, field.handle);
});
});
});
});
const shouldShowSidebar = computed(() => (slots.sidebar || sidebarTab.value) && width.value > 920);

const fieldTabMap = computed(() => {
Expand Down Expand Up @@ -48,10 +58,10 @@ function tabHasError(tab) {

<template>
<ElementContainer @resized="width = $event.width">
<Tabs :default-tab="mainTabs[0].handle">
<TabList v-if="mainTabs.length > 1" class="mb-6">
<Tabs :default-tab="visibleMainTabs[0].handle">
<TabList v-if="visibleMainTabs.length > 1" class="mb-6">
<TabTrigger
v-for="tab in mainTabs"
v-for="tab in visibleMainTabs"
:key="tab.handle"
:name="tab.handle"
:text="tab.display"
Expand Down
15 changes: 15 additions & 0 deletions resources/js/util/markdown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { marked } from 'marked';

export default function (markdown, options = {}) {
const renderer = new marked.Renderer();

if (options.openLinksInNewTabs) {
renderer.link = function(href, title, text) {
return marked.Renderer.prototype.link
.call(this, href, title, text)
.replace("<a", "<a target='_blank' ");
};
}

return marked.parse(markdown, { renderer });
}
Loading