Commit 4f79c3bb authored by nano's avatar nano

update

parent 3d31834a
...@@ -2,11 +2,15 @@ ...@@ -2,11 +2,15 @@
"parser": "babel-eslint", "parser": "babel-eslint",
"extends": "airbnb", "extends": "airbnb",
"rules": { "rules": {
"react/jsx-space-before-closing":[0],
"generator-star-spacing": [0], "generator-star-spacing": [0],
"semi":[0],
"no-console":[0],
"consistent-return": [0], "consistent-return": [0],
"react/forbid-prop-types": [0], "react/forbid-prop-types": [0],
"react/jsx-filename-extension": [1, { "extensions": [".js"] }], "react/jsx-filename-extension": [1, { "extensions": [".js"] }],
"global-require": [1], "global-require": [1],
"react/jsx-closing-bracket-location":[0],
"import/prefer-default-export": [0], "import/prefer-default-export": [0],
"react/jsx-no-bind": [0], "react/jsx-no-bind": [0],
"react/prop-types": [0], "react/prop-types": [0],
...@@ -22,11 +26,16 @@ ...@@ -22,11 +26,16 @@
"no-bitwise": [0], "no-bitwise": [0],
"no-cond-assign": [0], "no-cond-assign": [0],
"import/no-unresolved": [0], "import/no-unresolved": [0],
"require-yield": [1] "require-yield": [1],
"react/react-in-jsx-scope": [0],
"no-extra-semi": [0]
}, },
"parserOptions": { "parserOptions": {
"ecmaFeatures": { "ecmaFeatures": {
"experimentalObjectRestSpread": true "experimentalObjectRestSpread": true
} }
},
"env": {
"browser": true
} }
} }
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DBNavigator.Project.DataEditorManager">
<record-view-column-sorting-type value="BY_INDEX" />
<value-preview-text-wrapping value="true" />
<value-preview-pinned value="false" />
</component>
<component name="DBNavigator.Project.DataExportManager">
<export-instructions>
<create-header value="true" />
<quote-values-containing-separator value="true" />
<quote-all-values value="false" />
<value-separator value="" />
<file-name value="" />
<file-location value="" />
<scope value="GLOBAL" />
<destination value="FILE" />
<format value="EXCEL" />
<charset value="UTF-8" />
</export-instructions>
</component>
<component name="DBNavigator.Project.DatabaseBrowserManager">
<autoscroll-to-editor value="false" />
<autoscroll-from-editor value="true" />
<show-object-properties value="true" />
<loaded-nodes />
</component>
<component name="DBNavigator.Project.EditorStateManager">
<last-used-providers />
</component>
<component name="DBNavigator.Project.MethodExecutionManager">
<method-browser />
<execution-history>
<group-entries value="true" />
<execution-inputs />
</execution-history>
<argument-values-cache />
</component>
<component name="DBNavigator.Project.ObjectDependencyManager">
<last-used-dependency-type value="INCOMING" />
</component>
<component name="DBNavigator.Project.ObjectQuickFilterManager">
<last-used-operator value="EQUAL" />
<filters />
</component>
<component name="DBNavigator.Project.ScriptExecutionManager" clear-outputs="true">
<recently-used-interfaces />
</component>
<component name="DBNavigator.Project.Settings">
<connections />
<browser-settings>
<general>
<display-mode value="TABBED" />
<navigation-history-size value="100" />
<show-object-details value="false" />
</general>
<filters>
<object-type-filter>
<object-type name="SCHEMA" enabled="true" />
<object-type name="USER" enabled="true" />
<object-type name="ROLE" enabled="true" />
<object-type name="PRIVILEGE" enabled="true" />
<object-type name="CHARSET" enabled="true" />
<object-type name="TABLE" enabled="true" />
<object-type name="VIEW" enabled="true" />
<object-type name="MATERIALIZED_VIEW" enabled="true" />
<object-type name="NESTED_TABLE" enabled="true" />
<object-type name="COLUMN" enabled="true" />
<object-type name="INDEX" enabled="true" />
<object-type name="CONSTRAINT" enabled="true" />
<object-type name="DATASET_TRIGGER" enabled="true" />
<object-type name="DATABASE_TRIGGER" enabled="true" />
<object-type name="SYNONYM" enabled="true" />
<object-type name="SEQUENCE" enabled="true" />
<object-type name="PROCEDURE" enabled="true" />
<object-type name="FUNCTION" enabled="true" />
<object-type name="PACKAGE" enabled="true" />
<object-type name="TYPE" enabled="true" />
<object-type name="TYPE_ATTRIBUTE" enabled="true" />
<object-type name="ARGUMENT" enabled="true" />
<object-type name="DIMENSION" enabled="true" />
<object-type name="CLUSTER" enabled="true" />
<object-type name="DBLINK" enabled="true" />
</object-type-filter>
</filters>
<sorting>
<object-type name="COLUMN" sorting-type="NAME" />
<object-type name="FUNCTION" sorting-type="NAME" />
<object-type name="PROCEDURE" sorting-type="NAME" />
<object-type name="ARGUMENT" sorting-type="POSITION" />
</sorting>
<default-editors>
<object-type name="VIEW" editor-type="SELECTION" />
<object-type name="PACKAGE" editor-type="SELECTION" />
<object-type name="TYPE" editor-type="SELECTION" />
</default-editors>
</browser-settings>
<navigation-settings>
<lookup-filters>
<lookup-objects>
<object-type name="SCHEMA" enabled="true" />
<object-type name="USER" enabled="false" />
<object-type name="ROLE" enabled="false" />
<object-type name="PRIVILEGE" enabled="false" />
<object-type name="CHARSET" enabled="false" />
<object-type name="TABLE" enabled="true" />
<object-type name="VIEW" enabled="true" />
<object-type name="MATERIALIZED VIEW" enabled="true" />
<object-type name="NESTED TABLE" enabled="false" />
<object-type name="COLUMN" enabled="false" />
<object-type name="INDEX" enabled="true" />
<object-type name="CONSTRAINT" enabled="true" />
<object-type name="DATASET TRIGGER" enabled="true" />
<object-type name="DATABASE TRIGGER" enabled="true" />
<object-type name="SYNONYM" enabled="false" />
<object-type name="SEQUENCE" enabled="true" />
<object-type name="PROCEDURE" enabled="true" />
<object-type name="FUNCTION" enabled="true" />
<object-type name="PACKAGE" enabled="true" />
<object-type name="TYPE" enabled="true" />
<object-type name="TYPE ATTRIBUTE" enabled="false" />
<object-type name="ARGUMENT" enabled="false" />
<object-type name="DIMENSION" enabled="false" />
<object-type name="CLUSTER" enabled="false" />
<object-type name="DBLINK" enabled="true" />
</lookup-objects>
<force-database-load value="false" />
<prompt-connection-selection value="true" />
<prompt-schema-selection value="true" />
</lookup-filters>
</navigation-settings>
<dataset-grid-settings>
<general>
<enable-zooming value="true" />
</general>
<sorting>
<nulls-first value="true" />
<max-sorting-columns value="4" />
</sorting>
<tracking-columns>
<columnNames value="" />
<visible value="true" />
<editable value="false" />
</tracking-columns>
</dataset-grid-settings>
<dataset-editor-settings>
<text-editor-popup>
<active value="false" />
<active-if-empty value="false" />
<data-length-threshold value="100" />
<popup-delay value="1000" />
</text-editor-popup>
<values-list-popup>
<show-popup-button value="true" />
<element-count-threshold value="1000" />
<data-length-threshold value="250" />
</values-list-popup>
<general>
<fetch-block-size value="100" />
<fetch-timeout value="30" />
<trim-whitespaces value="true" />
<convert-empty-strings-to-null value="true" />
<select-content-on-cell-edit value="true" />
<large-value-preview-active value="true" />
</general>
<filters>
<prompt-filter-dialog value="true" />
<default-filter-type value="BASIC" />
</filters>
<qualified-text-editor text-length-threshold="300">
<content-types>
<content-type name="Text" enabled="true" />
<content-type name="XML" enabled="true" />
<content-type name="DTD" enabled="true" />
<content-type name="HTML" enabled="true" />
<content-type name="XHTML" enabled="true" />
<content-type name="CSS" enabled="true" />
<content-type name="SQL" enabled="true" />
<content-type name="PL/SQL" enabled="true" />
<content-type name="JavaScript" enabled="true" />
<content-type name="JSP" enabled="true" />
<content-type name="JSPx" enabled="true" />
<content-type name="ASP" enabled="true" />
<content-type name="YAML" enabled="true" />
</content-types>
</qualified-text-editor>
<record-navigation>
<navigation-target value="VIEWER" />
</record-navigation>
</dataset-editor-settings>
<code-editor-settings>
<general>
<show-object-navigation-gutter value="false" />
<show-spec-declaration-navigation-gutter value="true" />
</general>
<confirmations>
<save-changes value="false" />
<revert-changes value="true" />
</confirmations>
</code-editor-settings>
<code-completion-settings>
<filters>
<basic-filter>
<filter-element type="RESERVED_WORD" id="keyword" selected="true" />
<filter-element type="RESERVED_WORD" id="function" selected="true" />
<filter-element type="RESERVED_WORD" id="parameter" selected="true" />
<filter-element type="RESERVED_WORD" id="datatype" selected="true" />
<filter-element type="RESERVED_WORD" id="exception" selected="true" />
<filter-element type="OBJECT" id="schema" selected="true" />
<filter-element type="OBJECT" id="role" selected="true" />
<filter-element type="OBJECT" id="user" selected="true" />
<filter-element type="OBJECT" id="privilege" selected="true" />
<user-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="false" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</user-schema>
<public-schema>
<filter-element type="OBJECT" id="table" selected="false" />
<filter-element type="OBJECT" id="view" selected="false" />
<filter-element type="OBJECT" id="materialized view" selected="false" />
<filter-element type="OBJECT" id="index" selected="false" />
<filter-element type="OBJECT" id="constraint" selected="false" />
<filter-element type="OBJECT" id="trigger" selected="false" />
<filter-element type="OBJECT" id="synonym" selected="false" />
<filter-element type="OBJECT" id="sequence" selected="false" />
<filter-element type="OBJECT" id="procedure" selected="false" />
<filter-element type="OBJECT" id="function" selected="false" />
<filter-element type="OBJECT" id="package" selected="false" />
<filter-element type="OBJECT" id="type" selected="false" />
<filter-element type="OBJECT" id="dimension" selected="false" />
<filter-element type="OBJECT" id="cluster" selected="false" />
<filter-element type="OBJECT" id="dblink" selected="false" />
</public-schema>
<any-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</any-schema>
</basic-filter>
<extended-filter>
<filter-element type="RESERVED_WORD" id="keyword" selected="true" />
<filter-element type="RESERVED_WORD" id="function" selected="true" />
<filter-element type="RESERVED_WORD" id="parameter" selected="true" />
<filter-element type="RESERVED_WORD" id="datatype" selected="true" />
<filter-element type="RESERVED_WORD" id="exception" selected="true" />
<filter-element type="OBJECT" id="schema" selected="true" />
<filter-element type="OBJECT" id="user" selected="true" />
<filter-element type="OBJECT" id="role" selected="true" />
<filter-element type="OBJECT" id="privilege" selected="true" />
<user-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</user-schema>
<public-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</public-schema>
<any-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</any-schema>
</extended-filter>
</filters>
<sorting enabled="true">
<sorting-element type="RESERVED_WORD" id="keyword" />
<sorting-element type="RESERVED_WORD" id="datatype" />
<sorting-element type="OBJECT" id="column" />
<sorting-element type="OBJECT" id="table" />
<sorting-element type="OBJECT" id="view" />
<sorting-element type="OBJECT" id="materialized view" />
<sorting-element type="OBJECT" id="index" />
<sorting-element type="OBJECT" id="constraint" />
<sorting-element type="OBJECT" id="trigger" />
<sorting-element type="OBJECT" id="synonym" />
<sorting-element type="OBJECT" id="sequence" />
<sorting-element type="OBJECT" id="procedure" />
<sorting-element type="OBJECT" id="function" />
<sorting-element type="OBJECT" id="package" />
<sorting-element type="OBJECT" id="type" />
<sorting-element type="OBJECT" id="dimension" />
<sorting-element type="OBJECT" id="cluster" />
<sorting-element type="OBJECT" id="dblink" />
<sorting-element type="OBJECT" id="schema" />
<sorting-element type="OBJECT" id="role" />
<sorting-element type="OBJECT" id="user" />
<sorting-element type="RESERVED_WORD" id="function" />
<sorting-element type="RESERVED_WORD" id="parameter" />
</sorting>
<format>
<enforce-code-style-case value="true" />
</format>
</code-completion-settings>
<execution-engine-settings>
<statement-execution>
<fetch-block-size value="100" />
<execution-timeout value="20" />
<debug-execution-timeout value="600" />
<focus-result value="false" />
<prompt-execution value="false" />
</statement-execution>
<script-execution>
<command-line-interfaces />
<execution-timeout value="300" />
</script-execution>
<method-execution>
<execution-timeout value="30" />
<debug-execution-timeout value="600" />
<parameter-history-size value="10" />
</method-execution>
</execution-engine-settings>
<operation-settings>
<transactions>
<uncommitted-changes>
<on-project-close value="ASK" />
<on-disconnect value="ASK" />
<on-autocommit-toggle value="ASK" />
</uncommitted-changes>
<multiple-uncommitted-changes>
<on-commit value="ASK" />
<on-rollback value="ASK" />
</multiple-uncommitted-changes>
</transactions>
<session-browser>
<disconnect-session value="ASK" />
<kill-session value="ASK" />
<reload-on-filter-change value="false" />
</session-browser>
<compiler>
<compile-type value="KEEP" />
<compile-dependencies value="ASK" />
<always-show-controls value="false" />
</compiler>
<debugger>
<debugger-type value="JDBC" />
<use-generic-runners value="true" />
</debugger>
</operation-settings>
<ddl-file-settings>
<extensions>
<mapping file-type-id="VIEW" extensions="vw" />
<mapping file-type-id="TRIGGER" extensions="trg" />
<mapping file-type-id="PROCEDURE" extensions="prc" />
<mapping file-type-id="FUNCTION" extensions="fnc" />
<mapping file-type-id="PACKAGE" extensions="pkg" />
<mapping file-type-id="PACKAGE_SPEC" extensions="pks" />
<mapping file-type-id="PACKAGE_BODY" extensions="pkb" />
<mapping file-type-id="TYPE" extensions="tpe" />
<mapping file-type-id="TYPE_SPEC" extensions="tps" />
<mapping file-type-id="TYPE_BODY" extensions="tpb" />
</extensions>
<general>
<lookup-ddl-files value="true" />
<create-ddl-files value="false" />
<synchronize-ddl-files value="true" />
<use-qualified-names value="false" />
<make-scripts-rerunnable value="true" />
</general>
</ddl-file-settings>
<general-settings>
<regional-settings>
<date-format value="MEDIUM" />
<number-format value="UNGROUPED" />
<locale value="SYSTEM_DEFAULT" />
<use-custom-formats value="false" />
</regional-settings>
<environment>
<environment-types>
<environment-type id="development" name="Development" description="Development environment" color="-2430209/-12296320" readonly-code="false" readonly-data="false" />
<environment-type id="integration" name="Integration" description="Integration environment" color="-2621494/-12163514" readonly-code="true" readonly-data="false" />
<environment-type id="production" name="Production" description="Productive environment" color="-11574/-10271420" readonly-code="true" readonly-data="true" />
<environment-type id="other" name="Other" description="" color="-1576/-10724543" readonly-code="false" readonly-data="false" />
</environment-types>
<visibility-settings>
<connection-tabs value="true" />
<dialog-headers value="true" />
<object-editor-tabs value="true" />
<script-editor-tabs value="false" />
<execution-result-tabs value="true" />
</visibility-settings>
</environment>
</general-settings>
</component>
<component name="DBNavigator.Project.StatementExecutionManager">
<execution-variables />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="ERROR" enabled_by_default="true" />
</profile>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="JSX" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/moecube-console-web.iml" filepath="$PROJECT_DIR$/.idea/moecube-console-web.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectTasksOptions">
<TaskOptions isEnabled="false">
<option name="arguments" value="--no-color $FileName$" />
<option name="checkSyntaxErrors" value="true" />
<option name="description" />
<option name="exitCodeBehavior" value="ERROR" />
<option name="fileExtension" value="less" />
<option name="immediateSync" value="true" />
<option name="name" value="Less" />
<option name="output" value="$FileNameWithoutExtension$.css" />
<option name="outputFilters">
<array>
<FilterInfo>
<option name="description" value="lessc error format" />
<option name="name" value="lessc" />
<option name="regExp" value="$MESSAGE$\Q in \E$FILE_PATH$\Q on line \E$LINE$\Q, column \E$COLUMN$" />
</FilterInfo>
</array>
</option>
<option name="outputFromStdout" value="true" />
<option name="program" value="" />
<option name="scopeName" value="Project Files" />
<option name="trackOnlyRoot" value="false" />
<option name="workingDir" value="$FileDir$" />
<envs />
</TaskOptions>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="7dc474d0-9fc0-4b76-8c2f-3c98df702116" name="Default" comment="">
<change type="DELETED" beforePath="$PROJECT_DIR$/src/components/Example.js" afterPath="" />
<change type="MOVED" beforePath="$PROJECT_DIR$/.roadhogrc" afterPath="$PROJECT_DIR$/.roadhogrc.js" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/.eslintrc" afterPath="$PROJECT_DIR$/.eslintrc" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/package.json" afterPath="$PROJECT_DIR$/package.json" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/public/index.html" afterPath="$PROJECT_DIR$/public/index.html" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/components/App/Create.js" afterPath="$PROJECT_DIR$/src/components/App/Create.js" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/components/Common/Nav.js" afterPath="$PROJECT_DIR$/src/components/Common/Nav.js" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/index.js" afterPath="$PROJECT_DIR$/src/index.js" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/models/App.js" afterPath="$PROJECT_DIR$/src/models/App.js" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/models/Apps.js" afterPath="$PROJECT_DIR$/src/models/Apps.js" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/router.js" afterPath="$PROJECT_DIR$/src/router.js" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/routes/AppDetail.js" afterPath="$PROJECT_DIR$/src/routes/AppDetail.js" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/routes/AppDetail.less" afterPath="$PROJECT_DIR$/src/routes/AppDetail.less" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/routes/Entry.js" afterPath="$PROJECT_DIR$/src/routes/Entry.js" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/utils/request.js" afterPath="$PROJECT_DIR$/src/utils/request.js" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/yarn.lock" afterPath="$PROJECT_DIR$/yarn.lock" />
</list>
<ignored path="$PROJECT_DIR$/.tmp/" />
<ignored path="$PROJECT_DIR$/temp/" />
<ignored path="$PROJECT_DIR$/tmp/" />
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="TRACKING_ENABLED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ExecutionTargetManager" SELECTED_TARGET="default_target" />
<component name="FavoritesManager">
<favorites_list name="moecube-console-web" />
</component>
<component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file leaf-file-name="AppDetail.js" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/src/routes/AppDetail.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="798">
<caret line="701" column="40" lean-forward="false" selection-start-line="701" selection-start-column="40" selection-end-line="701" selection-end-column="40" />
<folding>
<element signature="e#0#26#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="FindInProjectRecents">
<findStrings>
<find>for</find>
<find>f</find>
<find>.update({ $set: { ...data }}).exec()</find>
<find>fo</find>
<find>format</find>
<find>formatm</find>
<find>formatme</find>
<find>cate</find>
<find>category</find>
<find>news</find>
<find>s</find>
<find>spin</find>
<find>&lt;</find>
<find>&lt;Sp</find>
<find>&lt;Spin</find>
<find>i</find>
<find>isMoun</find>
<find>isMounte</find>
<find>isMounted</find>
<find>isdanger</find>
<find>remove</find>
<find>width=&quot;100%&quot; height=&quot;100%&quot;</find>
<find>radio</find>
<find>console</find>
<find>pack</find>
<find>upload</find>
</findStrings>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/src/models/Common.js" />
<option value="$PROJECT_DIR$/src/models/App.js" />
<option value="$PROJECT_DIR$/src/components/App/Create.js" />
<option value="$PROJECT_DIR$/src/router.js" />
<option value="$PROJECT_DIR$/.roadhogrc" />
<option value="$PROJECT_DIR$/public/index.html" />
<option value="$PROJECT_DIR$/src/components/Common/Nav.js" />
<option value="$PROJECT_DIR$/.eslintrc" />
<option value="$PROJECT_DIR$/src/utils/request.js" />
<option value="$PROJECT_DIR$/src/index.js" />
<option value="$PROJECT_DIR$/src/routes/Entry.js" />
<option value="$PROJECT_DIR$/src/models/Apps.js" />
<option value="$PROJECT_DIR$/src/routes/AppDetail.less" />
<option value="$PROJECT_DIR$/src/routes/AppDetail.js" />
</list>
</option>
</component>
<component name="JsBuildToolGruntFileManager" detection-done="true" sorting="DEFINITION_ORDER" />
<component name="JsBuildToolPackageJson" detection-done="true" sorting="DEFINITION_ORDER">
<package-json value="$PROJECT_DIR$/package.json" />
</component>
<component name="JsGulpfileManager">
<detection-done>true</detection-done>
<sorting>DEFINITION_ORDER</sorting>
</component>
<component name="NodeModulesDirectoryManager">
<handled-path value="$PROJECT_DIR$/node_modules" />
</component>
<component name="ProjectFrameBounds">
<option name="x" value="235" />
<option name="y" value="58" />
<option name="width" value="1383" />
<option name="height" value="968" />
</component>
<component name="ProjectView">
<navigator currentView="ProjectPane" proportions="" version="1">
<flattenPackages />
<showMembers />
<showModules />
<showLibraryContents />
<hideEmptyPackages />
<abbreviatePackageNames />
<autoscrollToSource />
<autoscrollFromSource />
<sortByType />
<manualOrder />
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="Scratches" />
<pane id="Scope" />
<pane id="ProjectPane">
<subPane>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="moecube-console-web" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="moecube-console-web" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="moecube-console-web" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="moecube-console-web" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="src" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
</subPane>
</pane>
</panes>
</component>
<component name="PropertiesComponent">
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="HbShouldOpenHtmlAsHb" value="" />
<property name="node.js.path.for.package.eslint" value="project" />
<property name="nodejs_interpreter_path" value="/usr/local/bin/node" />
<property name="node.js.selected.package.eslint" value="$PROJECT_DIR$/node_modules/eslint" />
<property name="node.js.path.for.package.standard" value="project" />
<property name="node.js.selected.package.standard" value="" />
</component>
<component name="RecentsManager">
<key name="MoveFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$" />
</key>
</component>
<component name="RunDashboard">
<option name="ruleStates">
<list>
<RuleState>
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
</RuleState>
<RuleState>
<option name="name" value="StatusDashboardGroupingRule" />
</RuleState>
</list>
</option>
</component>
<component name="RunManager">
<configuration default="true" type="DartCommandLineRunConfigurationType" factoryName="Dart Command Line Application">
<method />
</configuration>
<configuration default="true" type="DartTestRunConfigurationType" factoryName="Dart Test">
<method />
</configuration>
<configuration default="true" type="JavaScriptTestRunnerJest" factoryName="Jest">
<node-interpreter value="project" />
<working-dir value="" />
<envs />
<scope-kind value="ALL" />
<method />
</configuration>
<configuration default="true" type="JavaScriptTestRunnerKarma" factoryName="Karma">
<config-file value="" />
<node-interpreter value="project" />
<envs />
<method />
</configuration>
<configuration default="true" type="JavaScriptTestRunnerProtractor" factoryName="Protractor">
<config-file value="" />
<node-interpreter value="project" />
<envs />
<method />
</configuration>
<configuration default="true" type="JavascriptDebugType" factoryName="JavaScript Debug">
<method />
</configuration>
<configuration default="true" type="NodeJSConfigurationType" factoryName="Node.js" path-to-node="project" working-dir="">
<method />
</configuration>
<configuration default="true" type="cucumber.js" factoryName="Cucumber.js">
<option name="cucumberJsArguments" value="" />
<option name="executablePath" />
<option name="filePath" />
<method />
</configuration>
<configuration default="true" type="js.build_tools.gulp" factoryName="Gulp.js">
<method />
</configuration>
<configuration default="true" type="js.build_tools.npm" factoryName="npm">
<command value="run" />
<scripts />
<node-interpreter value="project" />
<envs />
<method />
</configuration>
<configuration default="true" type="mocha-javascript-test-runner" factoryName="Mocha">
<node-interpreter>project</node-interpreter>
<node-options />
<working-directory />
<pass-parent-env>true</pass-parent-env>
<envs />
<ui />
<extra-mocha-options />
<test-kind>DIRECTORY</test-kind>
<test-directory />
<recursive>false</recursive>
<method />
</configuration>
</component>
<component name="ShelveChangesManager" show_recycled="false">
<option name="remove_strategy" value="false" />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="7dc474d0-9fc0-4b76-8c2f-3c98df702116" name="Default" comment="" />
<created>1492397512644</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1492397512644</updated>
<workItem from="1492397516564" duration="4541000" />
<workItem from="1492407287300" duration="13890000" />
</task>
<servers />
</component>
<component name="TimeTrackingManager">
<option name="totallyTimeSpent" value="18431000" />
</component>
<component name="ToolWindowManager">
<frame x="235" y="58" width="1383" height="968" extended-state="0" />
<editor active="true" />
<layout>
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
<window_info id="DB Browser" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32966226" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="DB Execution Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="npm" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32966226" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32990867" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33333334" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="TypeScript" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.2572707" sideWeight="0.49315068" order="0" side_tool="false" content_ui="combo" />
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.24981357" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25354213" sideWeight="0.5068493" order="2" side_tool="true" content_ui="tabs" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
</layout>
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="processedProjectFiles" value="true" />
<option name="exactExcludedFiles">
<list>
<option value="$PROJECT_DIR$/../moecube-console-backend/src/types.js" />
<option value="$PROJECT_DIR$/../moecube-console-backend/src/types.js.map" />
<option value="$PROJECT_DIR$/../moecube-console-backend/src/models/Iridium.js.map" />
<option value="$PROJECT_DIR$/../moecube-console-backend/src/models/Iridium.js" />
<option value="$PROJECT_DIR$/../moecube-console-backend/src/models/Package.js" />
<option value="$PROJECT_DIR$/../moecube-console-backend/src/models/Package.js.map" />
<option value="$PROJECT_DIR$/../moecube-console-backend/src/routes/upload.js.map" />
<option value="$PROJECT_DIR$/../moecube-console-backend/src/routes/upload.js" />
<option value="$PROJECT_DIR$/../moecube-console-backend/src/utils.js.map" />
<option value="$PROJECT_DIR$/../moecube-console-backend/src/utils.js" />
</list>
</option>
</component>
<component name="VcsContentAnnotationSettings">
<option name="myLimit" value="2678400000" />
</component>
<component name="XDebuggerManager">
<breakpoint-manager />
<watches-manager />
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/src/index.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="162">
<caret line="14" column="3" lean-forward="false" selection-start-line="14" selection-start-column="3" selection-end-line="14" selection-end-column="3" />
<folding>
<element signature="e#0#33#0" expanded="false" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/app.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/package.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/.roadhogrc.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="270">
<caret line="15" column="61" lean-forward="true" selection-start-line="15" selection-start-column="61" selection-end-line="15" selection-end-column="61" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/router.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="54">
<caret line="9" column="0" lean-forward="true" selection-start-line="9" selection-start-column="0" selection-end-line="9" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/routes/Apps.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/routes/Entry.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="324">
<caret line="25" column="1" lean-forward="true" selection-start-line="25" selection-start-column="1" selection-end-line="25" selection-end-column="1" />
<folding>
<element signature="e#0#26#0" expanded="false" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/components/Common/Nav.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="108">
<caret line="9" column="10" lean-forward="true" selection-start-line="9" selection-start-column="10" selection-end-line="9" selection-end-column="10" />
<folding>
<element signature="e#0#26#0" expanded="false" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/models/Apps.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="918">
<caret line="53" column="56" lean-forward="true" selection-start-line="53" selection-start-column="56" selection-end-line="53" selection-end-column="56" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/public/index.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="288">
<caret line="16" column="0" lean-forward="true" selection-start-line="16" selection-start-column="0" selection-end-line="16" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/dist/index.css">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="252">
<caret line="0" column="1627" lean-forward="false" selection-start-line="0" selection-start-column="1627" selection-end-line="0" selection-end-column="1627" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/routes/Login.css">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/routes/IndexPage.css">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/routes/LoginCallback.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/routes/Login.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/models/Common.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="90">
<caret line="5" column="18" lean-forward="true" selection-start-line="5" selection-start-column="18" selection-end-line="5" selection-end-column="18" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/models/user.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/routes/Apps/All.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-159">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding>
<element signature="e#0#26#0" expanded="false" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/routes/Apps.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/components/App/Create.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="162">
<caret line="9" column="4" lean-forward="false" selection-start-line="9" selection-start-column="4" selection-end-line="9" selection-end-column="4" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/public/index.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="198">
<caret line="11" column="0" lean-forward="true" selection-start-line="11" selection-start-column="0" selection-end-line="11" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/app.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/.roadhogrc.mock.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="54">
<caret line="3" column="0" lean-forward="true" selection-start-line="3" selection-start-column="0" selection-end-line="3" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/config.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="108">
<caret line="6" column="1" lean-forward="false" selection-start-line="6" selection-start-column="1" selection-end-line="6" selection-end-column="1" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/node_modules/dva/router.d.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="108">
<caret line="6" column="9" lean-forward="false" selection-start-line="6" selection-start-column="9" selection-end-line="6" selection-end-column="9" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/.roadhogrc.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="288">
<caret line="16" column="7" lean-forward="true" selection-start-line="16" selection-start-column="7" selection-end-line="16" selection-end-column="7" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/components/Example.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="180">
<caret line="10" column="21" lean-forward="true" selection-start-line="10" selection-start-column="21" selection-end-line="10" selection-end-column="21" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/components/Common/Nav.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="176">
<caret line="25" column="12" lean-forward="true" selection-start-line="25" selection-start-column="12" selection-end-line="25" selection-end-column="12" />
<folding>
<element signature="e#0#26#0" expanded="false" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/components/Common/EditableCell.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="684">
<caret line="38" column="20" lean-forward="true" selection-start-line="38" selection-start-column="20" selection-end-line="38" selection-end-column="20" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/index.less">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/package.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/.eslintrc">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="90">
<caret line="5" column="34" lean-forward="true" selection-start-line="5" selection-start-column="34" selection-end-line="5" selection-end-column="34" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/router.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="108">
<caret line="12" column="41" lean-forward="true" selection-start-line="12" selection-start-column="41" selection-end-line="12" selection-end-column="41" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/utils/request.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="252">
<caret line="14" column="46" lean-forward="true" selection-start-line="14" selection-start-column="46" selection-end-line="14" selection-end-column="46" />
<folding>
<element signature="e#0#30#0" expanded="false" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/index.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="144">
<caret line="13" column="26" lean-forward="true" selection-start-line="13" selection-start-column="26" selection-end-line="13" selection-end-column="26" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/models/App.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="252">
<caret line="14" column="14" lean-forward="true" selection-start-line="14" selection-start-column="14" selection-end-line="14" selection-end-column="14" />
<folding>
<element signature="e#0#39#0" expanded="false" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/dist/index.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="18">
<caret line="12" column="19201" lean-forward="false" selection-start-line="12" selection-start-column="19201" selection-end-line="12" selection-end-column="19201" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/node_modules/antd/lib/tabs/index.d.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="220">
<caret line="34" column="21" lean-forward="false" selection-start-line="34" selection-start-column="21" selection-end-line="34" selection-end-column="21" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/models/Apps.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="593">
<caret line="54" column="38" lean-forward="true" selection-start-line="54" selection-start-column="38" selection-end-line="54" selection-end-column="38" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/routes/Entry.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="270">
<caret line="15" column="4" lean-forward="true" selection-start-line="15" selection-start-column="4" selection-end-line="15" selection-end-column="4" />
<folding>
<element signature="e#0#26#0" expanded="false" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/routes/AppDetail.less">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="108">
<caret line="6" column="26" lean-forward="true" selection-start-line="6" selection-start-column="26" selection-end-line="6" selection-end-column="26" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/routes/IndexPage.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="270">
<caret line="17" column="23" lean-forward="false" selection-start-line="17" selection-start-column="23" selection-end-line="17" selection-end-column="23" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/node_modules/antd/lib/input/Input.d.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="124">
<caret line="60" column="6" lean-forward="true" selection-start-line="60" selection-start-column="6" selection-end-line="60" selection-end-column="6" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/node_modules/antd/lib/form/Form.d.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="187">
<caret line="73" column="21" lean-forward="false" selection-start-line="73" selection-start-column="21" selection-end-line="73" selection-end-column="21" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/routes/AppDetail.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="798">
<caret line="701" column="40" lean-forward="false" selection-start-line="701" selection-start-column="40" selection-end-line="701" selection-end-column="40" />
<folding>
<element signature="e#0#26#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</component>
</project>
\ No newline at end of file
{ export default {
"entry": "src/index.js", "entry": "src/index.js",
"env": { "env": {
"development": { "development": {
"extraBabelPlugins": [ "extraBabelPlugins": [
"dva-hmr", "dva-hmr",
"transform-runtime", "transform-runtime",
"babel-plugin-transform-decorators-legacy",
["import", { "libraryName": "antd", "style": "css" }] ["import", { "libraryName": "antd", "style": "css" }]
] ]
}, },
"production": { "production": {
"extraBabelPlugins": [ "extraBabelPlugins": [
"transform-runtime", "transform-runtime",
"babel-plugin-transform-decorators-legacy",
["import", { "libraryName": "antd", "style": "css" }] ["import", { "libraryName": "antd", "style": "css" }]
] ]
} }
......
...@@ -3,15 +3,14 @@ ...@@ -3,15 +3,14 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>Dva Demo</title> <link rel="stylesheet" href="index.css"/>
<link rel="stylesheet" href="index.css" /> <link rel="icon" href="https://moecube.com/favicon.ico">
<base href="/">
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>
<script src="index.js"></script> <script src="/index.js"></script>
</body> </body>
</html> </html>
import React from 'react'; import React from 'react';
import styles from './Create.css'; import styles from './Create.css';
import { Button, Modal, Form, Input, Radio, Select, Spin } from 'antd'; import { Button, Modal, Form, Input, Radio, Select, Spin } from 'antd';
import { connect } from 'dva'
const FormItem = Form.Item; const FormItem = Form.Item;
@connect(
(state, props) => {
const { loading } = state
return {
loading
}
}
)
class Create extends React.Component { class Create extends React.Component {
handleSubmit = (e) => { handleSubmit = (e) => {
...@@ -20,11 +29,11 @@ class Create extends React.Component { ...@@ -20,11 +29,11 @@ class Create extends React.Component {
} }
handleSelectChange = (value) => { handleSelectChange = (value) => {
} }
render() { render() {
const { visible, onCancel, form, isLoading } = this.props; const { visible, onCancel, form, loading } = this.props;
const { getFieldDecorator } = form; const { getFieldDecorator } = form;
return ( return (
...@@ -34,7 +43,7 @@ class Create extends React.Component { ...@@ -34,7 +43,7 @@ class Create extends React.Component {
okText="提交" okText="提交"
onCancel={onCancel} onCancel={onCancel}
onOk={this.handleSubmit}> onOk={this.handleSubmit}>
<Spin spinning={isLoading} delay={100} tip="提交中..."> <Spin spinning={loading.global} delay={100} tip="提交中...">
<Form vertical onSubmit={this.handleSubmit}> <Form vertical onSubmit={this.handleSubmit}>
<FormItem label="应用 ID (创建应用后无法修改)"> <FormItem label="应用 ID (创建应用后无法修改)">
...@@ -56,7 +65,7 @@ class Create extends React.Component { ...@@ -56,7 +65,7 @@ class Create extends React.Component {
<FormItem <FormItem
label="主要语言" label="主要语言"
wrapperCol={{ span: 8 }}> wrapperCol={{ span: 8 }}>
{getFieldDecorator('locale', { {getFieldDecorator('locale', {
rules: [{ required: true, message: '请至少选择一门主要语言' }], rules: [{ required: true, message: '请至少选择一门主要语言' }],
onChange: this.handleSelectChange, onChange: this.handleSelectChange,
...@@ -65,13 +74,13 @@ class Create extends React.Component { ...@@ -65,13 +74,13 @@ class Create extends React.Component {
<Select.Option value="zh-CN">zh-CN</Select.Option> <Select.Option value="zh-CN">zh-CN</Select.Option>
<Select.Option value="zh-TW">zh-TW</Select.Option> <Select.Option value="zh-TW">zh-TW</Select.Option>
<Select.Option value="en-US">en-US</Select.Option> <Select.Option value="en-US">en-US</Select.Option>
<Select.Option value="ja-JP">ja-JP</Select.Option> <Select.Option value="ja-JP">ja-JP</Select.Option>
</Select> </Select>
)} )}
</FormItem> </FormItem>
</Form> </Form>
</Spin> </Spin>
</Modal> </Modal>
); );
} }
......
...@@ -2,30 +2,44 @@ import React from 'react'; ...@@ -2,30 +2,44 @@ import React from 'react';
import styles from './Nav.less'; import styles from './Nav.less';
import { Layout, Menu, Icon, Breadcrumb } from 'antd'; import { Layout, Menu, Icon, Breadcrumb } from 'antd';
import {Link} from 'dva/router' import {Link} from 'dva/router'
import { FormattedMessage } from 'react-intl' import {connect} from 'dva'
const { Header, Sider, Content, Footer } = Layout; const { Header, Sider, Content, Footer } = Layout;
const SubMenu = Menu.SubMenu const SubMenu = Menu.SubMenu
function Nav({ collapsed, mode, dispatch }) {
return (
<Sider
collapsible
collapsed={collapsed}
onCollapse={() => dispatch({ type: 'Common/collapsed' })}>
<div className={styles.logo} />
<Menu theme="dark" mode={mode} defaultSelectedKeys={['0']}>
<Menu.Item key="0"> @connect(
<Link to="/apps"> (state, props) => {
<Icon type="windows-o" /> const {
Common: {collapsed, mode}
} = state
return {
collapsed,
mode
}
}
)
export default class Nav extends React.Component {
render(){
const { collapsed, mode, dispatch } = this.props
return (
<Sider
collapsible
collapsed={collapsed}
onCollapse={() => dispatch({ type: 'Common/collapsed' })}>
<div className={styles.logo} />
<Menu theme="dark" mode={mode} defaultSelectedKeys={['0']}>
<Menu.Item key="0">
<Link to="/apps">
<Icon type="windows-o" />
<span className="nav-next"> <span className="nav-next">
<FormattedMessage id="Apps"/> apps
</span> </span>
</Link> </Link>
</Menu.Item> </Menu.Item>
</Menu> </Menu>
</Sider> </Sider>
); )
}
} }
export default Nav;
import React from 'react';
const Example = () => {
return (
<div>
Example
</div>
);
};
Example.propTypes = {
};
export default Example;
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { browserHistory } from 'dva/router' import {browserHistory} from 'dva/router'
import createLoading from 'dva-loading'
import {message} from 'antd'
import dva from 'dva'; import dva from 'dva';
import './index.less'; import './index.less';
import { IntlProvider, addLocaleData } from 'react-intl';
// 1. Initialize // 1. Initialize
const app = dva({ const app = dva({
history: browserHistory onError: (error) => {
message.destroy();
message.error(error.message);
},
history: browserHistory,
}); });
app.model(require("./models/Apps")); app.model(require("./models/Apps"));
...@@ -24,6 +26,7 @@ app.model(require("./models/App")); ...@@ -24,6 +26,7 @@ app.model(require("./models/App"));
// 2. Plugins // 2. Plugins
// app.use({}); // app.use({});
app.use(createLoading())
// 3. Model // 3. Model
// app.model(require('./models/example')); // app.model(require('./models/example'));
...@@ -31,24 +34,10 @@ app.model(require("./models/App")); ...@@ -31,24 +34,10 @@ app.model(require("./models/App"));
// 4. Router // 4. Router
app.router(require('./router')); app.router(require('./router'));
// 5. Start
import en from 'react-intl/locale-data/en'
import zh from 'react-intl/locale-data/zh'
import localeData from '../i18n.json'
addLocaleData([...en, ...zh])
const language = navigator.language || (navigator.languages && navigator.languages[0]) || navigator.userLanguage;
const languageWithoutRegionCode = language.toLowerCase().split(/[_-]+/)[0];
const messages = localeData[languageWithoutRegionCode] || localeData[language] || localeData.zh;
const App = app.start() const App = app.start()
ReactDOM.render( ReactDOM.render(
<IntlProvider locale={ language } messages={ messages }> <App />,
<App />
</IntlProvider>,
document.getElementById("root") document.getElementById("root")
) )
import { create } from '../services/Apps' import {create} from '../services/Apps'
import {message} from 'antd'
export default { export default {
namespace: 'App', namespace: 'App',
...@@ -23,13 +24,6 @@ export default { ...@@ -23,13 +24,6 @@ export default {
isSubmit: true, isSubmit: true,
} }
}, },
SubmitSuccess(state, action){
return {
...state,
isSubmit: false,
isCreate: false
}
},
onCancel(state, action) { onCancel(state, action) {
return { return {
...state, ...state,
...@@ -49,8 +43,8 @@ export default { ...@@ -49,8 +43,8 @@ export default {
} }
}, },
effects: { effects: {
*submit({ payload }, { call, put }){ *submit({payload}, {call, put}){
yield put({ type: 'SubmitRequest', payload }) yield put({type: 'SubmitRequest', payload})
const params = { const params = {
id: payload.id, id: payload.id,
...@@ -59,13 +53,16 @@ export default { ...@@ -59,13 +53,16 @@ export default {
} }
} }
const req = yield call(create, params) try {
if(req.data) { const {data} = yield call(create, params)
yield put({ type: 'SubmitSuccess' }) if (data) {
yield put({ type: 'reset' }) yield put({type: 'SubmitSuccess'})
// TODO: 成功提示 yield put({type: 'reset'})
message.info("i18n 创建成功")
}
} catch (error) {
message.error(error.message)
} }
// TODO: 错误处理
} }
}, },
subscriptions: {}, subscriptions: {},
......
import { fetch, update } from '../services/Apps' import {fetch, update} from '../services/Apps'
import * as crypto from 'crypto' import * as crypto from 'crypto'
import {message} from 'antd'
import config from '../config' import config from '../config'
...@@ -10,47 +11,65 @@ export default { ...@@ -10,47 +11,65 @@ export default {
}, },
reducers: { reducers: {
save(state, action) { save(state, action) {
return { return {
...state, ...state,
...action.payload ...action.payload
} }
}, },
}, },
effects: { effects: {
*fetch({ payload }, { call, put }) { *fetch({payload}, {call, put}) {
const { data } = yield call(fetch, payload)
let apps = {} try {
if(data && data.length > 0) { const {data} = yield call(fetch, payload)
data.map(app => {
apps[app["id"]] = app let apps = {}
}) if (data && data.length > 0) {
data.map(app => {
apps[app["id"]] = app
})
}
yield put({type: 'save', payload: {apps}})
} catch (error) {
message.error(error.message)
} }
yield put({ type: 'save', payload: { apps } })
}, },
*update({ payload }, {call, put}){ *update({payload}, {call, put}){
const { data } = yield call(update, payload) try {
const {data} = yield call(update, payload)
if (data) { if (data) {
yield put({ type: 'success'}) yield put({type: 'success'})
} else { message.info("i18n success")
yield put({ type: 'faile' }) }
} catch (error) {
message.error(error.message)
} }
}, },
*success({ payload }, { call, put}) { *addPackage({payload}, {call, put}){
yield put({ type: 'fetch' }) try {
const {data} = yield call(update, payload)
if (data) {
yield put({type: 'success'})
}
} catch (error) {
message.error(error.message)
}
},
*success({payload}, {call, put}) {
yield put({type: 'fetch'})
} }
}, },
subscriptions: { subscriptions: {
setup({ dispatch, history }) { setup({dispatch, history}) {
return history.listen(({ pathname, query}) => {
dispatch({type: 'fetch'})
if(/^apps/.test(pathname)) { return history.listen(({pathname, query}) => {
dispatch({ type: 'fetch', payload: query}) if (pathname === '/login') {
} else if(pathname === '/login'){
let params = new URLSearchParams() let params = new URLSearchParams()
params.set('return_sso_url', config.returnSSO) params.set('return_sso_url', config.returnSSO)
let payload = Buffer.from(params.toString()).toString('base64') let payload = Buffer.from(params.toString()).toString('base64')
...@@ -59,7 +78,7 @@ export default { ...@@ -59,7 +78,7 @@ export default {
params.set('sso', payload); params.set('sso', payload);
params.set('sig', crypto.createHmac('sha256', 'zsZv6LXHDwwtUAGa').update(payload).digest('hex')) params.set('sig', crypto.createHmac('sha256', 'zsZv6LXHDwwtUAGa').update(payload).digest('hex'))
window.location.href=url window.location.href = url
} }
}) })
} }
......
...@@ -11,11 +11,10 @@ function RouterConfig({ history }) { ...@@ -11,11 +11,10 @@ function RouterConfig({ history }) {
return ( return (
<Router history={history}> <Router history={history}>
<Route path="/" component={Entry} > <Route path="/" component={Entry} >
<Route path="apps" component={Apps} /> <Route path="/apps/:id" component={AppDetail} />
<Route path="apps/:id" component={AppDetail} /> <Route path="/apps" component={Apps} />
</Route> </Route>
<Route path="/loginCallback" component={LoginCallback} /> <Route path="/loginCallback" component={LoginCallback} />
<Route path="*" component={() => <div>404</div>}/>
</Router> </Router>
); );
} }
......
import React from 'react'; import React from 'react';
import { connect } from 'dva'; import {connect} from 'dva';
import styles from './AppDetail.less'; import styles from './AppDetail.less';
import config from '../config' import config from '../config'
import uuid from 'uuid' import uuid from 'uuid'
import { Form, Input, Icon, Radio, Tag, Tooltip, Button, Select, Tabs, Upload, Modal, Table, Popconfirm, Row, Col, Card } from 'antd' import {
Form,
Input,
Icon,
Radio,
Tag,
Tooltip,
Button,
Select,
Tabs,
Upload,
Modal,
Table,
Popconfirm,
Row,
Col,
Card,
Spin,
} from 'antd'
const FormItem = Form.Item; const FormItem = Form.Item;
const RadioButton = Radio.Button; const RadioButton = Radio.Button;
const RadioGroup = Radio.Group; const RadioGroup = Radio.Group;
const Option = Select.Option; const Option = Select.Option;
const TabPane = Tabs.TabPane; const TabPane = Tabs.TabPane;
const Dragger = Upload.Dragger; const Dragger = Upload.Dragger;
const confirm = Modal.confirm
const defCategory = ["game", "runtime", "emulator", "module"] const defCategory = ["game", "runtime", "emulator", "module"]
const defLocales = ["zh-CN", "zh-TW", "en-US", "ja-JP"] const defLocales = ["zh-CN", "zh-TW", "en-US", "ja-JP"]
const defPlatform = ["win32","darwin"] const defPlatform = ["win32", "darwin"]
let defDevelopers = {} let defDevelopers = {}
let defPublishers = {} let defPublishers = {}
let defNews = {} let defNews = {}
...@@ -39,12 +55,11 @@ const defPackage = () => { ...@@ -39,12 +55,11 @@ const defPackage = () => {
} }
} }
const defPackages = { const defPackages = {}
}
const formItemLayout = { const formItemLayout = {
labelCol: { span: 5 }, labelCol: {span: 5},
wrapperCol: { span: 24 }, wrapperCol: {span: 24},
} }
const uploadProps = { const uploadProps = {
...@@ -57,9 +72,9 @@ const uploadProps = { ...@@ -57,9 +72,9 @@ const uploadProps = {
console.log(info.file, info.fileList); console.log(info.file, info.fileList);
} }
if (status === 'done') { if (status === 'done') {
message.success(`${info.file.name} file uploaded successfully.`); // message.success(`${info.file.name} file uploaded successfully.`);
} else if (status === 'error') { } else if (status === 'error') {
message.error(`${info.file.name} file upload failed.`); // message.error(`${info.file.name} file upload failed.`);
} }
}, },
} }
...@@ -70,7 +85,7 @@ class AppDetail extends React.Component { ...@@ -70,7 +85,7 @@ class AppDetail extends React.Component {
state = { state = {
previewVisible: false, previewVisible: false,
previewImage: '', previewImage: '',
icoList: [], iconList: [],
coverList: [], coverList: [],
backgroundList: [], backgroundList: [],
isCreateNews: false, isCreateNews: false,
...@@ -78,20 +93,19 @@ class AppDetail extends React.Component { ...@@ -78,20 +93,19 @@ class AppDetail extends React.Component {
publishers: {}, publishers: {},
news: {}, news: {},
packages: [], packages: [],
isDanger: false
}; };
componentWillReceiveProps(nextProps){ componentWillReceiveProps(nextProps) {
const { App:{ developers, publishers, news, packages = [] } } = nextProps const {App: {developers, publishers, news, packages = []}} = nextProps
this.setState({ this.setState({
developers: {...defDevelopers, ...developers}, developers: {...defDevelopers, ...developers},
publishers: {...defPublishers, ...publishers}, publishers: {...defPublishers, ...publishers},
packages: [...defPackages, ...packages], packages: [...defPackages, ...packages],
news: {...defNews, ...news}, news: {...defNews, ...news},
}) })
} }
handleCancel = () => this.setState({ previewVisible: false }) handleCancel = () => this.setState({previewVisible: false})
handlePreview = (file) => { handlePreview = (file) => {
this.setState({ this.setState({
...@@ -100,37 +114,36 @@ class AppDetail extends React.Component { ...@@ -100,37 +114,36 @@ class AppDetail extends React.Component {
}); });
} }
handleChangeIco = ({ fileList }) => { handleChangeIco = ({fileList}) => {
this.setState({ icoList: fileList }) this.setState({iconList: fileList})
this.handleUpdateImg({ fileList, field: 'icon'}) this.handleUpdateImg({fileList, field: 'icon'})
} }
handleChangeCover = ({ fileList }) => { handleChangeCover = ({fileList}) => {
this.setState({ coverList: fileList }) this.setState({coverList: fileList})
this.handleUpdateImg({ fileList, field: 'cover'}) this.handleUpdateImg({fileList, field: 'cover'})
} }
handleChangeBackground = ({ fileList }) => { handleChangeBackground = ({fileList}) => {
this.setState({ backgroundList: fileList }) this.setState({backgroundList: fileList})
this.handleUpdateImg({ fileList, field: 'background'}) this.handleUpdateImg({fileList, field: 'background'})
} }
handleUpdateImg = ({ field, fileList }) => {
const { form, dispatch, params: { id }} = this.props
const [img] = fileList
if(img.status === 'done') { handleUpdateImg = ({field, fileList}) => {
const {form, dispatch, params: {id}} = this.props
const [img] = fileList
if (img.status === 'done') {
const [res] = img.response const [res] = img.response
dispatch({type: "Apps/update", payload: {id, [field]: res.fileName }}) dispatch({type: "Apps/update", payload: {id, [field]: res.Key}})
} }
} }
onSubmitBase = (e) => { onSubmitBase = (e) => {
const { form, dispatch, params: { id }} = this.props const {form, dispatch, params: {id}} = this.props
e && e.preventDefault(); e && e.preventDefault();
form.validateFieldsAndScroll((err, values) => { form.validateFieldsAndScroll((err, values) => {
if (!err) { if (!err) {
console.log('Received values of form: ', values); console.log('Received values of form: ', values);
const {category, homepage, conference, tags, locales} = values const {category, homepage, conference, tags, locales} = values
dispatch({type: "Apps/update", payload: {id, category, homepage, conference, tags, locales}}) dispatch({type: "Apps/update", payload: {id, category, homepage, conference, tags, locales}})
...@@ -139,13 +152,13 @@ class AppDetail extends React.Component { ...@@ -139,13 +152,13 @@ class AppDetail extends React.Component {
} }
onSubmitIntro = (e) => { onSubmitIntro = (e) => {
const { form, dispatch, params: { id }} = this.props const {form, dispatch, params: {id}} = this.props
e && e.preventDefault(); e && e.preventDefault();
form.validateFieldsAndScroll((err, values) => { form.validateFieldsAndScroll((err, values) => {
if (!err) { if (!err) {
console.log('Received values of form: ', values); console.log('Received values of form: ', values);
const {description, name, developers, publishers, news} = values const {description, name, developers, publishers, news} = values
dispatch({type: "Apps/update", payload: {id, description, name, developers, publishers, news}}) dispatch({type: "Apps/update", payload: {id, description, name, developers, publishers, news}})
...@@ -154,47 +167,63 @@ class AppDetail extends React.Component { ...@@ -154,47 +167,63 @@ class AppDetail extends React.Component {
} }
onSubmitManage = (e) => { onSubmitManage = (e) => {
const { form, dispatch, params: { id }} = this.props const {form, dispatch, params: {id}} = this.props
e && e.preventDefault(); e && e.preventDefault();
form.validateFieldsAndScroll((err, values) => { form.validateFieldsAndScroll((err, values) => {
if (!err) { if (!err) {
console.log('Received values of form: ', values); console.log('Received values of form: ', values);
const {version, actions, references, dependencies} = values const {version, actions, references, dependencies} = values
Object.keys(actions).forEach((platform) => { Object.keys(actions).forEach((platform) => {
actions[platform] = JSON.parse(actions[platform]) actions[platform] = JSON.parse(actions[platform])
}) })
dispatch({type: "Apps/update", payload: {id, version, actions, references, dependencies }}) dispatch({type: "Apps/update", payload: {id, version, actions, references, dependencies}})
} }
}); });
} }
onSubmitUpload = (e) => { onSubmitUpload = (e, _pack) => {
const { form, dispatch, params: { id }} = this.props const {form, dispatch, params: {id}} = this.props
e && e.preventDefault(); e && e.preventDefault();
form.validateFieldsAndScroll((err, values) => { form.validateFieldsAndScroll((err, values) => {
if (!err) { if (!err) {
console.log('Received values of form: ', values); console.log('Received values of form: ', values);
let {upload: { packages }} = values
let {upload: {packages}} = values
const pack = packages.find(el => el.id == _pack.id)
dispatch({type: "Apps/update", payload: {id, packages}}) dispatch({type: "Apps/updatePackage", payload: {id, package: pack}})
}
});
}
onAddPackage = (e) => {
const {form, dispatch, params: {id}} = this.props
e && e.preventDefault();
form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
let {upload: {packages}} = values
dispatch({type: "Apps/addPackage", payload: {id, packages}})
} }
}); });
} }
onDeletePackage = (_id) => { onDeletePackage = (_id) => {
const { form, dispatch, params: { id }} = this.props const {form, dispatch, params: {id}} = this.props
form.validateFieldsAndScroll((err, values) => { form.validateFieldsAndScroll((err, values) => {
if (!err) { if (!err) {
let {upload: { packages }} = values let {upload: {packages}} = values
packages.splice(_id, 1) packages.splice(_id, 1)
dispatch({type: "Apps/update", payload: {id, packages}}) dispatch({type: "Apps/update", payload: {id, packages}})
...@@ -206,8 +235,6 @@ class AppDetail extends React.Component { ...@@ -206,8 +235,6 @@ class AppDetail extends React.Component {
this[action](targetKey); this[action](targetKey);
} }
add = async (targetKey) => { add = async (targetKey) => {
let packages = this.state.packages let packages = this.state.packages
...@@ -218,25 +245,30 @@ class AppDetail extends React.Component { ...@@ -218,25 +245,30 @@ class AppDetail extends React.Component {
packages packages
}) })
this.onSubmitUpload() // this.onSubmitUpload()
this.onAddPackage()
} }
remove = async (targetKey) => { remove = async (targetKey) => {
if(!this.props.isDanger) { confirm({
let {packages} = this.state title: '️警告',
packages.splice(targetKey,1) content: '你真的确定要删除嘛?',
onOk: async () => {
await this.setState({ let {packages} = this.state
packages packages.splice(targetKey, 1)
})
await this.setState({
this.onDeletePackage(targetKey) packages
} })
return this.onDeletePackage(targetKey)
},
})
} }
onAddField = ({locale, field, data}) => { onAddField = ({locale, field, data}) => {
let newField = Object.assign({}, this.state[field]) let newField = Object.assign({}, this.state[field])
newField[locale].push(data) newField[locale].push(data)
this.setState({ this.setState({
...@@ -247,7 +279,7 @@ class AppDetail extends React.Component { ...@@ -247,7 +279,7 @@ class AppDetail extends React.Component {
onDeleteField = ({locale, field, index}) => { onDeleteField = ({locale, field, index}) => {
let newField = Object.assign({}, this.state[field]) let newField = Object.assign({}, this.state[field])
newField[locale].splice(index,1) newField[locale].splice(index, 1)
this.setState({ this.setState({
[field]: newField [field]: newField
...@@ -255,464 +287,508 @@ class AppDetail extends React.Component { ...@@ -255,464 +287,508 @@ class AppDetail extends React.Component {
} }
render() { render() {
console.log(this.props, this.state) const {form, App, loading} = this.props
const {getFieldDecorator} = form
const { form, App} = this.props const {id, author, homepage, references = {}, dependencies = {}, description = {}, actions = {}, version = {}, name = {}, category, tags = [], locales = [], conference, icon, cover, background,} = App
const { getFieldDecorator } = form const {publishers, developers, previewVisible, previewImage, iconList, coverList, backgroundList, isCreateNews, news, packages} = this.state
const { id, author, homepage, references={}, dependencies={}, description={}, actions={}, version={}, name={}, category={}, tags=[], locales=[], conference, icon, cover, background, } = App
const { publishers, developers, previewVisible, previewImage, icoList, coverList, backgroundList, isCreateNews, news, packages } = this.state
return ( return (
<Tabs defaultActiveKey="1" className="app-detail-nav"> <Spin spinning={loading.global}>
<TabPane tab={<span><Icon type="setting" /> 基本信息 </span>} key="1"> <Tabs defaultActiveKey="1" className="app-detail-nav">
<div className={styles.form}> <TabPane tab={<span><Icon type="setting"/> 基本信息 </span>} key="1">
<Form onSubmit={this.onSubmitBase}> <div className={styles.form}>
<Form onSubmit={this.onSubmitBase}>
<div style={{ display: 'flex' }}>
<div style={{display: 'flex'}}>
<Modal visible={previewVisible} footer={null} onCancel={this.handleCancel}>
<img alt="example" style={{ width: '100%' }} src={previewImage} /> <Modal visible={previewVisible} footer={null} onCancel={this.handleCancel}>
</Modal> <img alt="example" style={{width: '100%'}} src={previewImage}/>
</Modal>
<FormItem {...formItemLayout}>
{getFieldDecorator('icon', { <FormItem {...formItemLayout}>
})( {getFieldDecorator('icon', {})(
<div className="clearfix"> <div className="clearfix">
<Upload <Upload
multiple={false} multiple={false}
action={`${config.apiRoot}/upload/image`} action={`${config.apiRoot}/upload/image`}
listType="picture-card" listType="picture-card"
className="upload-icon" className="upload-icon"
fileList={icoList} fileList={iconList}
onChange={this.handleChangeIco} onChange={this.handleChangeIco}
onPreview={this.handlePreview} onPreview={this.handlePreview}
> >
{icoList.length >= 1 ? null : {iconList.length >= 1 ? null :
<div> icon ?
<Icon type="plus" /> <img src={icon} width="100%" height="100%"/>
<div className="ant-upload-text">Icon</div> :
</div> <div>
} <Icon type="plus"/>
</Upload> <div className="ant-upload-text">Cover</div>
</div> </div>
)} }
</FormItem> </Upload>
</div>
<FormItem {...formItemLayout}> )}
{getFieldDecorator('cover', { </FormItem>
})(
<div className="clearfix"> <FormItem {...formItemLayout}>
<Upload {getFieldDecorator('cover', {})(
multiple={false} <div className="clearfix">
action={`${config.apiRoot}/upload/image`} <Upload
listType="picture-card" multiple={false}
className="upload-icon" action={`${config.apiRoot}/upload/image`}
fileList={coverList} listType="picture-card"
onChange={this.handleChangeCover} className="upload-icon"
onPreview={this.handlePreview} fileList={coverList}
> onChange={this.handleChangeCover}
{coverList.length >= 1 ? null : onPreview={this.handlePreview}
<div> >
<Icon type="plus" /> {coverList.length >= 1 ? null :
<div className="ant-upload-text">Cover</div> cover ?
</div> <img src={cover} width="100%" height="100%"/>
} :
</Upload> <div>
</div> <Icon type="plus"/>
)} <div className="ant-upload-text">Cover</div>
</FormItem> </div>
}
<FormItem {...formItemLayout}> </Upload>
{getFieldDecorator('background', { </div>
})( )}
<div className="clearfix"> </FormItem>
<Upload
multiple={false} <FormItem {...formItemLayout}>
action={`${config.apiRoot}/upload/image`} {getFieldDecorator('background', {})(
listType="picture-card" <div className="clearfix">
className="upload-icon" <Upload
fileList={backgroundList} multiple={false}
onChange={this.handleChangeBackground} action={`${config.apiRoot}/upload/image`}
onPreview={this.handlePreview} listType="picture-card"
> className="upload-icon"
{backgroundList.length >= 1 ? null : fileList={backgroundList}
<div> onChange={this.handleChangeBackground}
<Icon type="plus" /> onPreview={this.handlePreview}
<div className="ant-upload-text">Background</div> >
</div> {backgroundList.length >= 1 ? null :
} background ?
</Upload> <img src={background} width="100%" height="100%"/>
:
<div>
<Icon type="plus"/>
<div className="ant-upload-text">Cover</div>
</div>
}
</Upload>
</div>
)}
</FormItem>
</div> </div>
)}
</FormItem>
</div>
<FormItem {...formItemLayout} label="游戏类别" >
{getFieldDecorator('category', {
initialValue: category
})(
<RadioGroup>
{defCategory.map((c,i) => {
return <RadioButton value={c} key={i}>{c}</RadioButton>
})}
</RadioGroup>
)}
</FormItem>
<FormItem
{...formItemLayout}
help="以 http:// 或 https:// 开头,没有可留空">
{getFieldDecorator('homepage', {
initialValue: homepage
})(
<Input addonBefore={<Icon type="home" />} placeholder="网站" />
)}
</FormItem>
<FormItem
{...formItemLayout}
help="游戏类应用通常与 ID 相同,其他类型的应用留空">
{getFieldDecorator('conference', {
initialValue: conference
})(
<Input addonBefore={<Icon type="message" />} placeholder="聊天室" />
)}
</FormItem>
<FormItem
{...formItemLayout}
help="JSON string[],不会写请联系 zh99998@gmail.com"
>
{getFieldDecorator('tags', {
initialValue: tags
})(
<Select tags style={{ width: '100%' }} placeholder="标签">
</Select>
)}
</FormItem>
<FormItem {...formItemLayout}>
{getFieldDecorator('locales', {
initialValue: locales
})(
<Select
tags
style={{ width: '100%' }}
placeholder="游戏支持的语言">
{defLocales.map((locale,i) => {
return <Select.Option key={i} value={locale}>{locale}</Select.Option>
})}
</Select>
)}
</FormItem>
<FormItem {...formItemLayout} >
<div className={styles.wrapSubmit}>
<Button type="primary" htmlType="submit" size="large">提交</Button>
</div>
</FormItem>
</Form>
</div>
</TabPane>
<TabPane tab={<span><Icon type="solution" />应用介绍</span>} key="2">
<div className={styles.form}>
<Tabs type="card" className="app-detail-nav">
{defLocales.map((locale,i) => {
return (
<TabPane tab={locale} key={i}>
<Form onSubmit={this.onSubmitIntro}>
<FormItem {...formItemLayout}>
{getFieldDecorator(`name[${locale}]`, {
initialValue: name[locale]
})(
<Input addonBefore={<Icon type="edit" />} placeholder="应用名称" />
)}
</FormItem>
<FormItem {...formItemLayout} > <FormItem {...formItemLayout} label="游戏类别">
{getFieldDecorator(`description[${locale}]`, { {getFieldDecorator('category', {
initialValue: description[locale] initialValue: category
})( })(
<Input type="textarea" placeholder="应用介绍" autosize={{ minRows: 2}}/> <RadioGroup>
)} {defCategory.map((c, i) => {
</FormItem> return <RadioButton value={c} key={i}>{c}</RadioButton>
<Card title="开发者" extra={<a onClick={ () => this.onAddField({locale, field:'developers', data: { url:'', name: ''}})}>Add </a>}>
{developers[locale] && developers[locale].length > 0 && developers[locale].map((developer,index) => {
return (
<Form key={index}>
<FormItem {...formItemLayout}>
<Row gutter={24}>
<Col span={10}>
{getFieldDecorator(`developers[${locale}][${index}]["name"]`, {
initialValue: developer["name"]
})(
<Input addonBefore={<Icon type="user" />} placeholder="name" />
)}
</Col>
<Col span={10}>
{getFieldDecorator(`developers[${locale}][${index}]["url"]`, {
initialValue: developer["url"]
})(
<Input addonBefore={<Icon type="link" />} placeholder="url" />
)}
</Col>
<Col span={4}>
<a onClick={() => this.onDeleteField({locale, index, field: 'developers'})}>Delete</a>
</Col>
</Row>
</FormItem>
</Form>
)
})}
</Card>
<Card title="发行者" extra={<a onClick={ () => this.onAddField({locale, field:'publishers', data: { url:'', name: ''}})}>Add </a>}>
{publishers[locale] && publishers[locale].length > 0 && publishers[locale].map((publisher,index) => {
return (
<Form key={index}>
<FormItem {...formItemLayout}>
<Row gutter={24}>
<Col span={10}>
{getFieldDecorator(`publishers[${locale}][${index}]["name"]`, {
initialValue: publisher["name"]
})(
<Input addonBefore={<Icon type="user" />} placeholder="name" />
)}
</Col>
<Col span={10}>
{getFieldDecorator(`publishers[${locale}][${index}]["url"]`, {
initialValue: publisher["url"]
})(
<Input addonBefore={<Icon type="link" />} placeholder="url" />
)}
</Col>
<Col span={4}>
<a onClick={() => this.onDeleteField({locale, index, field: 'publishers'})}>Delete</a>
</Col>
</Row>
</FormItem>
</Form>
)
})} })}
</Card> </RadioGroup>
)}
<Card title="新闻" extra={<a onClick={ () => this.onAddField({locale, field:'news', data: { url:'', title: '', text: ""}})}>Add </a>}> </FormItem>
{news[locale] && news[locale].length > 0 && news[locale].map((item,index) => {
<FormItem
return ( {...formItemLayout}
<Form key={index}> help="以 http:// 或 https:// 开头,没有可留空">
<FormItem {...formItemLayout} > {getFieldDecorator('homepage', {
{getFieldDecorator(`news[${locale}][${index}]["url"]`, { initialValue: homepage
initialValue: item["url"] })(
})( <Input addonBefore={<Icon type="home"/>} placeholder="网站"/>
<Input prefix={<Icon type="link" />} placeholder="url" /> )}
)} </FormItem>
{getFieldDecorator(`news[${locale}][${index}]["title"]`, {
initialValue: item["title"] <FormItem
})( {...formItemLayout}
<Input prefix={<Icon type="edit" />} placeholder="title" /> help="游戏类应用通常与 ID 相同,其他类型的应用留空">
)} {getFieldDecorator('conference', {
initialValue: conference
{getFieldDecorator(`news[${locale}][${index}]["text"]`, { })(
initialValue: item["text"] <Input addonBefore={<Icon type="message"/>} placeholder="聊天室"/>
})( )}
<Input type="textarea" prefix={<Icon type="edit" />} placeholder="text" /> </FormItem>
)}
<a onClick={() => this.onDeleteField({locale, index, field: 'news'})}>Delete</a> <FormItem
</FormItem> {...formItemLayout}
</Form> help="JSON string[],不会写请联系 zh99998@gmail.com"
) >
{getFieldDecorator('tags', {
initialValue: tags
})(
<Select tags style={{width: '100%'}} placeholder="标签">
</Select>
)}
</FormItem>
<FormItem {...formItemLayout}>
{getFieldDecorator('locales', {
initialValue: locales
})(
<Select
tags
style={{width: '100%'}}
placeholder="游戏支持的语言">
{defLocales.map((locale, i) => {
return <Select.Option key={i} value={locale}>{locale}</Select.Option>
})} })}
</Card> </Select>
)}
</FormItem>
<FormItem {...formItemLayout} > <FormItem {...formItemLayout} >
<div className={styles.wrapSubmit}> <div className={styles.wrapSubmit}>
<Button type="primary" htmlType="submit" size="large">提交</Button> <Button type="primary" htmlType="submit" size="large">提交</Button>
</div> </div>
</FormItem> </FormItem>
</Form> </Form>
</TabPane> </div>
) </TabPane>
})}
</Tabs>
</div>
</TabPane>
<TabPane tab={<span><Icon type="save" />应用管理</span>} key="3">
<div className={styles.form}>
<Tabs type="card" className="app-detail-nav">
{defPlatform.map((platform,i) =>
<TabPane tab={platform} key={i}>
<Form onSubmit={this.onSubmitManage}>
<FormItem {...formItemLayout} help="version">
{getFieldDecorator(`version[${platform}]`, {
initialValue: version[platform]
})(
<Input addonBefore={<Icon type="info-circle-o" />} placeholder="版本号" />
)}
</FormItem>
<FormItem {...formItemLayout} help="actions">
{getFieldDecorator(`actions[${platform}]`, {
initialValue: actions[platform] && JSON.stringify(actions[platform], null, '\t')
})(
<Input type="textarea" addonBefore={<Icon type="info-circle-o" />} placeholder="actions" autosize/>
)}
</FormItem>
<FormItem {...formItemLayout} help="dependencies">
{getFieldDecorator(`dependencies[${platform}]`, {
initialValue: dependencies[platform]
})(
<Select tags style={{ width: '100%' }} placeholder="dependencies">
</Select>
)}
</FormItem>
<FormItem {...formItemLayout} help="references">
{getFieldDecorator(`references[${platform}]`, {
initialValue: references[platform]
})(
<Select tags style={{ width: '100%' }} placeholder="references">
</Select>
)}
</FormItem>
<FormItem {...formItemLayout} >
<div className={styles.wrapSubmit}>
<Button type="primary" htmlType="submit" size="large">提交</Button>
</div>
</FormItem>
</Form>
</TabPane>
)}
</Tabs>
</div>
</TabPane>
<TabPane tab={<span><Icon type="save" />应用上传</span>} key="4"> <TabPane tab={<span><Icon type="solution"/>应用介绍</span>} key="2">
<div className={styles.form}> <div className={styles.form}>
<Tabs type="editable-card" className="app-detail-nav" onEdit={this.onEdit}> <Tabs type="card" className="app-detail-nav">
{packages && packages.map((pack,i) => { {defLocales.map((locale, i) => {
if(pack) {
return (
<TabPane tab={pack.name || "New"} key={i} closable={false}>
<Form onSubmit={this.onSubmitUpload}>
<FormItem {...formItemLayout} help="id"> return (
{getFieldDecorator(`upload["packages"][${i}]["id"]`, { <TabPane tab={locale} key={i}>
initialValue: pack["id"] <Form onSubmit={this.onSubmitIntro}>
})( <FormItem {...formItemLayout}>
<Input addonBefore={<Icon type="info-circle-o" />} placeholder="id" disabled /> {getFieldDecorator(`name[${locale}]`, {
)} initialValue: name[locale]
</FormItem>
<FormItem {...formItemLayout} help="name">
{getFieldDecorator(`upload["packages"][${i}]["name"]`, {
initialValue: pack["name"]
})( })(
<Input addonBefore={<Icon type="info-circle-o" />} placeholder="name" /> <Input addonBefore={<Icon type="edit"/>} placeholder="应用名称"/>
)} )}
</FormItem> </FormItem>
<FormItem {...formItemLayout} help="version"> <FormItem {...formItemLayout} >
{getFieldDecorator(`upload["packages"][${i}]["version"]`, { {getFieldDecorator(`description[${locale}]`, {
initialValue: pack["version"] initialValue: description[locale]
})( })(
<Input addonBefore={<Icon type="info-circle-o" />} placeholder="版本号" /> <Input type="textarea" placeholder="应用介绍" autosize={{minRows: 2}}/>
)} )}
</FormItem> </FormItem>
<FormItem {...formItemLayout} help="platforms"> <Card title="开发者" extra={<a onClick={ () => this.onAddField({
{getFieldDecorator(`upload["packages"][${i}]["platforms"]`, { locale,
initialValue: pack["platforms"] field: 'developers',
})( data: {url: '', name: ''}
<Select multiple style={{ width: '100%' }} placeholder="platforms"> })}>Add </a>}>
{defPlatform.map((_platform,i) => { {developers[locale] && developers[locale].length > 0 && developers[locale].map((developer, index) => {
return <Select.Option key={i} value={_platform}>{_platform}</Select.Option> return (
})} <Form key={index}>
</Select> <FormItem {...formItemLayout}>
)} <Row gutter={24}>
</FormItem> <Col span={10}>
{getFieldDecorator(`developers[${locale}][${index}]["name"]`, {
<FormItem {...formItemLayout} help="locales"> initialValue: developer["name"]
{getFieldDecorator(`upload["packages"][${i}]["locales"]`, { })(
initialValue: pack["locales"] <Input addonBefore={<Icon type="user"/>} placeholder="name"/>
})( )}
<Select multiple style={{ width: '100%' }} placeholder="locales"> </Col>
{defLocales.map((_locales,i) => { <Col span={10}>
return <Select.Option key={i} value={_locales}>{_locales}</Select.Option> {getFieldDecorator(`developers[${locale}][${index}]["url"]`, {
})} initialValue: developer["url"]
</Select> })(
)} <Input addonBefore={<Icon type="link"/>} placeholder="url"/>
</FormItem> )}
</Col>
<Col span={4}>
<a onClick={() => this.onDeleteField({
locale,
index,
field: 'developers'
})}>Delete</a>
</Col>
</Row>
</FormItem>
</Form>
)
})}
</Card>
<Card title="发行者" extra={<a onClick={ () => this.onAddField({
locale,
field: 'publishers',
data: {url: '', name: ''}
})}>Add </a>}>
{publishers[locale] && publishers[locale].length > 0 && publishers[locale].map((publisher, index) => {
return (
<Form key={index}>
<FormItem {...formItemLayout}>
<Row gutter={24}>
<Col span={10}>
{getFieldDecorator(`publishers[${locale}][${index}]["name"]`, {
initialValue: publisher["name"]
})(
<Input addonBefore={<Icon type="user"/>} placeholder="name"/>
)}
</Col>
<Col span={10}>
{getFieldDecorator(`publishers[${locale}][${index}]["url"]`, {
initialValue: publisher["url"]
})(
<Input addonBefore={<Icon type="link"/>} placeholder="url"/>
)}
</Col>
<Col span={4}>
<a onClick={() => this.onDeleteField({
locale,
index,
field: 'publishers'
})}>Delete</a>
</Col>
</Row>
</FormItem>
</Form>
)
})}
</Card>
<Card title="新闻" extra={<a onClick={ () => this.onAddField({
locale,
field: 'news',
data: {url: '', title: '', text: ""}
})}>Add </a>}>
{news[locale] && news[locale].length > 0 && news[locale].map((item, index) => {
return (
<Form key={index}>
<FormItem {...formItemLayout} >
{getFieldDecorator(`news[${locale}][${index}]["url"]`, {
initialValue: item["url"]
})(
<Input prefix={<Icon type="link"/>} placeholder="url"/>
)}
{getFieldDecorator(`news[${locale}][${index}]["title"]`, {
initialValue: item["title"]
})(
<Input prefix={<Icon type="edit"/>} placeholder="title"/>
)}
<FormItem {...formItemLayout}> {getFieldDecorator(`news[${locale}][${index}]["text"]`, {
{getFieldDecorator(`upload["packages"][${i}]["upload"]`, { initialValue: item["text"]
})( })(
<Dragger <Input type="textarea" prefix={<Icon type="edit"/>} placeholder="text"/>
{...uploadProps} )}
action={`${config.apiRoot}/upload/packages/${pack["id"]}`} <a onClick={() => this.onDeleteField({locale, index, field: 'news'})}>Delete</a>
disabled={pack.isNew}> </FormItem>
<p className="ant-upload-drag-icon"> </Form>
<Icon type="inbox" /> )
</p> })}
<p className="ant-upload-text">Click or drag file to this area to upload</p> </Card>
<p className="ant-upload-hint">Support for a single or bulk upload. Strictly prohibit from uploading company data or other band files</p>
</Dragger>
)}
</FormItem>
<FormItem {...formItemLayout} > <FormItem {...formItemLayout} >
<div className={styles.wrapSubmit}> <div className={styles.wrapSubmit}>
<Button type="primary" htmlType="submit" size="large">提交</Button> <Button type="primary" htmlType="submit" size="large">提交</Button>
</div> </div>
</FormItem> </FormItem>
</Form> </Form>
</TabPane> </TabPane>
) )
} else { })}
return (
<TabPane tab={"!"} key={i} closable={true}> </Tabs>
<div>好像出了什么问题, 请联系xxxxxx</div> </div>
</TabPane> </TabPane>
)
}
})} <TabPane tab={<span><Icon type="save"/>应用管理</span>} key="3">
</Tabs> <div className={styles.form}>
</div> <Tabs type="card" className="app-detail-nav">
</TabPane> {defPlatform.map((platform, i) =>
</Tabs> <TabPane tab={platform} key={i}>
<Form onSubmit={this.onSubmitManage}>
<FormItem {...formItemLayout} help="version">
{getFieldDecorator(`version[${platform}]`, {
initialValue: version[platform]
})(
<Input addonBefore={<Icon type="info-circle-o"/>} placeholder="版本号"/>
)}
</FormItem>
<FormItem {...formItemLayout} help="actions">
{getFieldDecorator(`actions[${platform}]`, {
initialValue: actions[platform] && JSON.stringify(actions[platform], null, '\t')
})(
<Input type="textarea" addonBefore={<Icon type="info-circle-o"/>} placeholder="actions"
autosize/>
)}
</FormItem>
<FormItem {...formItemLayout} help="dependencies">
{getFieldDecorator(`dependencies[${platform}]`, {
initialValue: dependencies[platform]
})(
<Select tags style={{width: '100%'}} placeholder="dependencies">
</Select>
)}
</FormItem>
<FormItem {...formItemLayout} help="references">
{getFieldDecorator(`references[${platform}]`, {
initialValue: references[platform]
})(
<Select tags style={{width: '100%'}} placeholder="references">
</Select>
)}
</FormItem>
<FormItem {...formItemLayout} >
<div className={styles.wrapSubmit}>
<Button type="primary" htmlType="submit" size="large">提交</Button>
</div>
</FormItem>
</Form>
</TabPane>
)}
</Tabs>
</div>
</TabPane>
<TabPane tab={<span><Icon type="save"/>应用上传</span>} key="4">
<div className={styles.form}>
<Tabs type="editable-card" className="app-detail-nav" onEdit={this.onEdit}>
{packages && packages.map((pack, i) => {
if (pack) {
return (
<TabPane tab={pack.name || "New"} key={i} closable={packages.length > 1}>
<Form onSubmit={e => this.onSubmitUpload(e, pack)}>
<FormItem {...formItemLayout} help="id">
{getFieldDecorator(`upload["packages"][${i}]["id"]`, {
initialValue: pack["id"]
})(
<Input addonBefore={<Icon type="info-circle-o"/>} placeholder="id" disabled/>
)}
</FormItem>
<FormItem {...formItemLayout} help="name">
{getFieldDecorator(`upload["packages"][${i}]["name"]`, {
initialValue: pack["name"]
})(
<Input addonBefore={<Icon type="info-circle-o"/>} placeholder="name"/>
)}
</FormItem>
<FormItem {...formItemLayout} help="version">
{getFieldDecorator(`upload["packages"][${i}]["version"]`, {
initialValue: pack["version"]
})(
<Input addonBefore={<Icon type="info-circle-o"/>} placeholder="版本号"/>
)}
</FormItem>
<FormItem {...formItemLayout} help="platforms">
{getFieldDecorator(`upload["packages"][${i}]["platforms"]`, {
initialValue: pack["platforms"]
})(
<Select multiple style={{width: '100%'}} placeholder="platforms">
{defPlatform.map((_platform, i) => {
return <Select.Option key={i} value={_platform}>{_platform}</Select.Option>
})}
</Select>
)}
</FormItem>
<FormItem {...formItemLayout} help="locales">
{getFieldDecorator(`upload["packages"][${i}]["locales"]`, {
initialValue: pack["locales"]
})(
<Select multiple style={{width: '100%'}} placeholder="locales">
{defLocales.map((_locales, i) => {
return <Select.Option key={i} value={_locales}>{_locales}</Select.Option>
})}
</Select>
)}
</FormItem>
<FormItem {...formItemLayout}>
{getFieldDecorator(`upload["packages"][${i}]["upload"]`, {})(
<Tabs defaultActiveKey="1" size="small">
<TabPane tab="url上传" key="1">
{getFieldDecorator(`upload["packages"][${i}]["url"]`, {
// initialValue: pack["url"]
})(
<div>
<Input addonBefore={<Icon type="uplaad"/>} placeholder="url"/>
请确认输入的链接真实有效~
</div>
)}
</TabPane>
<TabPane tab="直接上传" key="2">
<Dragger
{...uploadProps}
action={`${config.apiRoot}/upload/packages/${pack["id"]}`}
disabled={pack.isNew}>
<p className="ant-upload-drag-icon">
<Icon type="inbox"/>
</p>
<p className="ant-upload-text">Click or drag file to this area to upload</p>
<p className="ant-upload-hint">Support for a single or bulk upload. Strictly
prohibit
from uploading company data or other band files</p>
</Dragger>
</TabPane>
</Tabs>
)}
</FormItem>
<FormItem {...formItemLayout} >
<div className={styles.wrapSubmit}>
<Button type="primary" htmlType="submit" size="large">提交</Button>
</div>
</FormItem>
</Form>
</TabPane>
)
} else {
return (
<TabPane tab={"!"} key={i} closable={true}>
<div>好像出了什么问题, 请联系xxxxxx</div>
</TabPane>
)
}
})}
</Tabs>
</div>
</TabPane>
</Tabs>
</Spin>
); );
} }
} }
function mapStateToProps(state, props) { function mapStateToProps(state, props) {
const {params: { id }} = props const {params: {id}} = props
const { const {
Apps: { apps } Apps: {apps},
loading
} = state } = state
const App = apps[id] || {} const App = apps[id] || {}
return { return {
loading,
App App
}; };
} }
......
:global { :global {
.app-detail-nav{
} .ant-upload {
.ant-card { display: flex !important;
margin: 2vh 0; justify-content: center;
} align-items:center;
.app-detail-nav .ant-tabs-nav-scroll { padding: 0 !important;
display: flex; }
justify-content: center;
} .ant-upload-text {
.ant-upload-select-picture-card i { margin-top: 0 !important;
font-size: 28px; }
color: #999;
} .ant-card {
margin: 2vh 0;
.ant-upload-select-picture-card .ant-upload-text { }
margin-top: 8px; .app-detail-nav .ant-tabs-nav-scroll {
font-size: 12px; display: flex;
color: #666; justify-content: center;
} }
} .ant-upload-select-picture-card i {
font-size: 28px;
.wrapSubmit{ color: #999;
display: flex; }
justify-content: center;
} .ant-upload-select-picture-card .ant-upload-text {
margin-top: 8px;
.form { font-size: 12px;
align-content: center; color: #666;
padding: 0 5vw; }
display: flex; }
justify-content: center;
} .wrapSubmit{
\ No newline at end of file display: flex;
justify-content: center;
}
.form {
align-content: center;
padding: 0 5vw;
display: flex;
justify-content: center;
}
import React from 'react'; import React from 'react';
import { connect } from 'dva'; import { connect } from 'dva';
import styles from './Entry.less';
import Nav from '../components/Common/Nav' import Nav from '../components/Common/Nav'
import { Router, Route, browserHistory } from 'dva/router';
import {Layout} from 'antd' import {Layout} from 'antd'
function Entry({ children, collapsed, mode, dispatch }) { function Entry({ children}) {
const NavProps = {
collapsed,
mode,
dispatch
}
return ( return (
<Layout style={{ flexDirection: 'row', minHeight: '100%'}}> <Layout style={{ flexDirection: 'row', minHeight: '100%'}}>
<Nav {...NavProps}/> <Nav />
<Layout style={{ minHeight: '400px'}}> <Layout style={{ minHeight: '400px'}}>
{children} {children}
</Layout> </Layout>
...@@ -26,13 +17,7 @@ function Entry({ children, collapsed, mode, dispatch }) { ...@@ -26,13 +17,7 @@ function Entry({ children, collapsed, mode, dispatch }) {
} }
function mapStateToProps(state) { function mapStateToProps(state) {
const { return {}
Common: {collapsed, mode}
} = state
return {
collapsed,
mode
};
} }
export default connect(mapStateToProps)(Entry); export default connect(mapStateToProps)(Entry);
import fetch from 'dva/fetch'; import fetch from 'dva/fetch';
import config from '../config' import config from '../config';
function parseJSON(response) { function parseJSON(response) {
return response.json(); return response.json();
} }
function checkStatus(response) { async function checkStatus(response) {
if (response.status >= 200 && response.status < 300) { if (response.status >= 200 && response.status < 300) {
return response; return response;
} }
const error = new Error(response.statusText); let message;
try {
message = (await response.json()).message;
} catch (error) {
message = response.statusText;
}
const error = new Error(message);
error.response = response; error.response = response;
throw error; throw error;
} }
...@@ -22,17 +29,20 @@ function checkStatus(response) { ...@@ -22,17 +29,20 @@ function checkStatus(response) {
* @param {object} [options] The options we want to pass to "fetch" * @param {object} [options] The options we want to pass to "fetch"
* @return {object} An object containing either "data" or "err" * @return {object} An object containing either "data" or "err"
*/ */
export default function request(url, options) { export default function request(relativeUrl, options) {
url = `${config.apiRoot}${url}` const url = `${config.apiRoot}${relativeUrl}`;
if(options && !options.headers && (options.method == 'POST' || options.method == 'PATCH')) { if (options && !options.headers) {
options.headers = { Object.assign(options, {
"content-type": "application/json" headers: {
} 'content-type': 'application/json',
},
});
} }
console.log(options);
return fetch(url, options) return fetch(url, options)
.then(checkStatus) .then(checkStatus)
.then(parseJSON) .then(parseJSON)
.then(data => ({ data })) .then(data => ({data}));
.catch(err => ({ err })); // .catch(err => ({ err }));
} };
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment