├── resources
├── templates
│ ├── component
│ │ ├── _{{componentName}}.scss.mustache
│ │ ├── {{componentName}}.md.mustache
│ │ ├── {{componentName}}.tsx.mustache
│ │ ├── {{componentName}}.spec.tsx.mustache
│ │ └── {{componentName}}.stories.tsx.mustache
│ └── reducer
│ │ ├── action-types.ts.mustache
│ │ ├── actions.ts.mustache
│ │ ├── types.ts.mustache
│ │ └── index.ts.mustache
├── icons
│ ├── store.png
│ ├── store@2x.png
│ ├── component.png
│ └── component@2x.png
└── META-INF
│ └── plugin.xml
├── .gitignore
├── doc
├── settings.png
├── create-dialog.png
├── create-menu.png
├── setup
│ ├── step1.png
│ ├── step10.png
│ ├── step11.png
│ ├── step12.png
│ ├── step13.png
│ ├── step2.png
│ ├── step3.png
│ ├── step4.png
│ ├── step5.png
│ ├── step6.png
│ ├── step7.png
│ ├── step8.png
│ └── step9.png
├── component-files.png
├── create_reducer.gif
├── create_component.gif
└── DEVELOPMENT.md
├── lib
├── jmustache-1.14.jar
├── jmustache-1.14-javadoc.jar
└── jmustache-1.14-sources.jar
├── src
└── io
│ └── fabs
│ ├── util
│ ├── settings
│ │ ├── SerializableOptions.java
│ │ ├── AbstractSettingsForm.java
│ │ ├── AbstractPersistentState.java
│ │ └── AbstractSettingsUI.java
│ ├── AbstractOptions.java
│ ├── TemplateUtils.java
│ ├── TemplateRenderer.java
│ ├── StringFormatter.java
│ ├── FileUtils.java
│ ├── AbstractDialog.java
│ ├── Creator.java
│ └── AbstractCreatorAction.java
│ └── react
│ ├── reducer
│ ├── action
│ │ └── ReducerCreatorAction.java
│ ├── data
│ │ ├── ReducerSettingsState.java
│ │ └── ReducerCreateOptions.java
│ ├── settings
│ │ └── ReducerSettings.java
│ └── ui
│ │ ├── CreateReducerForm.java
│ │ ├── SettingsForm.java
│ │ ├── SettingsForm.form
│ │ └── CreateReducerForm.form
│ └── component
│ ├── action
│ └── ComponentCreatorAction.java
│ ├── data
│ ├── ComponentSettingsState.java
│ └── ComponentCreateOptions.java
│ ├── settings
│ └── ComponentSettings.java
│ └── ui
│ ├── CreateComponentForm.java
│ ├── SettingsForm.java
│ ├── CreateComponentForm.form
│ └── SettingsForm.form
├── CHANGE-NOTES.md
├── react-component-creator-plugin.iml
├── LICENSE
└── README.md
/resources/templates/component/_{{componentName}}.scss.mustache:
--------------------------------------------------------------------------------
1 | .{{ componentName }} {
2 |
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | out
3 | react-component-creator-plugin.jar
4 | react-component-creator-plugin.zip
5 | .DS_Store
--------------------------------------------------------------------------------
/doc/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/doc/settings.png
--------------------------------------------------------------------------------
/doc/create-dialog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/doc/create-dialog.png
--------------------------------------------------------------------------------
/doc/create-menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/doc/create-menu.png
--------------------------------------------------------------------------------
/doc/setup/step1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/doc/setup/step1.png
--------------------------------------------------------------------------------
/doc/setup/step10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/doc/setup/step10.png
--------------------------------------------------------------------------------
/doc/setup/step11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/doc/setup/step11.png
--------------------------------------------------------------------------------
/doc/setup/step12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/doc/setup/step12.png
--------------------------------------------------------------------------------
/doc/setup/step13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/doc/setup/step13.png
--------------------------------------------------------------------------------
/doc/setup/step2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/doc/setup/step2.png
--------------------------------------------------------------------------------
/doc/setup/step3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/doc/setup/step3.png
--------------------------------------------------------------------------------
/doc/setup/step4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/doc/setup/step4.png
--------------------------------------------------------------------------------
/doc/setup/step5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/doc/setup/step5.png
--------------------------------------------------------------------------------
/doc/setup/step6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/doc/setup/step6.png
--------------------------------------------------------------------------------
/doc/setup/step7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/doc/setup/step7.png
--------------------------------------------------------------------------------
/doc/setup/step8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/doc/setup/step8.png
--------------------------------------------------------------------------------
/doc/setup/step9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/doc/setup/step9.png
--------------------------------------------------------------------------------
/doc/component-files.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/doc/component-files.png
--------------------------------------------------------------------------------
/doc/create_reducer.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/doc/create_reducer.gif
--------------------------------------------------------------------------------
/lib/jmustache-1.14.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/lib/jmustache-1.14.jar
--------------------------------------------------------------------------------
/doc/create_component.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/doc/create_component.gif
--------------------------------------------------------------------------------
/resources/icons/store.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/resources/icons/store.png
--------------------------------------------------------------------------------
/resources/icons/store@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/resources/icons/store@2x.png
--------------------------------------------------------------------------------
/lib/jmustache-1.14-javadoc.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/lib/jmustache-1.14-javadoc.jar
--------------------------------------------------------------------------------
/lib/jmustache-1.14-sources.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/lib/jmustache-1.14-sources.jar
--------------------------------------------------------------------------------
/resources/icons/component.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/resources/icons/component.png
--------------------------------------------------------------------------------
/resources/icons/component@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/component-creator-plugin/react-component-creator-plugin/HEAD/resources/icons/component@2x.png
--------------------------------------------------------------------------------
/resources/templates/component/{{componentName}}.md.mustache:
--------------------------------------------------------------------------------
1 | # {{ componentName }}
2 |
3 | Description of component
4 |
5 | <{{ componentNamePascalCase }}/>
6 |
--------------------------------------------------------------------------------
/resources/templates/reducer/action-types.ts.mustache:
--------------------------------------------------------------------------------
1 | export enum {{ actionTypesEnumName }} {
2 | {{ mutationType }} = '{{ componentNameCamelCase }}/{{ mutationType }}',
3 | }
4 |
--------------------------------------------------------------------------------
/src/io/fabs/util/settings/SerializableOptions.java:
--------------------------------------------------------------------------------
1 | package io.fabs.util.settings;
2 |
3 | import org.jdom.Element;
4 |
5 | public interface SerializableOptions {
6 | public Element serialize();
7 |
8 | public void deserialize(Element element);
9 | }
10 |
--------------------------------------------------------------------------------
/resources/templates/component/{{componentName}}.tsx.mustache:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export type {{ componentNamePascalCase }}Props = {}
4 |
5 | export default function {{ componentNamePascalCase }}({}: {{ componentNamePascalCase }}Props) {
6 | return (
);
7 | }
8 |
--------------------------------------------------------------------------------
/resources/templates/component/{{componentName}}.spec.tsx.mustache:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { expect } from 'chai';
3 | import {{ componentNamePascalCase }} from './{{ componentName }}';
4 |
5 | describe('Spec {{ componentNamePascalCase }}', function () {
6 | it('it exists', () => {
7 | expect({{ componentNamePascalCase }}).to.be.ok;
8 | });
9 | });
10 |
--------------------------------------------------------------------------------
/resources/templates/reducer/actions.ts.mustache:
--------------------------------------------------------------------------------
1 | import { Dispatch } from 'redux';
2 | import { {{ actionTypesEnumName }} } from './action-types';
3 | import { {{ actionTypeName }} } from './types';
4 |
5 | export const {{ actionFunctionName }} = (data: any) => (dispatch: Dispatch<{{ actionTypeName }}>) => {
6 | dispatch({ type: {{ actionTypesEnumName }}.{{ mutationType }}, data });
7 | };
8 |
--------------------------------------------------------------------------------
/resources/templates/reducer/types.ts.mustache:
--------------------------------------------------------------------------------
1 | import { Action } from 'redux';
2 | import { {{ actionTypesEnumName }} } from './action-types';
3 |
4 | export interface {{ componentNamePascalCase }}State {
5 | data: any;
6 | }
7 |
8 | export type {{ actionTypeName }} = Action< {{ actionTypesEnumName }}.{{ mutationType }}> & {
9 | }
10 |
11 | export type {{ componentNamePascalCase }}Actions = {{ actionTypeName }};
12 |
--------------------------------------------------------------------------------
/resources/templates/component/{{componentName}}.stories.tsx.mustache:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {{ componentNamePascalCase }}, { {{ componentNamePascalCase }}Props } from './{{componentName}}';
3 |
4 | export default {
5 | title: "{{ componentNamePascalCase }}",
6 | component: {{ componentNamePascalCase }}
7 | };
8 |
9 | export const Default = (props: {{ componentNamePascalCase }}Props) => <{{ componentNamePascalCase }} {...props} />;
--------------------------------------------------------------------------------
/src/io/fabs/util/AbstractOptions.java:
--------------------------------------------------------------------------------
1 | package io.fabs.util;
2 |
3 | import io.fabs.util.settings.SerializableOptions;
4 |
5 | import java.util.ArrayList;
6 | import java.util.Map;
7 |
8 | public abstract class AbstractOptions implements SerializableOptions {
9 | abstract public ArrayList getFiles();
10 |
11 | abstract public Map getTemplateVariables();
12 |
13 | public String[] getFileList() {
14 | return getFiles().toArray(new String[getFiles().size()]);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/CHANGE-NOTES.md:
--------------------------------------------------------------------------------
1 | - v1.0.1 Fix default templates for stories
2 | - v1.0.0 Major release. Fix bugs for windows
3 | - v0.6.0 Use component-creator-lib
4 | - Fix windows paths
5 | - Update documentation
6 | - Add camelcase and pascalcase variables for templates
7 | - v0.5.0 Checkboxes checked by default can be configured in the settings
8 | - v0.4.0 Add Customisable templates. Improve a lot of code. Update doc
9 | - v0.2.1 Export enum for action types
10 | - v0.2.1 Export enum for action types
11 | - v0.2.0 Add `Add Redux Reducer` Action
12 | - v0.1.0 Add `Add React Component` Action
13 |
--------------------------------------------------------------------------------
/src/io/fabs/react/reducer/action/ReducerCreatorAction.java:
--------------------------------------------------------------------------------
1 | package io.fabs.react.reducer.action;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import io.fabs.react.reducer.data.ReducerSettingsState;
5 | import io.fabs.react.reducer.ui.CreateReducerForm;
6 | import io.fabs.util.AbstractCreatorAction;
7 | import io.fabs.util.AbstractDialog;
8 |
9 | public class ReducerCreatorAction extends AbstractCreatorAction {
10 | @Override
11 | protected AbstractDialog createDialog(Project project) {
12 | ReducerSettingsState state = ReducerSettingsState.getInstance(project);
13 | return new CreateReducerForm(state.getOptions());
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/io/fabs/react/component/action/ComponentCreatorAction.java:
--------------------------------------------------------------------------------
1 | package io.fabs.react.component.action;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import io.fabs.react.component.data.ComponentSettingsState;
5 | import io.fabs.react.component.ui.CreateComponentForm;
6 | import io.fabs.util.AbstractCreatorAction;
7 | import io.fabs.util.AbstractDialog;
8 |
9 | public class ComponentCreatorAction extends AbstractCreatorAction {
10 | @Override
11 | protected AbstractDialog createDialog(Project project) {
12 | ComponentSettingsState state = ComponentSettingsState.getInstance(project);
13 | return new CreateComponentForm(state.getOptions());
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/io/fabs/util/TemplateUtils.java:
--------------------------------------------------------------------------------
1 | package io.fabs.util;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | public class TemplateUtils {
7 |
8 | /**
9 | * Create map with default transformations of component name
10 | */
11 | public static Map createVariableMap(String componentName) {
12 | Map templateModel = new HashMap<>();
13 | templateModel.put("componentName", componentName);
14 | templateModel.put("componentNameCamelCase", StringFormatter.toCamelCase(componentName));
15 | templateModel.put("componentNamePascalCase", StringFormatter.toPascalCase(componentName));
16 | return templateModel;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/resources/templates/reducer/index.ts.mustache:
--------------------------------------------------------------------------------
1 | import { {{ componentNamePascalCase }}Actions, {{ componentNamePascalCase }}State } from './types';
2 | import { {{ actionTypesEnumName }} } from './action-types';
3 |
4 | export const initialState: {{ componentNamePascalCase }}State = {
5 | data: null,
6 | };
7 |
8 | export default function {{ componentNamePascalCase }}Reducer(state = initialState, action: {{ componentNamePascalCase }}Actions): {{ componentNamePascalCase }}State {
9 | switch (action.type) {
10 | case {{ actionTypesEnumName }}.{{ mutationType }}:
11 | return {
12 | ...state,
13 | };
14 | default:
15 | return state;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/react-component-creator-plugin.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/io/fabs/react/reducer/data/ReducerSettingsState.java:
--------------------------------------------------------------------------------
1 | package io.fabs.react.reducer.data;
2 |
3 | import com.intellij.openapi.components.ServiceManager;
4 | import com.intellij.openapi.components.State;
5 | import com.intellij.openapi.components.Storage;
6 | import com.intellij.openapi.project.Project;
7 | import io.fabs.util.settings.AbstractPersistentState;
8 |
9 | @State(
10 | name = "ReducerSettings",
11 | storages = {
12 | @Storage("/rcc.xml")
13 | }
14 | )
15 | public class ReducerSettingsState extends AbstractPersistentState {
16 |
17 | public ReducerSettingsState() {
18 | super(new ReducerCreateOptions());
19 | }
20 |
21 | public static ReducerSettingsState getInstance(Project project) {
22 | return ServiceManager.getService(project, ReducerSettingsState.class);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/io/fabs/react/component/data/ComponentSettingsState.java:
--------------------------------------------------------------------------------
1 | package io.fabs.react.component.data;
2 |
3 | import com.intellij.openapi.components.ServiceManager;
4 | import com.intellij.openapi.components.State;
5 | import com.intellij.openapi.components.Storage;
6 | import com.intellij.openapi.project.Project;
7 | import io.fabs.util.settings.AbstractPersistentState;
8 |
9 | @State(
10 | name = "ComponentSettings",
11 | storages = {
12 | @Storage("/rcc.xml")
13 | }
14 | )
15 | public class ComponentSettingsState extends AbstractPersistentState {
16 |
17 | public ComponentSettingsState() {
18 | super(new ComponentCreateOptions());
19 | }
20 |
21 | public static ComponentSettingsState getInstance(Project project) {
22 | return ServiceManager.getService(project, ComponentSettingsState.class);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/io/fabs/react/reducer/settings/ReducerSettings.java:
--------------------------------------------------------------------------------
1 | package io.fabs.react.reducer.settings;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import io.fabs.react.reducer.data.ReducerCreateOptions;
5 | import io.fabs.react.reducer.data.ReducerSettingsState;
6 | import io.fabs.react.reducer.ui.SettingsForm;
7 | import io.fabs.util.settings.AbstractSettingsForm;
8 | import io.fabs.util.settings.AbstractSettingsUI;
9 |
10 | public class ReducerSettings extends AbstractSettingsUI {
11 | public ReducerSettings(Project project) {
12 | super(project, "Redux Reducer");
13 | }
14 |
15 | @Override
16 | public ReducerCreateOptions getOptions() {
17 | return ReducerSettingsState.getInstance(project).getOptions();
18 | }
19 |
20 | @Override
21 | public AbstractSettingsForm createUi() {
22 | return new SettingsForm(getOptions());
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/io/fabs/react/component/settings/ComponentSettings.java:
--------------------------------------------------------------------------------
1 | package io.fabs.react.component.settings;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import io.fabs.react.component.data.ComponentCreateOptions;
5 | import io.fabs.react.component.ui.SettingsForm;
6 | import io.fabs.react.component.data.ComponentSettingsState;
7 | import io.fabs.util.settings.AbstractSettingsForm;
8 | import io.fabs.util.settings.AbstractSettingsUI;
9 |
10 | public class ComponentSettings extends AbstractSettingsUI {
11 |
12 | public ComponentSettings(Project project) {
13 | super(project, "Component");
14 | }
15 |
16 | @Override
17 | public ComponentCreateOptions getOptions() {
18 | return ComponentSettingsState.getInstance(project).getOptions();
19 | }
20 |
21 | @Override
22 | public AbstractSettingsForm createUi() {
23 | return new SettingsForm(getOptions());
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/io/fabs/util/settings/AbstractSettingsForm.java:
--------------------------------------------------------------------------------
1 | package io.fabs.util.settings;
2 |
3 | import io.fabs.util.AbstractOptions;
4 |
5 | import javax.swing.*;
6 | import java.awt.event.ActionEvent;
7 |
8 | public abstract class AbstractSettingsForm {
9 | private JFileChooser fileChooser;
10 | protected T options;
11 |
12 | public AbstractSettingsForm(T options) {
13 | this.options = options;
14 | fileChooser = new JFileChooser();
15 | }
16 |
17 | public abstract JComponent getMainPanel();
18 |
19 | public abstract boolean isDirty();
20 |
21 | public abstract void applySettings(T options);
22 |
23 | protected void onBrowseButtonClicked(ActionEvent e, JTextField input) {
24 | if (fileChooser.showOpenDialog(getMainPanel()) == JFileChooser.APPROVE_OPTION) {
25 | input.setText(fileChooser.getSelectedFile().getAbsolutePath());
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/io/fabs/util/TemplateRenderer.java:
--------------------------------------------------------------------------------
1 | package io.fabs.util;
2 |
3 | import com.samskivert.mustache.Mustache;
4 | import com.samskivert.mustache.Template;
5 |
6 | import java.io.FileNotFoundException;
7 | import java.util.Map;
8 |
9 | public class TemplateRenderer {
10 | /**
11 | * Render a template
12 | */
13 | public static String render(String file, Map context) throws FileNotFoundException {
14 | FileUtils utils = new FileUtils();
15 | Template tmpl = Mustache.compiler().compile(utils.getContent(file));
16 | return tmpl.execute(context);
17 | }
18 |
19 | /**
20 | * Transform a filename
21 | */
22 | public static String transformTemplateName(String templateString, Map variables) {
23 | String[] parts = templateString.split("/");
24 | String fileName = parts[parts.length - 1];
25 | fileName = fileName.replace(".mustache", "");
26 | Template tmpl = Mustache.compiler().compile(fileName);
27 | return tmpl.execute(variables);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/io/fabs/util/settings/AbstractPersistentState.java:
--------------------------------------------------------------------------------
1 | package io.fabs.util.settings;
2 |
3 | import com.intellij.openapi.components.PersistentStateComponent;
4 | import org.jdom.Element;
5 | import org.jetbrains.annotations.NotNull;
6 | import org.jetbrains.annotations.Nullable;
7 |
8 | public abstract class AbstractPersistentState implements PersistentStateComponent {
9 | private T options;
10 |
11 | public AbstractPersistentState(T options) {
12 | this.options = options;
13 | }
14 |
15 | public T getOptions() {
16 | return options;
17 | }
18 |
19 | /**
20 | * Called when the state has to be persisted
21 | */
22 | @Nullable
23 | @Override
24 | public Element getState() {
25 | return options.serialize();
26 | }
27 |
28 | /**
29 | * Called when the settings start, and the data is loaded from store
30 | */
31 | @Override
32 | public void loadState(@NotNull Element element) {
33 | options.deserialize(element);
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/io/fabs/util/StringFormatter.java:
--------------------------------------------------------------------------------
1 | package io.fabs.util;
2 | import com.google.common.base.CaseFormat;
3 |
4 |
5 | public class StringFormatter {
6 | public static String toCamelCase(String input) {
7 | return CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, input);
8 | }
9 |
10 | public static String toPascalCase(String input) {
11 | return CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, input);
12 | }
13 |
14 | public static String toDashCase(String input) {
15 | StringBuffer sb = new StringBuffer();
16 | int c = 0;
17 | for (String s : input.split("-")) {
18 | if (c != 0) {
19 | sb.append("_");
20 | }
21 |
22 | sb.append(Character.toLowerCase(s.charAt(0)));
23 | if (s.length() > 1) {
24 | sb.append(s.substring(1, s.length()).toLowerCase());
25 | }
26 | c++;
27 | }
28 | return sb.toString();
29 | }
30 |
31 | public static String capitalizeFirst(String input) {
32 | return input.substring(0, 1).toUpperCase() + input.substring(1);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2020 Fabio Gianini
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/io/fabs/util/FileUtils.java:
--------------------------------------------------------------------------------
1 | package io.fabs.util;
2 |
3 | import com.intellij.openapi.vfs.VirtualFile;
4 |
5 | import java.io.*;
6 | import java.util.Scanner;
7 |
8 | public class FileUtils {
9 |
10 | /**
11 | * Get the file content
12 | */
13 | public String getContent(String filePath) throws FileNotFoundException {
14 | StringBuilder result = new StringBuilder("");
15 | InputStream resourceStream = getClass().getResourceAsStream(filePath);
16 | System.out.println(filePath);
17 |
18 | Scanner scanner = new Scanner(resourceStream);
19 |
20 | while (scanner.hasNextLine()) {
21 | String line = scanner.nextLine();
22 | result.append(line).append("\n");
23 | }
24 |
25 | scanner.close();
26 | return result.toString();
27 | }
28 |
29 | public static void writeFile(String content, VirtualFile destinationFile) throws IOException {
30 | destinationFile.setBinaryContent(content.getBytes());
31 | }
32 |
33 | public static boolean fileExists(String filePath) {
34 | File tmpDir = new File(filePath);
35 | return tmpDir.exists();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/io/fabs/util/AbstractDialog.java:
--------------------------------------------------------------------------------
1 | package io.fabs.util;
2 |
3 | import javax.swing.*;
4 | import java.awt.event.WindowAdapter;
5 | import java.awt.event.WindowEvent;
6 |
7 | public abstract class AbstractDialog extends JDialog {
8 | protected T options;
9 |
10 | public AbstractDialog(T options) {
11 | super();
12 | this.options = options;
13 |
14 | setModal(true);
15 | setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
16 | addWindowListener(new WindowAdapter() {
17 | public void windowClosing(WindowEvent e) {
18 | onCancel();
19 | }
20 | });
21 | }
22 |
23 | public abstract String getComponentName();
24 |
25 | public abstract String getDirectoryName();
26 |
27 | public abstract T setOptions(T options);
28 |
29 | protected boolean hasCanceled = false;
30 |
31 | public boolean isCanceled() {
32 | return hasCanceled;
33 | }
34 |
35 | protected void onOK() {
36 | hasCanceled = false;
37 | dispose();
38 | this.options = setOptions(this.options);
39 | }
40 |
41 | protected void onCancel() {
42 | hasCanceled = true;
43 | dispose();
44 | }
45 |
46 | public T getOptions() {
47 | return options;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/doc/DEVELOPMENT.md:
--------------------------------------------------------------------------------
1 | # Development
2 | First import the project into IntelliJ
3 |
4 | ## Import Project
5 | 
6 |
7 |
8 | ## Select `Create from exising source`
9 | 
10 |
11 | ## Set Project name
12 | Leave as is
13 |
14 | 
15 |
16 | ## Import
17 | Leave as is
18 |
19 | 
20 |
21 |
22 | ## Libraries
23 | Leave as is
24 |
25 | 
26 |
27 | ## Modules
28 | Leave as is
29 |
30 | 
31 |
32 | ## Project iml file
33 | Make sure to reuse the existing one
34 |
35 | 
36 |
37 | ## SDK
38 | Leave as is
39 |
40 | 
41 |
42 |
43 | # Setup
44 | Follow the setup to start developing the plugin
45 |
46 | ## Open Project Settings
47 |
48 | 
49 |
50 | ## Add "library"
51 | In `Libraries` make sure to read `com.samskivert:jmustache:1.14` as maven dependency
52 | 
53 |
54 | 
55 |
56 | # Add Plugin Run configuration
57 |
58 | 
59 |
60 | 
61 |
--------------------------------------------------------------------------------
/src/io/fabs/util/settings/AbstractSettingsUI.java:
--------------------------------------------------------------------------------
1 | package io.fabs.util.settings;
2 |
3 | import com.intellij.openapi.options.Configurable;
4 | import com.intellij.openapi.options.ConfigurationException;
5 | import com.intellij.openapi.project.Project;
6 | import io.fabs.util.AbstractOptions;
7 | import org.jetbrains.annotations.Nls;
8 | import org.jetbrains.annotations.Nullable;
9 |
10 | import javax.swing.*;
11 |
12 | public abstract class AbstractSettingsUI implements Configurable {
13 | protected Project project;
14 | private String title;
15 | protected AbstractSettingsForm ui;
16 |
17 |
18 | public AbstractSettingsUI(Project project, String title) {
19 | this.project = project;
20 | this.title = title;
21 | }
22 |
23 | public abstract T getOptions();
24 |
25 | public abstract AbstractSettingsForm createUi();
26 |
27 | @Override
28 | public void apply() throws ConfigurationException {
29 | ui.applySettings(getOptions());
30 | }
31 |
32 | @Nls(capitalization = Nls.Capitalization.Title)
33 | @Override
34 | public String getDisplayName() {
35 | return title;
36 | }
37 |
38 | @Nullable
39 | @Override
40 | public JComponent createComponent() {
41 | if (ui == null) {
42 | ui = createUi();
43 | }
44 | reset();
45 |
46 | return ui.getMainPanel();
47 | }
48 |
49 |
50 | @Override
51 | public boolean isModified() {
52 | return ui.isDirty();
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/io/fabs/react/reducer/ui/CreateReducerForm.java:
--------------------------------------------------------------------------------
1 | package io.fabs.react.reducer.ui;
2 |
3 | import io.fabs.react.reducer.data.ReducerCreateOptions;
4 | import io.fabs.util.AbstractDialog;
5 |
6 | import javax.swing.*;
7 | import java.awt.event.KeyEvent;
8 | import java.awt.event.WindowAdapter;
9 | import java.awt.event.WindowEvent;
10 |
11 | public class CreateReducerForm extends AbstractDialog {
12 |
13 | private JPanel contentPanel;
14 | private JButton createButton;
15 | private JTextField moduleNameTextField;
16 | private JTextField actionNameTextField;
17 | private JTextField mutationNameTextField;
18 |
19 | public CreateReducerForm(ReducerCreateOptions options) {
20 | super(options);
21 | setContentPane(contentPanel);
22 | setModal(true);
23 | getRootPane().setDefaultButton(createButton);
24 |
25 | createButton.addActionListener(e -> onOK());
26 |
27 | setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
28 | addWindowListener(new WindowAdapter() {
29 | public void windowClosing(WindowEvent e) {
30 | onCancel();
31 | }
32 | });
33 | contentPanel.registerKeyboardAction(e -> onCancel(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
34 | }
35 |
36 | @Override
37 | public String getComponentName() {
38 | return "";
39 | }
40 |
41 | public String getDirectoryName() {
42 | return moduleNameTextField.getText();
43 | }
44 |
45 | @Override
46 | public ReducerCreateOptions setOptions(ReducerCreateOptions reducerCreateOptions) {
47 | options.setActionFunctionName(actionNameTextField.getText());
48 | options.setModuleName(moduleNameTextField.getText());
49 | options.setMutationType(mutationNameTextField.getText());
50 | return options;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/io/fabs/util/Creator.java:
--------------------------------------------------------------------------------
1 | package io.fabs.util;
2 |
3 | import com.intellij.openapi.vfs.VfsUtil;
4 | import com.intellij.openapi.vfs.VirtualFile;
5 |
6 | import java.io.FileNotFoundException;
7 | import java.nio.file.Paths;
8 | import java.util.Map;
9 |
10 | public class Creator implements Runnable {
11 | protected VirtualFile directory;
12 | protected String componentName;
13 | protected String directoryName;
14 | protected AbstractOptions options;
15 |
16 | public Creator(VirtualFile directory, String directoryName, String componentName, AbstractOptions options) {
17 | this.directory = directory;
18 | this.componentName = componentName;
19 | this.directoryName = directoryName;
20 | this.options = options;
21 | }
22 |
23 | public void create() throws Exception {
24 | VirtualFile existingDirectory = VfsUtil.findRelativeFile(directory, componentName);
25 | if (existingDirectory != null) {
26 | return;
27 | }
28 |
29 | this.writeFiles();
30 | }
31 |
32 | protected void writeFiles() throws Exception {
33 | VirtualFile componentDirectory = directory.createChildDirectory(directory, directoryName);
34 | Map variableMap = options.getTemplateVariables();
35 |
36 | String[] files = options.getFileList();
37 |
38 | for (String filePath : files) {
39 | String file = Paths.get(filePath).toString();
40 | String templateName = TemplateRenderer.transformTemplateName(file, variableMap);
41 | // try {
42 | String content = TemplateRenderer.render(file, variableMap);
43 | FileUtils.writeFile(content, componentDirectory.createChildData(componentDirectory, templateName));
44 | // } catch (Exception e) {
45 | // throw new Exception("" + (e.getMessage()) + " for file " + file, e.fillInStackTrace());
46 | // }
47 | }
48 | }
49 |
50 | @Override
51 | public void run() {
52 | try {
53 | this.create();
54 | } catch (Exception e) {
55 | e.printStackTrace();
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/io/fabs/util/AbstractCreatorAction.java:
--------------------------------------------------------------------------------
1 | package io.fabs.util;
2 |
3 | import com.intellij.openapi.actionSystem.AnAction;
4 | import com.intellij.openapi.actionSystem.AnActionEvent;
5 | import com.intellij.openapi.actionSystem.CommonDataKeys;
6 | import com.intellij.openapi.application.ApplicationManager;
7 | import com.intellij.openapi.project.Project;
8 | import com.intellij.openapi.vfs.VirtualFile;
9 | import com.intellij.pom.Navigatable;
10 |
11 | import java.awt.*;
12 |
13 | public abstract class AbstractCreatorAction extends AnAction {
14 |
15 | protected abstract AbstractDialog createDialog(Project project);
16 |
17 | @Override
18 | public void update(AnActionEvent anActionEvent) {
19 | Project project = anActionEvent.getProject();
20 |
21 | Navigatable navigatable = anActionEvent.getData(CommonDataKeys.NAVIGATABLE);
22 | anActionEvent.getPresentation().setEnabledAndVisible(project != null && navigatable != null);
23 | }
24 |
25 | protected VirtualFile getLocation(VirtualFile file) {
26 | if (file.isDirectory()) {
27 | return file;
28 | }
29 | return file.getParent();
30 | }
31 |
32 | @Override
33 | public void actionPerformed(AnActionEvent e) {
34 | AbstractDialog dialog = this.createDialog(e.getProject());
35 | VirtualFile selectedLocation = e.getData(CommonDataKeys.VIRTUAL_FILE);
36 | VirtualFile targetLocation = getLocation(selectedLocation);
37 |
38 | final int width = dialog.getWidth();
39 | final int height = dialog.getHeight();
40 | final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
41 | int x = (screenSize.width / 2) - (width / 2);
42 | int y = (screenSize.height / 2) - (height / 2);
43 | dialog.setLocation(x, y);
44 |
45 | dialog.pack();
46 | dialog.setVisible(true);
47 |
48 | if (dialog.isCanceled()) {
49 | return;
50 | }
51 |
52 | ApplicationManager.getApplication().runWriteAction(
53 | new Creator(targetLocation, dialog.getDirectoryName(), dialog.getComponentName(), dialog.getOptions())
54 | );
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/io/fabs/react/component/ui/CreateComponentForm.java:
--------------------------------------------------------------------------------
1 | package io.fabs.react.component.ui;
2 |
3 | import io.fabs.react.component.data.ComponentCreateOptions;
4 | import io.fabs.util.AbstractDialog;
5 |
6 | import javax.swing.*;
7 | import java.awt.event.*;
8 |
9 | public class CreateComponentForm extends AbstractDialog {
10 | private JPanel contentPane;
11 | private JButton buttonOK;
12 | private JTextField componentNameTextField;
13 | private JCheckBox storybookCheckBox;
14 | private JCheckBox unitTestCheckBox;
15 | private JCheckBox SCSSCheckBox;
16 | private JCheckBox markdownCheckBox;
17 |
18 | public CreateComponentForm(ComponentCreateOptions options) {
19 | super(options);
20 | setContentPane(contentPane);
21 | setModal(true);
22 | getRootPane().setDefaultButton(buttonOK);
23 |
24 | buttonOK.addActionListener(e -> onOK());
25 |
26 | // call onCancel() when cross is clicked
27 | setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
28 | addWindowListener(new WindowAdapter() {
29 | public void windowClosing(WindowEvent e) {
30 | onCancel();
31 | }
32 | });
33 |
34 | // call onCancel() on ESCAPE
35 | contentPane.registerKeyboardAction(e -> onCancel(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
36 |
37 | storybookCheckBox.setSelected(options.isCreateStorybookDefaultChecked());
38 | unitTestCheckBox.setSelected(options.isCreateSpecDefaultChecked());
39 | SCSSCheckBox.setSelected(options.isCreateScssDefaultChecked());
40 | markdownCheckBox.setSelected(options.isCreateMarkdownDefaultChecked());
41 | }
42 |
43 | public String getComponentName() {
44 | return componentNameTextField.getText();
45 | }
46 |
47 | @Override
48 | public String getDirectoryName() {
49 | return componentNameTextField.getText();
50 | }
51 |
52 | @Override
53 | public ComponentCreateOptions setOptions(ComponentCreateOptions componentCreateOptions) {
54 | options.setComponentName(componentNameTextField.getText());
55 | options.setCreateStoryFile(storybookCheckBox.isSelected());
56 | options.setCreateSpecFile(unitTestCheckBox.isSelected());
57 | options.setCreateSassFile(SCSSCheckBox.isSelected());
58 | options.setCreateMDFile(markdownCheckBox.isSelected());
59 | return options;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-component-creator
2 |
3 | 
4 | 
5 | 
6 |
7 |
8 | w
9 |
10 |
11 | 
12 | 
13 | 
14 |
15 | # Install
16 | Search for `React Component Creator` in the plugins settings. Or download the plugin from the [release site](https://github.com/component-creator-plugin/react-component-creator-plugin/releases)
17 |
18 | # Custom Templates
19 | If you are not happy with the predefined templates, you can choose your
20 | own templates. The templates will be processed with mustache as templating.
21 | All variables can also be used for the filenames.
22 |
23 | Following variables are available
24 |
25 |
26 | **Component**
27 |
28 | | variable | Description |
29 | |---|---|
30 | | {{componentName}} | the inputted component name. Without any alterations |
31 | | {{componentNameCamelCase}} | camelcased input `my-component` becomes `myComponent` |
32 | | {{componentNamePascalCase}} | pascalcased input `my-component` becomes `MyComponent` |
33 |
34 | **Reducer**
35 |
36 | | variable | Description |
37 | |---|---|
38 | | {{componentName}} | Name of the folder |
39 | | {{componentNameCamelCase}} | camelcased input `my-component` becomes `myComponent` |
40 | | {{componentNamePascalCase}} | pascalcased input `my-component` becomes `MyComponent` |
41 | | {{actionFunctionName}} | Name of the function inside the `actions.ts` file |
42 | | {{mutationType}} | String which will be used as type of the dispatch/mutation |
43 | | {{actionTypeName}} | Takes the input of `actionFunctionName` and capitalizes the first letter and appends `Action`. From `setData` becomes `SetDataAction` |
44 | | {{actionTypesEnumName}} | Name used for the action types enum. actionTypesEnumName is the namespace where all `mutationType` actions are kept |
45 |
46 |
47 | # Development
48 | Follow the [Setup Instructions](./doc/DEVELOPMENT.md)
49 |
50 | # Icons
51 | Icons provided by https://www.iconfinder.com/justicon via https://www.iconfinder.com
52 |
--------------------------------------------------------------------------------
/src/io/fabs/react/reducer/ui/SettingsForm.java:
--------------------------------------------------------------------------------
1 | package io.fabs.react.reducer.ui;
2 |
3 | import io.fabs.react.reducer.data.ReducerCreateOptions;
4 | import io.fabs.util.settings.AbstractSettingsForm;
5 |
6 | import javax.swing.*;
7 |
8 | public class SettingsForm extends AbstractSettingsForm {
9 | private JPanel mainPanel;
10 | private JTextField actionTypesTemplateInput;
11 | private JButton actionTypesTemplateButton;
12 | private JTextField actionsTemplateInput;
13 | private JButton actionsTemplateBtn;
14 | private JTextField indexTemplateInput;
15 | private JTextField typesTemplateInput;
16 | private JButton indexTemplateBtn;
17 | private JButton typesTemplateBtn;
18 |
19 | public SettingsForm(ReducerCreateOptions options) {
20 | super(options);
21 |
22 | // Set default settings received from state
23 | if (!options.isActionTypesTemplateDefault()) {
24 | actionTypesTemplateInput.setText(options.getActionTypesTemplateFile());
25 | }
26 |
27 | if (!options.isActionTemplateDefault()) {
28 | actionsTemplateInput.setText(options.getActionTemplateFile());
29 | }
30 |
31 | if (!options.isModuleTemplateDefault()) {
32 | indexTemplateInput.setText(options.getModuleIndexTemplateFile());
33 | }
34 |
35 | if (!options.isTypesTemplateDefault()) {
36 | typesTemplateInput.setText(options.getTypesTemplateFile());
37 | }
38 |
39 | // Add listeners for browse button
40 | actionTypesTemplateButton.addActionListener(e -> onBrowseButtonClicked(e, actionTypesTemplateInput));
41 | actionsTemplateBtn.addActionListener(e -> onBrowseButtonClicked(e, actionsTemplateInput));
42 | indexTemplateBtn.addActionListener(e -> onBrowseButtonClicked(e, indexTemplateInput));
43 | typesTemplateBtn.addActionListener(e -> onBrowseButtonClicked(e, typesTemplateInput));
44 | }
45 |
46 | @Override
47 | public JComponent getMainPanel() {
48 | return this.mainPanel;
49 | }
50 |
51 | public boolean isDirty() {
52 | ReducerCreateOptions o = new ReducerCreateOptions();
53 | o.setActionTypesTemplateFile(actionTypesTemplateInput.getText());
54 | o.setActionTemplateFile(actionsTemplateInput.getText());
55 | o.setModuleIndexTemplateFile(indexTemplateInput.getText());
56 | o.setTypesTemplateFile(typesTemplateInput.getText());
57 | return !options.equals(o);
58 | }
59 |
60 | @Override
61 | public void applySettings(ReducerCreateOptions options) {
62 | String actionTypes = actionTypesTemplateInput.getText();
63 | String actions = actionsTemplateInput.getText();
64 | String index = indexTemplateInput.getText();
65 | String types = typesTemplateInput.getText();
66 |
67 | if (actionTypes != null) {
68 | options.setActionTypesTemplateFile(actionTypes);
69 | }
70 |
71 | if (actions != null) {
72 | options.setActionTemplateFile(actions);
73 | }
74 |
75 | if (index != null) {
76 | options.setModuleIndexTemplateFile(index);
77 | }
78 |
79 | if (types != null) {
80 | options.setTypesTemplateFile(types);
81 | }
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/src/io/fabs/react/component/ui/SettingsForm.java:
--------------------------------------------------------------------------------
1 | package io.fabs.react.component.ui;
2 |
3 | import io.fabs.react.component.data.ComponentCreateOptions;
4 | import io.fabs.util.settings.AbstractSettingsForm;
5 |
6 | import javax.swing.*;
7 |
8 | public class SettingsForm extends AbstractSettingsForm {
9 | private JPanel mainPanel;
10 | private JTextField componentTemplateInput;
11 | private JTextField storyTemplateInput;
12 | private JTextField specTemplateInput;
13 | private JTextField scssTemplateInput;
14 | private JTextField mdTemplateInput;
15 |
16 | private JButton componentTemplateBtn;
17 | private JButton storyTemplateBtn;
18 | private JButton specTemplateBtn;
19 | private JButton scssTemplateBtn;
20 | private JButton mdTemplateBtn;
21 | private JCheckBox storybookCheckbox;
22 | private JCheckBox specCheckBox;
23 | private JCheckBox SCSSCheckBox;
24 | private JCheckBox mdCheckBox;
25 |
26 | public SettingsForm(ComponentCreateOptions options) {
27 | super(options);
28 |
29 | if (!options.isComponentTemplateDefault()) {
30 | componentTemplateInput.setText(options.getComponentTemplateFile());
31 | }
32 |
33 | if (!options.isStoryTemplateDefault()) {
34 | storyTemplateInput.setText(options.getStoryTemplateFile());
35 | }
36 |
37 | if (!options.isSpecTemplateDefault()) {
38 | specTemplateInput.setText(options.getSpecTemplateFile());
39 | }
40 |
41 | if (!options.isSassTemplateDefault()) {
42 | scssTemplateInput.setText(options.getSassTemplateFile());
43 | }
44 |
45 | if (!options.isMDTemplateDefault()) {
46 | mdTemplateInput.setText(options.getMarkdownTemplateFile());
47 | }
48 |
49 | storybookCheckbox.setSelected(options.isCreateStorybookDefaultChecked());
50 | specCheckBox.setSelected(options.isCreateSpecDefaultChecked());
51 | SCSSCheckBox.setSelected(options.isCreateScssDefaultChecked());
52 | mdCheckBox.setSelected(options.isCreateMarkdownDefaultChecked());
53 |
54 | componentTemplateBtn.addActionListener(e -> onBrowseButtonClicked(e, componentTemplateInput));
55 |
56 | storyTemplateBtn.addActionListener(e -> onBrowseButtonClicked(e, storyTemplateInput));
57 |
58 | specTemplateBtn.addActionListener(e -> onBrowseButtonClicked(e, specTemplateInput));
59 |
60 | scssTemplateBtn.addActionListener(e -> onBrowseButtonClicked(e, scssTemplateInput));
61 |
62 | mdTemplateBtn.addActionListener(e -> onBrowseButtonClicked(e, mdTemplateInput));
63 | }
64 |
65 | @Override
66 | public JComponent getMainPanel() {
67 | return mainPanel;
68 | }
69 |
70 | @Override
71 | public boolean isDirty() {
72 | ComponentCreateOptions o = new ComponentCreateOptions();
73 | applySettings(o);
74 | return !options.equals(o);
75 | }
76 |
77 | public void applySettings(ComponentCreateOptions options) {
78 | String component = componentTemplateInput.getText();
79 | String story = storyTemplateInput.getText();
80 | String spec = specTemplateInput.getText();
81 | String scss = scssTemplateInput.getText();
82 | String md = mdTemplateInput.getText();
83 |
84 | options.setComponentTemplateFile(component);
85 | options.setStoryTemplateFile(story);
86 | options.setSpecTemplateFile(spec);
87 | options.setSassTemplateFile(scss);
88 | options.setMarkdownTemplateFile(md);
89 |
90 | options.setCreateMarkdownDefaultChecked(mdCheckBox.isSelected());
91 | options.setCreateSpecDefaultChecked(specCheckBox.isSelected());
92 | options.setCreateScssDefaultChecked(SCSSCheckBox.isSelected());
93 | options.setCreateStorybookDefaultChecked(storybookCheckbox.isSelected());
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/resources/META-INF/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 | com.faebeee.reactcomponentcreator
3 | React Component Creator
4 | 1.0.1
5 | Fabio Gianini
6 |
7 |
8 |
9 |
10 |
12 |
13 | com.intellij.modules.lang
14 |
15 |
20 |
21 |
22 |
23 |
25 | v1.0.1 Fix default templates for stories
26 | v1.0.0 Major release. Fix bugs for windows
27 | v0.6.0 Use component-creator-lib
28 |
29 | - Fix windows paths
30 | - Update documentation
31 | - Add camelcase and pascalcase variables for templates
32 |
33 |
34 | v0.5.0 Checkboxes checked by default can be configured in the settings
35 | v0.4.0 Add Customisable templates. Improve a lot of code. Update doc
36 | v0.2.1 Export enum for action types
37 | v0.2.1 Export enum for action types
38 | v0.2.0 Add Add Redux Reducer Action
39 | v0.1.0 Add Add React Component Action
40 |
41 | ]]>
42 |
43 |
44 |
45 |
46 |
51 |
52 |
58 |
59 |
65 |
66 |
68 |
69 |
71 |
72 |
73 |
74 |
75 |
76 |
81 |
82 |
83 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/src/io/fabs/react/reducer/ui/SettingsForm.form:
--------------------------------------------------------------------------------
1 |
2 |
132 |
--------------------------------------------------------------------------------
/src/io/fabs/react/reducer/data/ReducerCreateOptions.java:
--------------------------------------------------------------------------------
1 | package io.fabs.react.reducer.data;
2 |
3 | import io.fabs.util.AbstractOptions;
4 | import io.fabs.util.StringFormatter;
5 | import io.fabs.util.TemplateUtils;
6 | import org.jdom.Element;
7 |
8 | import java.util.ArrayList;
9 | import java.util.Map;
10 | import java.util.Objects;
11 |
12 | public class ReducerCreateOptions extends AbstractOptions {
13 | public static final String STORE_KEY = "rcc.reducer";
14 | private final static String ACTION_TEMPLATE = "ACTION_TEMPLATE";
15 | private final static String ACTION_TYPES_TEMPLATE = "ACTION_TYPES_TEMPLATE";
16 | private final static String INDEX_TEMPLATE = "INDEX_TEMPLATE";
17 | private final static String TYPES_TEMPLATE = "TYPES_TEMPLATE";
18 |
19 | private final String defaultActionTemplateFile = "/templates/reducer/actions.ts.mustache";
20 | private final String defaultModuleIndexTemplateFile = "/templates/reducer/index.ts.mustache";
21 | private final String defaultTypesTemplateFile = "/templates/reducer/types.ts.mustache";
22 | private final String defaultActionTypesTemplateFile = "/templates/reducer/action-types.ts.mustache";
23 |
24 | private String actionTemplateFile = defaultActionTemplateFile;
25 | private String moduleIndexTemplateFile = defaultModuleIndexTemplateFile;
26 | private String typesTemplateFile = defaultTypesTemplateFile;
27 | private String actionTypesTemplateFile = defaultActionTypesTemplateFile;
28 |
29 | private String actionFunctionName;
30 | private String moduleName;
31 | private String mutationType;
32 |
33 |
34 | public Element serialize() {
35 | final Element element = new Element(STORE_KEY);
36 | element.setAttribute(ACTION_TEMPLATE, actionTemplateFile);
37 | element.setAttribute(INDEX_TEMPLATE, moduleIndexTemplateFile);
38 | element.setAttribute(ACTION_TYPES_TEMPLATE, actionTypesTemplateFile);
39 | element.setAttribute(TYPES_TEMPLATE, typesTemplateFile);
40 | return element;
41 | }
42 |
43 | public void deserialize(Element element) {
44 | setActionTemplateFile(element.getAttributeValue(ACTION_TEMPLATE));
45 | setActionTypesTemplateFile(element.getAttributeValue(ACTION_TYPES_TEMPLATE));
46 | setModuleIndexTemplateFile(element.getAttributeValue(INDEX_TEMPLATE));
47 | setTypesTemplateFile(element.getAttributeValue(TYPES_TEMPLATE));
48 | }
49 |
50 | public ArrayList getFiles() {
51 | ArrayList files = new ArrayList<>();
52 | files.add(actionTemplateFile);
53 | files.add(moduleIndexTemplateFile);
54 | files.add(typesTemplateFile);
55 | files.add(actionTypesTemplateFile);
56 | return files;
57 | }
58 |
59 | @Override
60 | public Map getTemplateVariables() {
61 | Map templateModel = TemplateUtils.createVariableMap(moduleName);
62 |
63 | templateModel.put("actionFunctionName", actionFunctionName);
64 | templateModel.put("mutationType", mutationType);
65 |
66 | templateModel.put("actionTypeName", StringFormatter.capitalizeFirst(actionFunctionName) + "Action");
67 | templateModel.put("actionTypesEnumName", StringFormatter.toDashCase(moduleName).toUpperCase() + "_ACTIONS");
68 |
69 | return templateModel;
70 | }
71 |
72 | public void setActionTemplateFile(String actionTemplateFile) {
73 | if (actionTemplateFile == null) {
74 | this.actionTemplateFile = null;
75 | return;
76 | }
77 |
78 | if (actionTemplateFile.isEmpty()) {
79 | this.actionTemplateFile = defaultActionTemplateFile;
80 | return;
81 | }
82 | this.actionTemplateFile = actionTemplateFile;
83 | }
84 |
85 | public void setModuleIndexTemplateFile(String moduleIndexTemplateFile) {
86 | if (moduleIndexTemplateFile == null) {
87 | this.moduleIndexTemplateFile = null;
88 | return;
89 | }
90 |
91 | if (moduleIndexTemplateFile.isEmpty()) {
92 | this.moduleIndexTemplateFile = defaultModuleIndexTemplateFile;
93 | return;
94 | }
95 | this.moduleIndexTemplateFile = moduleIndexTemplateFile;
96 | }
97 |
98 |
99 | public void setTypesTemplateFile(String typesTemplateFile) {
100 | if (typesTemplateFile == null) {
101 | this.typesTemplateFile = null;
102 | return;
103 | }
104 |
105 | if (typesTemplateFile.isEmpty()) {
106 | this.typesTemplateFile = defaultTypesTemplateFile;
107 | return;
108 | }
109 | this.typesTemplateFile = typesTemplateFile;
110 | }
111 |
112 | public void setActionTypesTemplateFile(String actionTypesTemplateFile) {
113 | if (actionTypesTemplateFile == null) {
114 | this.actionTypesTemplateFile = null;
115 | return;
116 | }
117 |
118 | if (actionTypesTemplateFile.isEmpty()) {
119 | this.actionTypesTemplateFile = defaultActionTypesTemplateFile;
120 | return;
121 | }
122 | this.actionTypesTemplateFile = actionTypesTemplateFile;
123 | }
124 |
125 | @Override
126 | public boolean equals(Object o) {
127 | if (this == o) return true;
128 | if (o == null || getClass() != o.getClass()) return false;
129 | ReducerCreateOptions that = (ReducerCreateOptions) o;
130 | return Objects.equals(actionTemplateFile, that.actionTemplateFile) &&
131 | Objects.equals(moduleIndexTemplateFile, that.moduleIndexTemplateFile) &&
132 | Objects.equals(typesTemplateFile, that.typesTemplateFile) &&
133 | Objects.equals(actionTypesTemplateFile, that.actionTypesTemplateFile);
134 | }
135 |
136 | @Override
137 | public int hashCode() {
138 | return 0;
139 | }
140 |
141 | public String getActionTemplateFile() {
142 | return actionTemplateFile;
143 | }
144 |
145 | public String getModuleIndexTemplateFile() {
146 | return moduleIndexTemplateFile;
147 | }
148 |
149 | public String getTypesTemplateFile() {
150 | return typesTemplateFile;
151 | }
152 |
153 | public String getActionTypesTemplateFile() {
154 | return actionTypesTemplateFile;
155 | }
156 |
157 | public boolean isActionTemplateDefault() {
158 | return this.actionTemplateFile.equals(this.defaultActionTemplateFile);
159 | }
160 |
161 | public boolean isModuleTemplateDefault() {
162 | return this.moduleIndexTemplateFile.equals(this.defaultModuleIndexTemplateFile);
163 | }
164 |
165 | public boolean isTypesTemplateDefault() {
166 | return this.typesTemplateFile.equals(this.defaultTypesTemplateFile);
167 | }
168 |
169 | public boolean isActionTypesTemplateDefault() {
170 | return this.actionTypesTemplateFile.equals(this.defaultActionTypesTemplateFile);
171 | }
172 |
173 | public void setActionFunctionName(String actionFunctionName) {
174 | this.actionFunctionName = actionFunctionName;
175 | }
176 |
177 | public void setModuleName(String moduleName) {
178 | this.moduleName = moduleName;
179 | }
180 |
181 | public void setMutationType(String mutationType) {
182 | this.mutationType = mutationType;
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/src/io/fabs/react/component/ui/CreateComponentForm.form:
--------------------------------------------------------------------------------
1 |
2 |
158 |
--------------------------------------------------------------------------------
/src/io/fabs/react/reducer/ui/CreateReducerForm.form:
--------------------------------------------------------------------------------
1 |
2 |
176 |
--------------------------------------------------------------------------------
/src/io/fabs/react/component/ui/SettingsForm.form:
--------------------------------------------------------------------------------
1 |
2 |
191 |
--------------------------------------------------------------------------------
/src/io/fabs/react/component/data/ComponentCreateOptions.java:
--------------------------------------------------------------------------------
1 | package io.fabs.react.component.data;
2 |
3 | import io.fabs.util.AbstractOptions;
4 | import io.fabs.util.TemplateUtils;
5 | import org.jdom.Element;
6 |
7 | import java.util.ArrayList;
8 | import java.util.Map;
9 |
10 | public class ComponentCreateOptions extends AbstractOptions {
11 | public static final String STORE_KEY = "rcc.component";
12 | private final String COMPONENT_TEMPLATE_KEY = "COMPONENT_TEMPLATE_KEY";
13 | private final String SASS_TEMPLATE_KEY = "SASS_TEMPLATE_KEY";
14 | private final String SPEC_TEMPLATE_KEY = "SPEC_TEMPLATE_KEY";
15 | private final String STORY_TEMPLATE_KEY = "STORY_TEMPLATE_KEY";
16 | private final String MD_TEMPLATE_KEY = "MD_TEMPLATE_KEY";
17 |
18 | private final String defaultComponentTemplateFile = "/templates/component/{{componentName}}.tsx.mustache";
19 | private final String defaultSassTemplateFile = "/templates/component/_{{componentName}}.scss.mustache";
20 | private final String defaultSpecTemplateFile = "/templates/component/{{componentName}}.spec.tsx.mustache";
21 | private final String defaultStoryTemplateFile = "/templates/component/{{componentName}}.stories.tsx.mustache";
22 | private final String defaultMarkdownTemplateFile = "/templates/component/{{componentName}}.md.mustache";
23 |
24 | private String componentTemplateFile = defaultComponentTemplateFile;
25 | private String sassTemplateFile = defaultSassTemplateFile;
26 | private String specTemplateFile = defaultSpecTemplateFile;
27 | private String storyTemplateFile = defaultStoryTemplateFile;
28 | private String markdownTemplateFile = defaultMarkdownTemplateFile;
29 |
30 | private final String MD_CHECKBOX_KEY = "MD_CHECKBOX_KEY";
31 | private final String STORY_CHECKBOX_KEY = "STORY_CHECKBOX_KEY";
32 | private final String SCSS_CHECKBOX_KEY = "SCSS_CHECKBOX_KEY";
33 | private final String SPEC_CHECKBOX_KEY = "SPEC_CHECKBOX_KEY";
34 |
35 | private boolean isCreateStorybookDefaultChecked = false;
36 | private boolean isCreateSpecDefaultChecked = false;
37 | private boolean isCreateScssDefaultChecked = false;
38 | private boolean isCreateMarkdownDefaultChecked = false;
39 |
40 | private Boolean isCreateSassFile = false;
41 | private Boolean isCreateSpecFile = false;
42 | private Boolean isCreateStoryFile = false;
43 | private Boolean isCreateMDFile = false;
44 |
45 | private String componentName;
46 |
47 | @Override
48 | public Element serialize() {
49 | final Element element = new Element(STORE_KEY);
50 | element.setAttribute(COMPONENT_TEMPLATE_KEY, componentTemplateFile);
51 | element.setAttribute(SASS_TEMPLATE_KEY, sassTemplateFile);
52 | element.setAttribute(SPEC_TEMPLATE_KEY, specTemplateFile);
53 | element.setAttribute(STORY_TEMPLATE_KEY, storyTemplateFile);
54 | element.setAttribute(MD_TEMPLATE_KEY, markdownTemplateFile);
55 |
56 | element.setAttribute(MD_CHECKBOX_KEY, Boolean.toString(isCreateMarkdownDefaultChecked));
57 | element.setAttribute(STORY_CHECKBOX_KEY, Boolean.toString(isCreateStorybookDefaultChecked));
58 | element.setAttribute(SCSS_CHECKBOX_KEY, Boolean.toString(isCreateScssDefaultChecked));
59 | element.setAttribute(SPEC_CHECKBOX_KEY, Boolean.toString(isCreateSpecDefaultChecked));
60 | return element;
61 | }
62 |
63 | @Override
64 | public void deserialize(Element element) {
65 | setComponentTemplateFile(element.getAttributeValue(COMPONENT_TEMPLATE_KEY));
66 | setSassTemplateFile(element.getAttributeValue(SASS_TEMPLATE_KEY));
67 | setSpecTemplateFile(element.getAttributeValue(SPEC_TEMPLATE_KEY));
68 | setStoryTemplateFile(element.getAttributeValue(STORY_TEMPLATE_KEY));
69 | setMarkdownTemplateFile(element.getAttributeValue(MD_TEMPLATE_KEY));
70 |
71 | setCreateMarkdownDefaultChecked(Boolean.parseBoolean(element.getAttributeValue(MD_CHECKBOX_KEY)));
72 | setCreateStorybookDefaultChecked(Boolean.parseBoolean(element.getAttributeValue(STORY_CHECKBOX_KEY)));
73 | setCreateScssDefaultChecked(Boolean.parseBoolean(element.getAttributeValue(SCSS_CHECKBOX_KEY)));
74 | setCreateSpecDefaultChecked(Boolean.parseBoolean(element.getAttributeValue(SPEC_CHECKBOX_KEY)));
75 | }
76 |
77 | @Override
78 | public ArrayList getFiles() {
79 | ArrayList files = new ArrayList<>();
80 | files.add(componentTemplateFile);
81 |
82 | if (isCreateStoryFile) {
83 | files.add(storyTemplateFile);
84 | }
85 |
86 | if (isCreateSassFile) {
87 | files.add(sassTemplateFile);
88 | }
89 |
90 | if (isCreateSpecFile) {
91 | files.add(specTemplateFile);
92 | }
93 |
94 | if (isCreateMDFile) {
95 | files.add(this.markdownTemplateFile);
96 | }
97 | return files;
98 | }
99 |
100 | @Override
101 | public Map getTemplateVariables() {
102 | return TemplateUtils.createVariableMap(componentName);
103 | }
104 |
105 | public void setComponentTemplateFile(String componentTemplateFile) {
106 | if (componentTemplateFile == null || componentTemplateFile.isEmpty()) {
107 | this.componentTemplateFile = defaultComponentTemplateFile;
108 | return;
109 | }
110 | this.componentTemplateFile = componentTemplateFile;
111 | }
112 |
113 |
114 | public void setSassTemplateFile(String sassTemplateFile) {
115 | if (sassTemplateFile == null || sassTemplateFile.isEmpty()) {
116 | this.sassTemplateFile = defaultSassTemplateFile;
117 | return;
118 | }
119 | this.sassTemplateFile = sassTemplateFile;
120 | }
121 |
122 |
123 | public void setSpecTemplateFile(String specTemplateFile) {
124 | if (specTemplateFile == null || specTemplateFile.isEmpty()) {
125 | this.specTemplateFile = defaultSpecTemplateFile;
126 | return;
127 | }
128 | this.specTemplateFile = specTemplateFile;
129 | }
130 |
131 |
132 | public void setStoryTemplateFile(String storyTemplateFile) {
133 | if (storyTemplateFile == null || storyTemplateFile.isEmpty()) {
134 | this.storyTemplateFile = defaultStoryTemplateFile;
135 | return;
136 | }
137 | this.storyTemplateFile = storyTemplateFile;
138 | }
139 |
140 |
141 | public void setMarkdownTemplateFile(String markdownTemplateFile) {
142 | if (markdownTemplateFile == null || markdownTemplateFile.isEmpty()) {
143 | this.markdownTemplateFile = defaultMarkdownTemplateFile;
144 | return;
145 | }
146 | this.markdownTemplateFile = markdownTemplateFile;
147 | }
148 |
149 | public boolean isComponentTemplateDefault() {
150 | return componentTemplateFile.equals(defaultComponentTemplateFile);
151 | }
152 |
153 | public boolean isSassTemplateDefault() {
154 | return sassTemplateFile.equals(defaultSassTemplateFile);
155 | }
156 |
157 | public boolean isSpecTemplateDefault() {
158 | return specTemplateFile.equals(defaultSpecTemplateFile);
159 | }
160 |
161 | public boolean isStoryTemplateDefault() {
162 | return storyTemplateFile.equals(defaultStoryTemplateFile);
163 | }
164 |
165 | public boolean isMDTemplateDefault() {
166 | return markdownTemplateFile.equals(defaultMarkdownTemplateFile);
167 | }
168 |
169 | public void setCreateSassFile(Boolean createSassFile) {
170 | isCreateSassFile = createSassFile;
171 | }
172 |
173 | public void setCreateSpecFile(Boolean createSpecFile) {
174 | isCreateSpecFile = createSpecFile;
175 | }
176 |
177 | public void setCreateStoryFile(Boolean createStoryFile) {
178 | isCreateStoryFile = createStoryFile;
179 | }
180 |
181 | public void setCreateMDFile(Boolean createMDFile) {
182 | isCreateMDFile = createMDFile;
183 | }
184 |
185 | public void setComponentName(String componentName) {
186 | this.componentName = componentName;
187 | }
188 |
189 | public String getComponentTemplateFile() {
190 | return componentTemplateFile;
191 | }
192 |
193 | public String getSassTemplateFile() {
194 | return sassTemplateFile;
195 | }
196 |
197 | public String getSpecTemplateFile() {
198 | return specTemplateFile;
199 | }
200 |
201 | public String getStoryTemplateFile() {
202 | return storyTemplateFile;
203 | }
204 |
205 | public String getMarkdownTemplateFile() {
206 | return markdownTemplateFile;
207 | }
208 |
209 | public boolean isCreateStorybookDefaultChecked() {
210 | return isCreateStorybookDefaultChecked;
211 | }
212 |
213 | public boolean isCreateSpecDefaultChecked() {
214 | return isCreateSpecDefaultChecked;
215 | }
216 |
217 | public boolean isCreateScssDefaultChecked() {
218 | return isCreateScssDefaultChecked;
219 | }
220 |
221 | public boolean isCreateMarkdownDefaultChecked() {
222 | return isCreateMarkdownDefaultChecked;
223 | }
224 |
225 | public void setCreateStorybookDefaultChecked(boolean createStorybookDefaultChecked) {
226 | isCreateStorybookDefaultChecked = createStorybookDefaultChecked;
227 | }
228 |
229 | public void setCreateSpecDefaultChecked(boolean createSpecDefaultChecked) {
230 | isCreateSpecDefaultChecked = createSpecDefaultChecked;
231 | }
232 |
233 | public void setCreateScssDefaultChecked(boolean createScssDefaultChecked) {
234 | isCreateScssDefaultChecked = createScssDefaultChecked;
235 | }
236 |
237 | public void setCreateMarkdownDefaultChecked(boolean createMarkdownDefaultChecked) {
238 | isCreateMarkdownDefaultChecked = createMarkdownDefaultChecked;
239 | }
240 |
241 | public boolean equals(ComponentCreateOptions options) {
242 | return (options.getComponentTemplateFile().equals(componentTemplateFile)
243 | && options.getStoryTemplateFile().equals(storyTemplateFile)
244 | && options.getSpecTemplateFile().equals(specTemplateFile)
245 | && options.getSassTemplateFile().equals(sassTemplateFile)
246 | && options.getMarkdownTemplateFile().equals(markdownTemplateFile)
247 | && options.isCreateMarkdownDefaultChecked() == isCreateMarkdownDefaultChecked
248 | && options.isCreateScssDefaultChecked() == isCreateScssDefaultChecked
249 | && options.isCreateSpecDefaultChecked() == isCreateSpecDefaultChecked
250 | && options.isCreateStorybookDefaultChecked() == isCreateStorybookDefaultChecked
251 | );
252 | }
253 | }
254 |
--------------------------------------------------------------------------------