Giter VIP home page Giter VIP logo

field-plugin's Introduction

Welcome to Storyblok

Storyblok is a visual CMS that works with any framework. Integrate with any app, frontend, or framework. Publish anywhere with an API-first backend. Storyblok’s industry-leading Visual Editor makes it easy for marketing teams to independently create, edit, and collaborate.

Getting Started

Start with your favorite technology

The Storyblok Next.js Ultimate Tutorial

The Storyblok Nuxt Ultimate Tutorial

The Storyblok SvelteKit Ultimate Tutorial

The Storyblok Gatsby Ultimate Tutorial

The Storyblok Laravel Ultimate Tutorial

💡 Try it out for free

Why Storyblok?

  • Work with any technology: Storyblok’s headless, API-first CMS architecture empowers developers to work with any technology and integrate with any third-party solution.
  • Scale without limits: Storyblok monitors your applications and automatically scales performance to ensure optimal efficiency and performance.
  • Flexible data schemas: Storyblok's component-based approach gives you full control over your content structure. You can define your own custom data models with nestable components that can be reused across all your projects.
  • Publish faster: Marketing and content teams work faster with a Visual Editor enabling them to work independently. No more content tickets in your backlog.
  • Enterprise security: Ensure data security using one of the most secure, enterprise-grade CMSs available on the market. Storyblok is ISO 27001 certified.
  • Deliver Better Experiences: Personalize content experiences for different markets, languages, or audience segments using Storyblok's built-in localization tools, or integrate with any third-party solution through API-first integrations.

How it works

Headless CMS is a back-end-only content management system (CMS) built from the ground up as a content repository that makes content accessible via APIs.

A basic headless CMS Architecture:

A basic headless CMS architecture

Storyblok CMS architecture:

Storyblok CMS architecture

Key Features

Composable Architecture:

  • APIs: Work with any frontend or third-party integration with GraphQL, REST, and Management API.
  • Flexible backend: As a headless content management system, Storyblok can manage and serve content for any app or site.
  • Apps: Add extra functionalities to your space through a suite of custom apps available for free on the Storyblok App Directory, or build your own.
  • Composable components: Easily define new nestable blocks (such as a hero, grid, or button) or content type blocks (such as an article, landing page, or product page). Create once, reuse everywhere. The limit is your imagination. Learn more.

Streamline Workflows:

  • Visual editing interface: Storyblok enables non-technical users to build and edit JSON structures with an easy-to-use visual interface. Learn more.
  • Component Library: Find, access, and edit components directly from the Visual Editor making it easier for teams to collaborate.
  • Collaboration workflows: Publish faster with inclusive collaboration workflows that give anyone on the team a simple way to make a suggestion or take action.

Audience Experiences:

  • Image Service: Make apps and websites faster by Transforming, optimizing, and caching images in a CDN. Learn more.
  • Internationalization: Create personalized content experiences via built-in folder-level and field-level internationalization. Learn more.
  • Omnichannel Experiences: Storyblok’s headless architecture enables developers to publish content across any digital channel via APIs. Learn more.

Resources

We are Hiring

field-plugin's People

Contributors

allcontributors[bot] avatar bibisebi avatar demetriusfeijoo avatar dependabot[bot] avatar eunjae-lee avatar hoersamu avatar johannes-lindgren avatar plitzenberger avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

field-plugin's Issues

Extending `data.content` without losing type-safety

Is your feature request related to a problem? Please describe.
Hey! I know this project is in alpha stage, but I've been using it to create some plugins and it works like a charm, much better than the legacy method. Great work!

Since the templates are written in TypeScript, would be nice to have generic types, specially to customize the useFieldPlugin().data.content (which is unknown) without losing type-safety. In your templates you treat the content as number to store the value of the counter. In my case, I would like to store an object instead.

What I've done to achieve that is modifying the FieldPluginProvider.vue (vue3 template) and useFieldPlugin.ts to inject my custom types. By doing this, I have safe autocompletion in useFieldPlugin().data.content and useFieldPlugin().data.setContent().

image

I made this codesandbox to show my workaround, based on the vue3 template.

Files of interest:
src/types.ts
src/useFieldPlugin.ts
src/components/FieldPluginProvider.vue
src/components/Counter.vue
src/components/Foo.vue

Describe the solution you'd like
If you see src/types.ts, I added an interface (PluginContent) for my custom content, and rewrite FieldPluginData, FieldPluginActions and FieldPluginResponse to include the PluginContent. Also I updated some pieces in the createFieldPlugin callback function used in FieldPluginProvider.vue.

Instead rewriting those types and monkey-patching that callback would be nicer to do something like:

const plugin = reactive<PluginResponse<MyContent>>({
  type: 'loading',
});

createFieldPlugin<MyContent>(() => {})

Not sure that would be the best solution, it's just an idea.

Describe alternatives you've considered
Nothing else

Additional context
Nothing else

Possibility to edit complete data structure in Field Plugin Sandbox

Is your feature request related to a problem? Please describe.
Currently the Field Plugin Sandbox only displays the content and the data.
I would suggest for a possibility to enter data.
Not a problem, but would help to develop plugins, that access content of the current story.

Describe the solution you'd like
The complete data structure (incl. content) should be editable and provided to the field plugin as storyblok would do it in real life.

Describe alternatives you've considered
Currently the data will be taken from an .env.local file and "simulated" that this data comes from stroyblok

Extend CLI with --publish flag option configurable

Is your feature request related to a problem? Please describe.

As we see the publish: true is enabled in CLI (https://github.com/storyblok/field-plugin/blob/main/packages/cli/src/commands/deploy/helper.ts#L83C7-L83C21), this it is not possible to push an update of the Plugin in draft level, thus it gets instantly published, which may not align with the way teams may use it in CI automations.

Describe the solution you'd like

It should be possible to define --publish false (though by default it is enabled, that is fine), so the release process would be 2 steps:

  1. CI automation pushes new version of plugin after monorepo project tag creation in "draft" level
  2. Release manager or QA makes sure the plugin is as expected
  3. Manually publish a certain version to go live.

Describe alternatives you've considered

No alternatives, we have to be sure the version we push is the one we want to appear on production, thus there is no doublecheck step or other flows possible.

Additional context

Severity: minor.

Vue 3: Sandbox Reactivity Issues

Describe the bug
When updating Vue Refs to update page content in the Sandbox, the Refs update, but the Sandbox doesn't as it usually would in a vue 3 project. For instance, I am using the Cloudinary Media Library, and when an asset is returned, it is added to the assetList ref. I am then using a v-for in my template to display each item in the assetList. However, once a new item is added (or removed) from the ref, the Sandbox doesn't reflect that change. I have to then hot reload the code in order to force update it to reflect the new content.

To Reproduce
Steps to reproduce the behavior:

  1. Create a Vue 3 plugin using the field plugin CLI
  2. Create a Ref/other reactive element
  3. Have it display in your Vue template
  4. Add a button/functionality to change the reactive element within the sandbox during runtime.
  5. The reactive element will update in Vue, but the page will not reflect the up to date element, it will remain as it initially did.

Expected behavior
Once reactive vue elements are updated, the sandbox should display them as so.

I've set up a simple example below with a counter (which is initialised as const counter = ref(0);) & button to demonstrate (the counter ref is updating, but the sandbox is not. However, if i change something, change it back & hot reload it updates to what it should be in the Sandbox)

Screenshots

image

Desktop (please complete the following information):

  • OS: Windows 10 Enterprise
  • Browser: Chrome
  • Version: Version 115.0.5790.110

Additional context
I am new to working with the Field Plugin Sandbox & creating custom Storyblok plugins so please let me know if it's something I'm going wrong with on my end with the plugin/need to do to rectify. thankyou!

update: found the issue & rectified. it was a vue onMounted error causing the issue. thanks :)

Multirepo pnpm install fails after creation

Describe the bug
Create fails for pnpm due to missing version constraint for the package manager field in the package.json

Error:

✖ Running `pnpm install`..
file:///Users/xxx/.npm/_npx/ca700ea613ccf9d4/node_modules/execa/lib/error.js:59
		error = new Error(message);
		        ^

Error: Command failed with exit code 1: pnpm install
Usage Error: Invalid package manager specification in ../../package.json; expected a semver version

$ pnpm ...
    at makeError (file:///Users/xxx/.npm/_npx/ca700ea613ccf9d4/node_modules/execa/lib/error.js:59:11)
    at handlePromise (file:///Users/xxx/.npm/_npx/ca700ea613ccf9d4/node_modules/execa/index.js:119:26)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async S (/Users/xxx/.npm/_npx/ca700ea613ccf9d4/node_modules/@storyblok/field-plugin-cli/dist/main.cjs:1:1594)
    at async R (/Users/xxx/.npm/_npx/ca700ea613ccf9d4/node_modules/@storyblok/field-plugin-cli/dist/main.cjs:7:885)
    at async Pe (/Users/xxx/.npm/_npx/ca700ea613ccf9d4/node_modules/@storyblok/field-plugin-cli/dist/main.cjs:15:77)
    at async Te (/Users/xxx/.npm/_npx/ca700ea613ccf9d4/node_modules/@storyblok/field-plugin-cli/dist/main.cjs:17:401)
    at async Command.<anonymous> (/Users/xxx/.npm/_npx/ca700ea613ccf9d4/node_modules/@storyblok/field-plugin-cli/dist/main.cjs:20:3468) {
  shortMessage: 'Command failed with exit code 1: pnpm install',
  command: 'pnpm install',
  escapedCommand: 'pnpm install',
  exitCode: 1,
  signal: undefined,
  signalDescription: undefined,
  stdout: 'Usage Error: Invalid package manager specification in ../../package.json; expected a semver version\n' +
    '\n' +
    '$ pnpm ...',
  stderr: '',
  failed: true,
  timedOut: false,
  isCanceled: false,
  killed: false
}

To Reproduce
Steps to reproduce the behavior:

  1. run npx @storyblok/field-plugin-cli@latest
  2. Select pnpm
  3. Select multirepo, vue 3 (looking at the code this problem probably exists for multiple templates)
  4. See error

Expected behavior
Pnpm install starts and succeds.

Desktop (please complete the following information):

  • OS: macOS (13 and 14)
  • Versions: Node 18.15.0 with pnpm 8.6.5

Visual Editor does not detect changes in custom field plugin

Describe the bug
I have following behavior with my custom field plugin:
The Visual Editor does not detect changes if the content of the field plugin changes

Created a react field plugin that returns an object like {A:stringA, b:stringB}.

In the plugin the state will be stored with useState

const [value, setValue] = useState<>({A: '',B: ''})

every time the value changes the setContent function will be called via an useEffect

  useEffect(() => {
    actions?.setContent(value)
  }, [value])

To Reproduce
Steps to reproduce the behavior:

  1. Create a blok with a custom field plugin
  2. Add the blok to a story
  3. Change a value in the field plugin
  4. "Save" button keeps state - signaling that there is no change

Expected behavior
"Save" button of Visual Editor should change to a different state - signaling that there are changes in the story

Vue3 Template - Failed to mount component: template or render function not defined.

Describe the bug
When trying to run a vue3 plugin, it results in an error.
image

To Reproduce
Steps to reproduce the behavior:

  1. Run npx @storyblok/field-plugin-cli@alpha
  2. Go into the new field plugin project with cd {what-ever-you-named-it}
  3. Run yarn build
  4. CHeck the errors

Expected behavior
I expect no errors.

Screenshots
image
image

Desktop (please complete the following information):

  • OS: Windows 11
  • Browser: Chrome
  • Version: 111.0.5563.111

Additional context
I have no idea if this actually causes it to not work properly, or if its just an error with no affect.

[sandbox] Preserve settings in URL query parameters for easy sharing

Is your feature request related to a problem? Please describe.

To ensure smooth QA process, we have a need to share the sandbox URLs to other people with the settings preserved, hence it is not possible to have it now, which makes it inconvenient to share link and share what to enter to settings to test out different look or configuration of the plugin for QA or other developers.

Describe the solution you'd like
A clear and concise description of what you want to happen.

Whenever anything changes in "Settings" (manifest / translatable toggle / language) changes, preserve the state in URL query parameters.

Additional context

Screen.Recording.2024-03-21.at.16.44.10.mov

Use data source for options

Currently the only way to provide options to a plugin seems to be through "Self" and entering the individual options for each instance of a plugin. This becomes extremely tedious and error-prone when having more than very frew instances of a plugin.

In the field settings pane it is possible to switch from "Self" to "Datasource" (amongst others). So we thought that would be the perfect way to use a datasource. That way we only have to select the correct data source and when something changes (external API URL in our case) only the datasource has to be updated.

There does not seem to be a good way to centrally manage settings like that – for standard field types like Single-Option this works very well and we'd like to have the same ease of use for custom fields…

Extend CLI to enable deleting field-type plugins

Is your feature request related to a problem? Please describe.

There is a way to publish (creates new or updates existing one), but there is no way to delete plugins via CLI, hence only via admin panel.

Describe the solution you'd like

Add possibility to delete plugin by name (or id (?), but name makes more sense as the publishing happens by stating the name) via CLI

Vue3 Template issues

Vue3 Template issues

Describe the bug

A collection of bugs with the vue3 template.

To Reproduce

Steps to reproduce the behavior:

  1. Run npx @storyblok/field-plugin-cli@alpha --template vue3
  2. Run cd ./nameoffieldtemplate
  3. Run yarn dev

Issues

[@vue/compiler-sfc] defineProps is a compiler macro and no longer needs to be imported."

image
Fix: Remove all explicit imports of defineProps.

Building with vue3 results in a non working field plugin where it infinite loads

image
No known fix.
How to reproduce

  1. Follow the steps to reproduce above.
  2. Run yarn build
  3. Copy the index.js file.
  4. Paste it into storyblok.
    Additonal info about this issue:
    image

Access FieldPlugin options from within validateContent

Describe the solution you'd like
I would like to be able to access FieldPlugin options from within the validateContent function.

The reason is i've got a plugin that selects objects, and i was thinking about having an option that states if it should be an single or multiselect. And if multiple, the validation creates an array, if single its just a string.

Describe alternatives you've considered
...

Additional context
...

Cannot find module '@storyblok/field-plugin/test' or its corresponding type declarations.

Describe the bug
I just bootstrapped a new custom field plug-in. When running pnpm build the task fails, because @storyblok/field-plugin/test could not be found.
A clear and concise description of what the bug is.

To Reproduce
Steps to reproduce the behavior:

  1. Run pnpm dlx @storyblok/field-plugin-cli@latest create with options pnpm and vue3.
  2. Run pnpm build
  3. The build task crashes with:
src/components/FieldPluginExample/index.spec.ts:4:34 - error TS2307: Cannot find module '@storyblok/field-plugin/test' or its corresponding type declarations.

Expected behavior
Bootstrapping an empty custom field works as described in the documentation.

Screenshots
I first discovered the problem after following the guide regarding Continuous Delivery:
image
After doing some debugging I realized that I do not get auto-completion for the test-helpers package at all:
image
There is also no test folder in the distribution release:
image

Desktop (please complete the following information):

  • OS: macOS Sonoma 14.1.1 on Macbook Air 2020 M1
  • Node: 21.5.0
  • pnpm: 8.14.0
  • @storyblok/field-plugin: 1.0.1

Additional context
I did a bit of debugging into

const copyHelpersToRootDist = async () => {
const cwd = path.resolve(__dirname)
for (const mod of SUBMODULES) {
await execaCommand(`cd ../dist && mkdir -p ${mod}`, { cwd, shell: true })
await execaCommand(`cp ./dist/${mod}/src/* ../dist/${mod}/`, {
cwd,
shell: true,
})
}
and still wonder what's the difference between the test-package and the others?

Wrong modal iframe heigth

Describe the bug
The height of the iframe doesn't fill the available height of the modal.

To Reproduce
Steps to reproduce the behavior:

  1. Create a new field plugin running npx @storyblok/field-plugin-cli@latest create
  2. Select React (I don't think it matters, but only tested with the React template)
  3. Run pnpm dev
  4. Open sandbox
  5. Open modal.

Expected behavior
The iframe should fill the available height.

Screenshots
image

Desktop (please complete the following information):

  • OS: macOS
  • Browser Edge & Chrome
  • Version 120.0.2210.121 (Official build) (arm64) - Edge browser

Add custom errors hook and capability to prevent saving the page

Is your feature request related to a problem? Please describe.

I have played around with React template and made my first field type plugin in this new new API. Unfortunately, I found out that there is no error interception or some hook to prevent CMS from saving, so I could make custom error handling within the field type plugin.

Describe the solution you'd like
My plugin is much more advanced and acts rather like a widget with input and some more inputs generated dynamically, so I have error handling to prevent invalid cases. The example could look like in the additional context.

My FieldPluginResponse.data.content is not a string, but rather an object {}, so I have to have custom error handling for better and UI with guided output.

I do not want to imply exact solution, but from top of my head there could be some setError (similar to setContent), so CMS could check it before saving the page and would generate the messages queue of single string and/or array of strings which are set by the field plugin. The rest could be part of the usual flow - that error icon next to Publish button to hint user to resolve listed errors.

Additional context

image

Add selected interface app language

Is your feature request related to a problem? Please describe.
When I create a new field type plugin, I have no possibility to deliver e.g. texts, labels, descriptions, buttons in the language of the user, because I do not know the interface language of the user.

Describe the solution you'd like
Maybe add the storyblok interface language from the user to the message that the field type wrapper (parent) sends to the field type (child) via postMessage(). Now you can set the interface language in the Vue or React app and add the correct translations. If the language does not exist in the field plugin you can set a fallback.

Extend CLI with --spaces flag option configurable

Is your feature request related to a problem? Please describe.

We do keep Field-types in Organisation level (https://app.storyblok.com/#/me/org/fields), which is accessible ONLY for users having Admin level.
Multiple developers can contribute to plugin monorepo, and they should be able to push new plugins in automated way via CLI only with no need to go to Admin panel to configure them, hence they must be able to have plugin assigned to some certain spaces via CLI.

Describe the solution you'd like

Extend CLI with --spaces flag option to instantly assign plugin to certain spaces, f.e

--spaces 0123456

or multiple:

--spaces 0123456,0123457,0123458

Additional context

Severity: high.

Vue3 plugin options from useFieldPlugin hook is `undefined`

Describe the bug
The options object from the useFieldPlugin is continuously undefined in my field plugins. I logged out the type also and I can see that it's stuck in a loading value.

I'm experiencing this on with the version "@storyblok/field-plugin": "1.0.1" and "vue": "^3.2.47". I also created a new project using version "@storyblok/field-plugin": "1.0.2",.

I really would love to get a fix for this as we need to use the same plugin for multiple StoryBlok spaces so we are relying on the options to switch the credentials.

To Reproduce
Steps to reproduce the behavior:

Log out the options object from the useFieldPlugin as shown below;

  <script setup lang="ts">
  import type { SetModalOpen } from '@storyblok/field-plugin'
  import { useFieldPlugin } from '@storyblok/field-plugin/vue3';
  
  const { data: pluginData, type: pluginType } = useFieldPlugin()
  
  console.log("PLUGIN OPTIONS", pluginData?.options);
  
  const props = defineProps<{
    isModalOpen: boolean
    setModalOpen: SetModalOpen<any>
  }>()
  </script>

Expected behavior
The options object should have the properties defined in the following field-plugin.config.json` file;

{
  "options": [
    {
      "name": "API_URL",
      "value": ""
    },
      {
        "name": "API_KEY",
        "value": ""
      }
  ]
}

Screenshots

Screenshot 2024-02-17 at 12 58 16

Additional context

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.