diff --git a/.eslintignore b/.eslintignore index 43ab7824efa0352bbcbffde924c60fb1d2634518..c1fcbb8a79c1eb2990b138469a6d86f8e02eefda 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,3 @@ -/functions/mock/** +/lambda/mock/** /scripts -/config \ No newline at end of file +/config diff --git a/.eslintrc.js b/.eslintrc.js index 10309cef189855ac5cc6c46feabf83e56731e2f6..aeeca68fee6a891c9a1719140228cc0ef8d44598 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -34,6 +34,6 @@ module.exports = { 'linebreak-style': 0, }, settings: { - polyfills: ['fetch', 'promises', 'url'], + polyfills: ['fetch', 'promises', 'url', 'object-assign'], }, }; diff --git a/.firebaserc b/.firebaserc deleted file mode 100644 index e3a9a50c8a53831595f67ab41862f94d8f050bd0..0000000000000000000000000000000000000000 --- a/.firebaserc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "projects": { - "default": "antd-pro" - } -} diff --git a/.gitignore b/.gitignore index 2859215803d95b14b51d6618bf9cc99587b99aa1..253591b5200c5227e85ef7fa1ea33a5279a4deaa 100644 --- a/.gitignore +++ b/.gitignore @@ -25,8 +25,8 @@ package-lock.json # visual studio code .history *.log - -functions/mock +functions/* +lambda/mock/index.js .temp/** # umi diff --git a/README.md b/README.md index ce0725dfd5b671fde4dcc894108b4f8a997fe027..c6da6474c5ce12b04bd107d4eb5b3c74dd804b6d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -English | [简体中文](./README.zh-CN.md) | [Русский](./README.ru-RU.md) +English | [简体中文](./README.zh-CN.md) | [Русский](./README.ru-RU.md) | [Türkçe](./README.tr-TR.md)

Ant Design Pro

@@ -12,7 +12,7 @@ An out-of-box UI solution for enterprise applications as a React boilerplate. [![DevDependencies](https://img.shields.io/david/dev/ant-design/ant-design-pro.svg)](https://david-dm.org/ant-design/ant-design-pro?type=dev) [![Gitter](https://img.shields.io/gitter/room/ant-design/pro-english.svg?style=flat-square&logoWidth=20&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjEyMzUiIGhlaWdodD0iNjUwIiB2aWV3Qm94PSIwIDAgNzQxMCAzOTAwIj4NCjxyZWN0IHdpZHRoPSI3NDEwIiBoZWlnaHQ9IjM5MDAiIGZpbGw9IiNiMjIyMzQiLz4NCjxwYXRoIGQ9Ik0wLDQ1MEg3NDEwbTAsNjAwSDBtMCw2MDBINzQxMG0wLDYwMEgwbTAsNjAwSDc0MTBtMCw2MDBIMCIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjMwMCIvPg0KPHJlY3Qgd2lkdGg9IjI5NjQiIGhlaWdodD0iMjEwMCIgZmlsbD0iIzNjM2I2ZSIvPg0KPGcgZmlsbD0iI2ZmZiI%2BDQo8ZyBpZD0iczE4Ij4NCjxnIGlkPSJzOSI%2BDQo8ZyBpZD0iczUiPg0KPGcgaWQ9InM0Ij4NCjxwYXRoIGlkPSJzIiBkPSJNMjQ3LDkwIDMxNy41MzQyMzAsMzA3LjA4MjAzOSAxMzIuODczMjE4LDE3Mi45MTc5NjFIMzYxLjEyNjc4MkwxNzYuNDY1NzcwLDMwNy4wODIwMzl6Ii8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB5PSI0MjAiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHk9Ijg0MCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgeT0iMTI2MCIvPg0KPC9nPg0KPHVzZSB4bGluazpocmVmPSIjcyIgeT0iMTY4MCIvPg0KPC9nPg0KPHVzZSB4bGluazpocmVmPSIjczQiIHg9IjI0NyIgeT0iMjEwIi8%2BDQo8L2c%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzOSIgeD0iNDk0Ii8%2BDQo8L2c%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzMTgiIHg9Ijk4OCIvPg0KPHVzZSB4bGluazpocmVmPSIjczkiIHg9IjE5NzYiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3M1IiB4PSIyNDcwIi8%2BDQo8L2c%2BDQo8L3N2Zz4%3D)](https://gitter.im/ant-design/pro-english?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Join the chat at https://gitter.im/ant-design/ant-design-pro](https://img.shields.io/gitter/room/ant-design/ant-design-pro.svg?style=flat-square&logoWidth=20&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjkwMCIgaGVpZ2h0PSI2MDAiIHZpZXdCb3g9IjAgMCAzMCAyMCI%2BDQo8ZGVmcz4NCjxwYXRoIGlkPSJzIiBkPSJNMCwtMSAwLjU4Nzc4NSwwLjgwOTAxNyAtMC45NTEwNTcsLTAuMzA5MDE3SDAuOTUxMDU3TC0wLjU4Nzc4NSwwLjgwOTAxN3oiIGZpbGw9IiNmZmRlMDAiLz4NCjwvZGVmcz4NCjxyZWN0IHdpZHRoPSIzMCIgaGVpZ2h0PSIyMCIgZmlsbD0iI2RlMjkxMCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNSw1KSBzY2FsZSgzKSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsMikgcm90YXRlKDIzLjAzNjI0MykiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEyLDQpIHJvdGF0ZSg0NS44Njk4OTgpIi8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMiw3KSByb3RhdGUoNjkuOTQ1Mzk2KSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsOSkgcm90YXRlKDIwLjY1OTgwOCkiLz4NCjwvc3ZnPg%3D%3D)](https://gitter.im/ant-design/ant-design-pro?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) - +[![Netlify Status](https://api.netlify.com/api/v1/badges/b68e9850-a529-4364-9d3b-d70aade560f9/deploy-status)](https://app.netlify.com/sites/ant-design-pro/deploys) ![](https://user-images.githubusercontent.com/8186664/44953195-581e3d80-aec4-11e8-8dcb-54b9db38ec11.png) diff --git a/README.ru-RU.md b/README.ru-RU.md index 22d16c9ac83c9b8f56dbc9f409753ff589b7c00c..f820dfba2343571ac0803274109b2d989845e727 100644 --- a/README.ru-RU.md +++ b/README.ru-RU.md @@ -1,4 +1,4 @@ -[English](./README.md) | [简体中文](./README.zh-CN.md) | Русский +[English](./README.md) | [简体中文](./README.zh-CN.md) | Русский | [Türkçe](./README.tr-TR.md)

Ant Design Pro

@@ -12,7 +12,7 @@ UI-решение "из коробки" для корпоративных при [![DevDependencies](https://img.shields.io/david/dev/ant-design/ant-design-pro.svg)](https://david-dm.org/ant-design/ant-design-pro?type=dev) [![Gitter](https://img.shields.io/gitter/room/ant-design/pro-english.svg?style=flat-square&logoWidth=20&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjEyMzUiIGhlaWdodD0iNjUwIiB2aWV3Qm94PSIwIDAgNzQxMCAzOTAwIj4NCjxyZWN0IHdpZHRoPSI3NDEwIiBoZWlnaHQ9IjM5MDAiIGZpbGw9IiNiMjIyMzQiLz4NCjxwYXRoIGQ9Ik0wLDQ1MEg3NDEwbTAsNjAwSDBtMCw2MDBINzQxMG0wLDYwMEgwbTAsNjAwSDc0MTBtMCw2MDBIMCIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjMwMCIvPg0KPHJlY3Qgd2lkdGg9IjI5NjQiIGhlaWdodD0iMjEwMCIgZmlsbD0iIzNjM2I2ZSIvPg0KPGcgZmlsbD0iI2ZmZiI%2BDQo8ZyBpZD0iczE4Ij4NCjxnIGlkPSJzOSI%2BDQo8ZyBpZD0iczUiPg0KPGcgaWQ9InM0Ij4NCjxwYXRoIGlkPSJzIiBkPSJNMjQ3LDkwIDMxNy41MzQyMzAsMzA3LjA4MjAzOSAxMzIuODczMjE4LDE3Mi45MTc5NjFIMzYxLjEyNjc4MkwxNzYuNDY1NzcwLDMwNy4wODIwMzl6Ii8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB5PSI0MjAiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHk9Ijg0MCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgeT0iMTI2MCIvPg0KPC9nPg0KPHVzZSB4bGluazpocmVmPSIjcyIgeT0iMTY4MCIvPg0KPC9nPg0KPHVzZSB4bGluazpocmVmPSIjczQiIHg9IjI0NyIgeT0iMjEwIi8%2BDQo8L2c%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzOSIgeD0iNDk0Ii8%2BDQo8L2c%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzMTgiIHg9Ijk4OCIvPg0KPHVzZSB4bGluazpocmVmPSIjczkiIHg9IjE5NzYiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3M1IiB4PSIyNDcwIi8%2BDQo8L2c%2BDQo8L3N2Zz4%3D)](https://gitter.im/ant-design/pro-english?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Join the chat at https://gitter.im/ant-design/ant-design-pro](https://img.shields.io/gitter/room/ant-design/ant-design-pro.svg?style=flat-square&logoWidth=20&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjkwMCIgaGVpZ2h0PSI2MDAiIHZpZXdCb3g9IjAgMCAzMCAyMCI%2BDQo8ZGVmcz4NCjxwYXRoIGlkPSJzIiBkPSJNMCwtMSAwLjU4Nzc4NSwwLjgwOTAxNyAtMC45NTEwNTcsLTAuMzA5MDE3SDAuOTUxMDU3TC0wLjU4Nzc4NSwwLjgwOTAxN3oiIGZpbGw9IiNmZmRlMDAiLz4NCjwvZGVmcz4NCjxyZWN0IHdpZHRoPSIzMCIgaGVpZ2h0PSIyMCIgZmlsbD0iI2RlMjkxMCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNSw1KSBzY2FsZSgzKSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsMikgcm90YXRlKDIzLjAzNjI0MykiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEyLDQpIHJvdGF0ZSg0NS44Njk4OTgpIi8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMiw3KSByb3RhdGUoNjkuOTQ1Mzk2KSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsOSkgcm90YXRlKDIwLjY1OTgwOCkiLz4NCjwvc3ZnPg%3D%3D)](https://gitter.im/ant-design/ant-design-pro?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) - +[![Netlify Status](https://api.netlify.com/api/v1/badges/b68e9850-a529-4364-9d3b-d70aade560f9/deploy-status)](https://app.netlify.com/sites/ant-design-pro/deploys) ![](https://user-images.githubusercontent.com/8186664/44953195-581e3d80-aec4-11e8-8dcb-54b9db38ec11.png) diff --git a/README.tr-TR.md b/README.tr-TR.md new file mode 100644 index 0000000000000000000000000000000000000000..8470cb79a41153736603c6bb92c63ebbbfdc2187 --- /dev/null +++ b/README.tr-TR.md @@ -0,0 +1,130 @@ +[English](./README.md) | [简体中文](./README.zh-CN.md) | [Русский](./README.ru-RU.md) | Türkçe + +

Ant Design Pro

+ +
+ +React ile kurumsal uygulamalar için taslak olarak geliştirilmiş kullanıma hazır bir UI çözümü. + +[![CircleCI Status](https://circleci.com/gh/ant-design/ant-design-pro.svg?style=svg)](https://circleci.com/gh/ant-design/ant-design-pro/) +[![Build status](https://ci.appveyor.com/api/projects/status/67fxu2by3ibvqtat/branch/master?svg=true)](https://ci.appveyor.com/project/afc163/ant-design-pro/branch/master) +[![Dependencies](https://img.shields.io/david/ant-design/ant-design-pro.svg)](https://david-dm.org/ant-design/ant-design-pro) +[![DevDependencies](https://img.shields.io/david/dev/ant-design/ant-design-pro.svg)](https://david-dm.org/ant-design/ant-design-pro?type=dev) +[![Gitter](https://img.shields.io/gitter/room/ant-design/pro-english.svg)](https://gitter.im/ant-design/pro-english?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)(🇺🇸) +[![Gitter](https://img.shields.io/gitter/room/ant-design/ant-design-pro.svg?style=flat-square)](https://gitter.im/ant-design/ant-design-pro?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)(🇨🇳) +[![Netlify Status](https://api.netlify.com/api/v1/badges/b68e9850-a529-4364-9d3b-d70aade560f9/deploy-status)](https://app.netlify.com/sites/ant-design-pro/deploys) +![](https://user-images.githubusercontent.com/8186664/44953195-581e3d80-aec4-11e8-8dcb-54b9db38ec11.png) + +
+ +- Önizleme: http://preview.pro.ant.design +- Anasayfa: http://pro.ant.design +- Dokümantasyon: http://pro.ant.design/docs/getting-started +- ChangeLog: http://pro.ant.design/docs/changelog +- SSS: http://pro.ant.design/docs/faq +- Çinde barındırılan site: http://ant-design-pro.gitee.io + +## 2.0 Versiyonu Şimdi Yayında! 🎉🎉🎉 +[Announcing Ant Design Pro 2.0.0](https://medium.com/ant-design/beautiful-and-powerful-ant-design-pro-2-0-release-51358da5af95) + +## Çeviri Desteği :loudspeaker: + +Çeviriler için yardımınıza ihtiyacımız var: https://github.com/ant-design/ant-design-pro/issues/120 + +## Özellikler + +- :gem: **Zarif Tasarım**: Buradan [Ant Design özellikleri](http://ant.design/) +- :triangular_ruler: **Ortak Şablonlar**: Kurumsal uygulamalar için şablonlar +- :rocket: **Sanatsal gelişim durumu**: Newest development stack of React/umi/dva/antd +- :iphone: **Responsive**: Değişken ekran boyutları için tasarlanmıştır +- :art: **Tema Kullanımı**: Basit ayarlar ile özelleştirilebilir tema +- :globe_with_meridians: **Uluslararası**: Built-in i18n solution +- :gear: **Best Practices**: İyi kod için sağlam iş akışı +- :1234: **Mock Geliştirme**: Model(Mock) geliştirmeler için kolay çözüm +- :white_check_mark: **UI Testi**: Unit ve e2e testleri ile güvenli sürdürülebilirlik + +## Şablonlar + +``` +- Dashboard + - Analitik + - Monitör + - Çalışma alanı +- Form + - Basit Form + - Step Form + - Gelişmiş Form +- List + - Standard Tablo + - Standard Liste + - Kart Liste + - Arama Listesi (Project/Applications/Article) +- Profil + - Basit Profil + - Gelişmiş Profil +- Hesap + - Hesap Yönetimi + - Hesap Ayarları +- Sonuç + - Başarılı + - Hatalı +- Hatalar + - 403 + - 404 + - 500 +- Kullanıcı + - Giriş + - Kayıt + - Kayıt Sonucu +``` + +## Kullanım + +### bash ile kullanım + +```bash +$ git clone https://github.com/ant-design/ant-design-pro.git --depth=1 +$ cd ant-design-pro +$ npm install +$ npm start # visit http://localhost:8000 +``` + +### Docker ile kullanım + +```bash +# preview +$ docker pull chenshuai2144/ant-design-pro +$ docker run -p 80:80 chenshuai2144/ant-design-pro +# open http://localhost + +# dev +$ npm run docker:dev + +# build +$ npm run docker:build + + +# production dev +$ npm run docker-prod:dev + +# production build +$ npm run docker-prod:build +``` + +Daha fazla talimat için [dokümantasyon](http://pro.ant.design/docs/getting-started) sayfasına göz atın. + +## Tarayıcı desteği + +Modern internet tarayıcıları ve IE11. + +| [IE / Edge](http://godban.github.io/browsers-support-badges/)
IE / Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | [Opera](http://godban.github.io/browsers-support-badges/)
Opera | +| --------- | --------- | --------- | --------- | --------- | +| IE11, Edge| son 2 versiyon | son 2 versiyon | son 2 versiyon | son 2 versiyon + +## Destek + +Her türlü desteğinize açığız, bu projeye nasıl katkıda bulunabileceğinize dair bazı örnekler: + +- Günlük işinizde Ant Design Pro kullanın. +- Hataları bildirmek veya soru sormak için [issues](http://github.com/ant-design/ant-design-pro/issues) gönderin. +- kodumuzu geliştirmek için [pull requests](http://github.com/ant-design/ant-design-pro/pulls) gönderin. diff --git a/README.zh-CN.md b/README.zh-CN.md index 6b150506179b433d3dbf5c4ad5ced0c00c86dcb9..b4b3b722c650b12905a652c59076252129a8d897 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -1,4 +1,4 @@ -[English](./README.md) | 简体中文 | [Русский](./README.ru-RU.md) +[English](./README.md) | 简体中文 | [Русский](./README.ru-RU.md) | [Türkçe](./README.tr-TR.md)

Ant Design Pro

@@ -11,7 +11,7 @@ [![Dependencies](https://img.shields.io/david/ant-design/ant-design-pro.svg)](https://david-dm.org/ant-design/ant-design-pro) [![DevDependencies](https://img.shields.io/david/dev/ant-design/ant-design-pro.svg)](https://david-dm.org/ant-design/ant-design-pro?type=dev) [![Join the chat at https://gitter.im/ant-design/ant-design-pro](https://img.shields.io/gitter/room/ant-design/ant-design-pro.svg?style=flat-square&logoWidth=20&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjkwMCIgaGVpZ2h0PSI2MDAiIHZpZXdCb3g9IjAgMCAzMCAyMCI%2BDQo8ZGVmcz4NCjxwYXRoIGlkPSJzIiBkPSJNMCwtMSAwLjU4Nzc4NSwwLjgwOTAxNyAtMC45NTEwNTcsLTAuMzA5MDE3SDAuOTUxMDU3TC0wLjU4Nzc4NSwwLjgwOTAxN3oiIGZpbGw9IiNmZmRlMDAiLz4NCjwvZGVmcz4NCjxyZWN0IHdpZHRoPSIzMCIgaGVpZ2h0PSIyMCIgZmlsbD0iI2RlMjkxMCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNSw1KSBzY2FsZSgzKSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsMikgcm90YXRlKDIzLjAzNjI0MykiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEyLDQpIHJvdGF0ZSg0NS44Njk4OTgpIi8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMiw3KSByb3RhdGUoNjkuOTQ1Mzk2KSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsOSkgcm90YXRlKDIwLjY1OTgwOCkiLz4NCjwvc3ZnPg%3D%3D)](https://gitter.im/ant-design/ant-design-pro?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) - +[![Netlify Status](https://api.netlify.com/api/v1/badges/b68e9850-a529-4364-9d3b-d70aade560f9/deploy-status)](https://app.netlify.com/sites/ant-design-pro/deploys) ![](https://user-images.githubusercontent.com/8186664/44953195-581e3d80-aec4-11e8-8dcb-54b9db38ec11.png) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 9c4c97e1ad91a23e84b499ffdae0eac65a9cb579..2df685a5dd6c44538cf54537cd2ff99ffa7b99ba 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -52,6 +52,10 @@ jobs: displayName: install - script: npm run lint displayName: lint + - script: npm run test:all + env: + PROGRESS: none + displayName: test - script: npm run build env: PROGRESS: none diff --git a/config/config.js b/config/config.js index d0eef764477aebdd9210d0b43a3683859d8e6f7f..9e55fe6442423e483a3f5762aa57652b0e62f696 100644 --- a/config/config.js +++ b/config/config.js @@ -5,7 +5,7 @@ import defaultSettings from '../src/defaultSettings'; import slash from 'slash2'; const { pwa, primaryColor } = defaultSettings; -const { NODE_ENV, APP_TYPE, TEST } = process.env; +const { APP_TYPE, TEST } = process.env; const plugins = [ [ @@ -37,12 +37,12 @@ const plugins = [ importWorkboxFrom: 'local', }, } - : {}, + : false, ...(!TEST && os.platform() === 'darwin' ? { dll: { include: ['dva', 'dva/router', 'dva/saga', 'dva/fetch'], - exclude: ['@babel/runtime'], + exclude: ['@babel/runtime', 'netlify-lambda'], }, hardSource: false, } @@ -91,10 +91,6 @@ export default { theme: { 'primary-color': primaryColor, }, - externals: { - '@antv/data-set': 'DataSet', - bizcharts: 'BizCharts', - }, // proxy: { // '/server/api/': { // target: 'https://preview.pro.ant.design/', diff --git a/config/plugin.config.js b/config/plugin.config.js index b9e842d26a900cceb0880b75c3e5c7489cb0c81f..2273586e6753a24ea561f7ff8764926e3985688a 100644 --- a/config/plugin.config.js +++ b/config/plugin.config.js @@ -4,6 +4,25 @@ import MergeLessPlugin from 'antd-pro-merge-less'; import AntDesignThemePlugin from 'antd-theme-webpack-plugin'; import path from 'path'; +function getModulePackageName(module) { + if (!module.context) return null; + + const nodeModulesPath = path.join(__dirname, '../node_modules/'); + if (module.context.substring(0, nodeModulesPath.length) !== nodeModulesPath) { + return null; + } + + const moduleRelativePath = module.context.substring(nodeModulesPath.length); + const [moduleDirName] = moduleRelativePath.split(path.sep); + let packageName = moduleDirName; + // handle tree shaking + if (packageName.match('^_')) { + // eslint-disable-next-line prefer-destructuring + packageName = packageName.match(/^_(@?[^@]+)/)[1]; + } + return packageName; +} + export default config => { // pro 和 开发环境再添加这个插件 if (process.env.APP_TYPE === 'site' || process.env.NODE_ENV !== 'production') { @@ -30,4 +49,32 @@ export default config => { }, ]); } + // optimize chunks + config.optimization + .runtimeChunk(false) // share the same chunks across different modules + .splitChunks({ + chunks: 'async', + name: 'vendors', + maxInitialRequests: Infinity, + minSize: 0, + cacheGroups: { + vendors: { + test: module => { + const packageName = getModulePackageName(module); + if (packageName) { + return ['bizcharts', '@antv_data-set'].indexOf(packageName) >= 0; + } + return false; + }, + name(module) { + const packageName = getModulePackageName(module); + + if (['bizcharts', '@antv_data-set'].indexOf(packageName) >= 0) { + return 'viz'; // visualization package + } + return 'misc'; + }, + }, + }, + }); }; diff --git a/config/router.config.js b/config/router.config.js index 840fe8334989fc4035947800767869c881018621..e954ced977efea00da8597f484376e345b32caf9 100644 --- a/config/router.config.js +++ b/config/router.config.js @@ -12,6 +12,9 @@ export default [ name: 'register.result', component: './User/RegisterResult', }, + { + component: '404', + }, ], }, // app @@ -19,10 +22,9 @@ export default [ path: '/', component: '../layouts/BasicLayout', Routes: ['src/pages/Authorized'], - authority: ['admin', 'user'], routes: [ // dashboard - { path: '/', redirect: '/dashboard/analysis' }, + { path: '/', redirect: '/dashboard/analysis', authority: ['admin', 'user'] }, { path: '/dashboard', name: 'dashboard', @@ -265,6 +267,29 @@ export default [ }, ], }, + // editor + { + name: 'editor', + icon: 'highlight', + path: '/editor', + routes: [ + { + path: '/editor/flow', + name: 'flow', + component: './Editor/GGEditor/Flow', + }, + { + path: '/editor/mind', + name: 'mind', + component: './Editor/GGEditor/Mind', + }, + { + path: '/editor/koni', + name: 'koni', + component: './Editor/GGEditor/Koni', + }, + ], + }, { component: '404', }, diff --git a/firebase.json b/firebase.json deleted file mode 100644 index a00223d4ddce6ed47ef14af8e3b78f86294c0706..0000000000000000000000000000000000000000 --- a/firebase.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "hosting": { - "public": "dist", - "rewrites": [ - { "source": "/api/**", "function": "api" }, - { - "source": "**", - "destination": "/index.html" - } - ], - "ignore": ["firebase.json", "**/.*", "**/node_modules/**"] - } -} diff --git a/functions/index.js b/functions/index.js deleted file mode 100644 index 609b51ca4df69bf827cac9ba7e600bd6685eec89..0000000000000000000000000000000000000000 --- a/functions/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// [START functionsimport] -const functions = require('firebase-functions'); -const express = require('express'); - -const matchMock = require('./matchMock'); - -const app = express(); - -app.use(matchMock); -exports.api = functions.https.onRequest(app); diff --git a/functions/package.json b/functions/package.json deleted file mode 100644 index fe77db2ab178ceec526d78d077834a401b7970a0..0000000000000000000000000000000000000000 --- a/functions/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "functions", - "description": "Cloud Functions for Firebase", - "scripts": { - "serve": "firebase serve --only functions", - "shell": "firebase functions:shell", - "start": "npm run shell", - "deploy": "npm run mock && firebase deploy --only functions", - "logs": "firebase functions:log", - "mock": "node ../scripts/generateMock.js" - }, - "dependencies": { - "@babel/runtime": "^7.0.0", - "body-parser": "^1.18.3", - "express": "^4.16.4", - "firebase-admin": "^6.4.0", - "firebase-functions": "^2.1.0", - "mockjs": "^1.0.1-beta3", - "moment": "^2.22.2", - "path-to-regexp": "^3.0.0" - }, - "private": true -} diff --git a/jest-puppeteer.config.js b/jest-puppeteer.config.js index 090687a34f3770a7b4617bc7390c19bc0575d26e..21b41e4aaf354b1081863e45321f229f7ffe9416 100644 --- a/jest-puppeteer.config.js +++ b/jest-puppeteer.config.js @@ -6,6 +6,7 @@ module.exports = { '--disable-dev-shm-usage', '--no-first-run', '--no-zygote', + '--no-sandbox', ], }, }; diff --git a/lambda/api.js b/lambda/api.js new file mode 100644 index 0000000000000000000000000000000000000000..e0c147a6a3baa8ee307b69df1a4a2d11ba1072c5 --- /dev/null +++ b/lambda/api.js @@ -0,0 +1,11 @@ +// [START functions import] +const express = require('express'); +const serverLess = require('serverless-http'); + +const matchMock = require('./mock/matchMock'); + +const app = express(); + +app.use(matchMock); + +exports.handler = serverLess(app); diff --git a/functions/matchMock.js b/lambda/mock/matchMock.js similarity index 90% rename from functions/matchMock.js rename to lambda/mock/matchMock.js index 924573a53a6c1cf5b58a45f43487b06b96516929..94027802a6174e0bc0322a402c51d1ec51a53bd7 100644 --- a/functions/matchMock.js +++ b/lambda/mock/matchMock.js @@ -1,7 +1,7 @@ const pathToRegexp = require('path-to-regexp'); const bodyParser = require('body-parser'); -const mockFile = require('./mock/index'); +const mockFile = require('./index'); const BODY_PARSED_METHODS = ['post', 'put', 'patch']; @@ -10,13 +10,14 @@ function parseKey(key) { let method = 'get'; let path = key; if (key.indexOf(' ') > -1) { - const splited = key.split(' '); - method = splited[0].toLowerCase(); - path = splited[1]; // eslint-disable-line + const spliced = key.split(' '); + method = spliced[0].toLowerCase(); + path = spliced[1]; // eslint-disable-line } + const routerBasePath = process.env.NODE_ENV === 'dev' ? `${path}` : `/.netlify/functions${path}`; return { method, - path, + path: routerBasePath, }; } diff --git a/mock/notices.js b/mock/notices.js index e07565dfe603c73b348c908a201d20422da3bf52..505088e0da17ba556961e2d1f3ed1159d561cae2 100644 --- a/mock/notices.js +++ b/mock/notices.js @@ -1,114 +1,101 @@ -const fakeNotices = [ - { - id: '000000001', - avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png', - title: '你收到了 14 份新周报', - datetime: '2017-08-09', - type: 'notification', - }, - { - id: '000000002', - avatar: 'https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png', - title: '你推荐的 曲妮妮 已通过第三轮面试', - datetime: '2017-08-08', - type: 'notification', - }, - { - id: '000000003', - avatar: 'https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png', - title: '这种模板可以区分多种通知类型', - datetime: '2017-08-07', - read: true, - type: 'notification', - }, - { - id: '000000004', - avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png', - title: '左侧图标用于区分不同的类型', - datetime: '2017-08-07', - type: 'notification', - }, - { - id: '000000005', - avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png', - title: '内容不要超过两行字,超出时自动截断', - datetime: '2017-08-07', - type: 'notification', - }, - { - id: '000000006', - avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg', - title: '曲丽丽 评论了你', - description: '描述信息描述信息描述信息', - datetime: '2017-08-07', - type: 'message', - clickClose: true, - }, - { - id: '000000007', - avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg', - title: '朱偏右 回复了你', - description: '这种模板用于提醒谁与你发生了互动,左侧放『谁』的头像', - datetime: '2017-08-07', - type: 'message', - clickClose: true, - }, - { - id: '000000008', - avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg', - title: '标题', - description: '这种模板用于提醒谁与你发生了互动,左侧放『谁』的头像', - datetime: '2017-08-07', - type: 'message', - clickClose: true, - }, - { - id: '000000009', - title: '任务名称', - description: '任务需要在 2017-01-12 20:00 前启动', - extra: '未开始', - status: 'todo', - type: 'event', - }, - { - id: '000000010', - title: '第三方紧急代码变更', - description: '冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务', - extra: '马上到期', - status: 'urgent', - type: 'event', - }, - { - id: '000000011', - title: '信息安全考试', - description: '指派竹尔于 2017-01-09 前完成更新并发布', - extra: '已耗时 8 天', - status: 'doing', - type: 'event', - }, - { - id: '000000012', - title: 'ABCD 版本发布', - description: '冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务', - extra: '进行中', - status: 'processing', - type: 'event', - }, -]; - -const getNotices = (req, res) => { - if (req.query && req.query.type) { - const startFrom = parseInt(req.query.lastItemId, 10) + 1; - const result = fakeNotices - .filter(({ type }) => type === req.query.type) - .map((notice, index) => ({ - ...notice, - id: `0000000${startFrom + index}`, - })); - return res.json(startFrom > 24 ? result.concat(null) : result); - } - return res.json(fakeNotices); -}; +const getNotices = (req, res) => + res.json([ + { + id: '000000001', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png', + title: '你收到了 14 份新周报', + datetime: '2017-08-09', + type: 'notification', + }, + { + id: '000000002', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png', + title: '你推荐的 曲妮妮 已通过第三轮面试', + datetime: '2017-08-08', + type: 'notification', + }, + { + id: '000000003', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png', + title: '这种模板可以区分多种通知类型', + datetime: '2017-08-07', + read: true, + type: 'notification', + }, + { + id: '000000004', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png', + title: '左侧图标用于区分不同的类型', + datetime: '2017-08-07', + type: 'notification', + }, + { + id: '000000005', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png', + title: '内容不要超过两行字,超出时自动截断', + datetime: '2017-08-07', + type: 'notification', + }, + { + id: '000000006', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg', + title: '曲丽丽 评论了你', + description: '描述信息描述信息描述信息', + datetime: '2017-08-07', + type: 'message', + clickClose: true, + }, + { + id: '000000007', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg', + title: '朱偏右 回复了你', + description: '这种模板用于提醒谁与你发生了互动,左侧放『谁』的头像', + datetime: '2017-08-07', + type: 'message', + clickClose: true, + }, + { + id: '000000008', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg', + title: '标题', + description: '这种模板用于提醒谁与你发生了互动,左侧放『谁』的头像', + datetime: '2017-08-07', + type: 'message', + clickClose: true, + }, + { + id: '000000009', + title: '任务名称', + description: '任务需要在 2017-01-12 20:00 前启动', + extra: '未开始', + status: 'todo', + type: 'event', + }, + { + id: '000000010', + title: '第三方紧急代码变更', + description: '冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务', + extra: '马上到期', + status: 'urgent', + type: 'event', + }, + { + id: '000000011', + title: '信息安全考试', + description: '指派竹尔于 2017-01-09 前完成更新并发布', + extra: '已耗时 8 天', + status: 'doing', + type: 'event', + }, + { + id: '000000012', + title: 'ABCD 版本发布', + description: '冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务', + extra: '进行中', + status: 'processing', + type: 'event', + }, + ]); export default { 'GET /api/notices': getNotices, diff --git a/mock/route.js b/mock/route.js index 17a00bce3690803325340419d4be549f88d7993c..d7cc17df189fdb863a8b55dc3342e4e9857efb79 100644 --- a/mock/route.js +++ b/mock/route.js @@ -192,6 +192,25 @@ export default { }, ], }, + { + name: 'editor', + icon: 'highlight', + path: '/editor', + routes: [ + { + path: '/editor/flow', + name: 'flow', + }, + { + path: '/editor/mind', + name: 'mind', + }, + { + path: '/editor/koni', + name: 'koni', + }, + ], + }, ], }, }; diff --git a/netlify.toml b/netlify.toml index 18b22e9d58b17ae991caaa6f96317b1aeac87f93..9d3438c4aff06f5a644d10167b5c7133f5175e45 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,12 +1,15 @@ +[build] + functions = "./functions" + [[redirects]] from = "/api/*" - to = "https://us-central1-antd-pro.cloudfunctions.net/api/api/:splat" + to = "/.netlify/functions/api/:splat" status = 200 force = true [redirects.headers] X-From = "Netlify" X-Api-Key = "some-api-key-string" - + [[redirects]] from = "/*" to = "/index.html" diff --git a/package.json b/package.json index da3053f08f0f40598458373ee47d04be352d59c3..362776f217fd06fd2befbbd9bb1795df855867b1 100644 --- a/package.json +++ b/package.json @@ -1,49 +1,69 @@ { "name": "ant-design-pro", - "version": "2.2.1", - "description": "An out-of-box UI solution for enterprise applications", + "version": "2.3.1", "private": true, + "description": "An out-of-box UI solution for enterprise applications", "scripts": { - "presite": "cd functions && npm install", - "start": "cross-env APP_TYPE=site umi dev", - "start:no-mock": "cross-env MOCK=none umi dev", - "build": "umi build", - "site": "npm run presite && cross-env APP_TYPE=site npm run build && firebase deploy && npm run docker:push", "analyze": "cross-env ANALYZE=1 umi build", - "lint:style": "stylelint 'src/**/*.less' --syntax less", - "lint:prettier": "check-prettier lint", + "build": "umi build && npm run functions:build", + "docker-hub:build": "docker build -f Dockerfile.hub -t ant-design-pro ./", + "docker-prod:build": "docker-compose -f ./docker/docker-compose.yml build", + "docker-prod:dev": "docker-compose -f ./docker/docker-compose.yml up", + "docker:build": "docker-compose -f ./docker/docker-compose.dev.yml build", + "docker:dev": "docker-compose -f ./docker/docker-compose.dev.yml up", + "docker:push": "npm run docker-hub:build && npm run docker:tag && docker push antdesign/ant-design-pro", + "docker:tag": "docker tag ant-design-pro antdesign/ant-design-pro", + "functions:build": "npm run generateMock && netlify-lambda build ./lambda", + "functions:run": "npm run generateMock && cross-env NODE_ENV=dev netlify-lambda serve ./lambda", + "generateMock": "node ./scripts/generateMock", "lint": "eslint --ext .js src mock tests && npm run lint:style && npm run lint:prettier", - "lint:fix": "eslint --fix --ext .js src mock tests && stylelint --fix 'src/**/*.less' --syntax less", "lint-staged": "lint-staged", "lint-staged:js": "eslint --ext .js", - "tslint": "npm run tslint:fix", - "tslint:fix": "tslint --fix 'src/**/*.ts*'", + "lint:fix": "eslint --fix --ext .js src mock tests && stylelint --fix 'src/**/*.less' --syntax less", + "lint:prettier": "check-prettier lint", + "lint:style": "stylelint 'src/**/*.less' --syntax less", + "prettier": "node ./scripts/prettier.js", + "start": "cross-env APP_TYPE=site umi dev", + "start:no-mock": "cross-env MOCK=none umi dev", "test": "umi test", - "test:component": "umi test ./src/components", "test:all": "node ./tests/run-tests.js", - "prettier": "node ./scripts/prettier.js", - "docker:dev": "docker-compose -f ./docker/docker-compose.dev.yml up", - "docker:build": "docker-compose -f ./docker/docker-compose.dev.yml build", - "docker-prod:dev": "docker-compose -f ./docker/docker-compose.yml up", - "docker-prod:build": "docker-compose -f ./docker/docker-compose.yml build", - "docker-hub:build": "docker build -f Dockerfile.hub -t ant-design-pro ./", - "docker:tag": "docker tag ant-design-pro antdesign/ant-design-pro", - "docker:push": "npm run docker-hub:build && npm run docker:tag && docker push antdesign/ant-design-pro" + "test:component": "umi test ./src/components", + "tslint": "npm run tslint:fix", + "tslint:fix": "tslint --fix 'src/**/*.ts*'" + }, + "husky": { + "hooks": { + "pre-commit": "npm run lint-staged" + } + }, + "lint-staged": { + "**/*.less": "stylelint --syntax less", + "**/*.{js,jsx}": "npm run lint-staged:js", + "**/*.{js,ts,tsx,json,jsx,less}": [ + "node ./scripts/lint-prettier.js", + "git add" + ] }, + "browserslist": [ + "> 1%", + "last 2 versions", + "not ie <= 10" + ], "dependencies": { "@antv/data-set": "^0.10.1", - "@babel/runtime": "^7.3.1", "antd": "^3.13.0", "bizcharts": "^3.4.3", "bizcharts-plugin-slider": "^2.1.1-beta.1", "classnames": "^2.2.6", "dva": "^2.4.1", "enquire-js": "^0.2.1", - "hash.js": "^1.1.7", + "express": "^4.16.4", + "gg-editor": "^2.0.2", "lodash": "^4.17.11", "lodash-decorators": "^6.0.1", "memoize-one": "^5.0.0", "moment": "^2.24.0", + "netlify-lambda": "^1.4.3", "numeral": "^2.0.6", "nzh": "^1.0.4", "omit.js": "^1.0.0", @@ -58,10 +78,13 @@ "react-dom": "^16.7.0", "react-fittext": "^1.0.0", "react-media": "^1.9.2", - "react-router-dom": "^4.3.1", + "umi": "^2.4.4", + "umi-plugin-react": "^1.7.2", + "umi-request": "^1.0.5", "umi-plugin-authorize": "^1.0.0" }, "devDependencies": { + "@types/history": "^4.7.2", "@types/react": "^16.8.1", "@types/react-dom": "^16.0.11", "antd-pro-merge-less": "^1.0.0", @@ -71,28 +94,28 @@ "check-prettier": "^1.0.1", "cross-env": "^5.2.0", "cross-port-killer": "^1.0.1", - "enzyme": "3.8.0", + "enzyme": "^3.9.0", "eslint": "^5.13.0", "eslint-config-airbnb": "^17.1.0", - "eslint-config-prettier": "^4.0.0", + "eslint-config-prettier": "^4.1.0", "eslint-plugin-babel": "^5.3.0", "eslint-plugin-compat": "^2.6.3", "eslint-plugin-import": "^2.16.0", - "eslint-plugin-jsx-a11y": "^6.2.0", + "eslint-plugin-jsx-a11y": "^6.2.1", "eslint-plugin-markdown": "^1.0.0", "eslint-plugin-react": "^7.12.4", "gh-pages": "^2.0.1", "husky": "^1.3.1", - "jest-puppeteer": "^3.9.0", + "jest-puppeteer": "^4.1.0", "less": "^3.9.0", "lint-staged": "^8.1.1", "merge-umi-mock-data": "^1.0.4", "mockjs": "^1.0.1-beta3", - "prettier": "1.16.3", + "prettier": "^1.16.4", "slash2": "^2.0.0", "stylelint": "^9.10.1", "stylelint-config-css-modules": "^1.3.0", - "stylelint-config-prettier": "^4.0.0", + "stylelint-config-prettier": "^5.0.0", "stylelint-config-rational-order": "^0.0.4", "stylelint-config-standard": "^18.2.0", "stylelint-declaration-block-no-ignored-properties": "^1.1.0", @@ -100,39 +123,20 @@ "tslint": "^5.12.1", "tslint-config-prettier": "^1.17.0", "tslint-react": "^3.6.0", - "umi": "^2.4.4", "umi-plugin-ga": "^1.1.3", - "umi-plugin-react": "^1.4.2" + "serverless-http": "^1.9.1" }, "optionalDependencies": { "puppeteer": "^1.12.1" }, - "lint-staged": { - "**/*.{js,ts,tsx,json,jsx,less}": [ - "node ./scripts/lint-prettier.js", - "git add" - ], - "**/*.{js,jsx}": "npm run lint-staged:js", - "**/*.less": "stylelint --syntax less" - }, "engines": { "node": ">=8.0.0" }, - "browserslist": [ - "> 1%", - "last 2 versions", - "not ie <= 10" - ], "checkFiles": [ "src/**/*.js*", "src/**/*.ts*", "src/**/*.less", "config/**/*.js*", "scripts/**/*.js" - ], - "husky": { - "hooks": { - "pre-commit": "npm run lint-staged" - } - } + ] } diff --git a/public/ggeditor/flow/decision.svg b/public/ggeditor/flow/decision.svg new file mode 100644 index 0000000000000000000000000000000000000000..7af317ce1355d5a77f56a98c6d77a1c3bef86127 --- /dev/null +++ b/public/ggeditor/flow/decision.svg @@ -0,0 +1,29 @@ + + + + Group 3 + Created with Sketch. + + + + + + + + + + + + + + + + + + + Decision + + + + + \ No newline at end of file diff --git a/public/ggeditor/flow/model.svg b/public/ggeditor/flow/model.svg new file mode 100644 index 0000000000000000000000000000000000000000..3fd8afaacc1999532827a51f3751a22093ec71ae --- /dev/null +++ b/public/ggeditor/flow/model.svg @@ -0,0 +1,29 @@ + + + + Group 4 + Created with Sketch. + + + + + + + + + + + + + + + + + + + Model + + + + + \ No newline at end of file diff --git a/public/ggeditor/flow/normal.svg b/public/ggeditor/flow/normal.svg new file mode 100644 index 0000000000000000000000000000000000000000..53791e9f09c0a70e69daa7a3ab574723b352ae5a --- /dev/null +++ b/public/ggeditor/flow/normal.svg @@ -0,0 +1,29 @@ + + + + Group + Created with Sketch. + + + + + + + + + + + + + + + + + + + Normal + + + + + \ No newline at end of file diff --git a/public/ggeditor/flow/start.svg b/public/ggeditor/flow/start.svg new file mode 100644 index 0000000000000000000000000000000000000000..3ab4c3cb0ed9a2dc9d43c760f87c07c15fa9248c --- /dev/null +++ b/public/ggeditor/flow/start.svg @@ -0,0 +1,29 @@ + + + + Group 2 + Created with Sketch. + + + + + + + + + + + + + + + + + + + Start + + + + + \ No newline at end of file diff --git a/public/ggeditor/koni/bank.svg b/public/ggeditor/koni/bank.svg new file mode 100644 index 0000000000000000000000000000000000000000..7ec116435088f35f39bd31646811d9038eb38726 --- /dev/null +++ b/public/ggeditor/koni/bank.svg @@ -0,0 +1,29 @@ + + + + Group 16 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/ggeditor/koni/country.svg b/public/ggeditor/koni/country.svg new file mode 100644 index 0000000000000000000000000000000000000000..eeb861a7ba40d65a9e71062f95818bbf3cf90f3e --- /dev/null +++ b/public/ggeditor/koni/country.svg @@ -0,0 +1,29 @@ + + + + Group 18 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/ggeditor/koni/icon.svg b/public/ggeditor/koni/icon.svg new file mode 100644 index 0000000000000000000000000000000000000000..0c3eba65765ebcf28d71a69ec43f652a7ae32fd6 --- /dev/null +++ b/public/ggeditor/koni/icon.svg @@ -0,0 +1,14 @@ + + + + earth copy 53 + Created with Sketch. + + + + + + + + + \ No newline at end of file diff --git a/public/ggeditor/koni/person.svg b/public/ggeditor/koni/person.svg new file mode 100644 index 0000000000000000000000000000000000000000..c9dcad00bb39d2860fbda7615fce97a4b0df7de2 --- /dev/null +++ b/public/ggeditor/koni/person.svg @@ -0,0 +1,29 @@ + + + + Group 17 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/scripts/generateMock.js b/scripts/generateMock.js index 54c7d6d624fcefd98cec3600538284a5056910a7..e8600caf24a4bcb509b1bd8f691bed89febc5c49 100644 --- a/scripts/generateMock.js +++ b/scripts/generateMock.js @@ -1,3 +1,3 @@ const generateMock = require('merge-umi-mock-data'); const path = require('path'); -generateMock(path.join(__dirname, '../mock'), path.join(__dirname, '../functions/mock/index.js')); +generateMock(path.join(__dirname, '../mock'), path.join(__dirname, '../lambda/mock/index.js')); diff --git a/src/common/IconFont/index.js b/src/common/IconFont/index.js new file mode 100644 index 0000000000000000000000000000000000000000..3bba8d2ed7043dd0b4f542ad5ef64bd2e9939f66 --- /dev/null +++ b/src/common/IconFont/index.js @@ -0,0 +1,7 @@ +import { Icon } from 'antd'; + +const IconFont = Icon.createFromIconfontCN({ + scriptUrl: 'https://at.alicdn.com/t/font_1101588_01zniftxm9yp.js', +}); + +export default IconFont; diff --git a/src/common/worldCup2018.json b/src/common/worldCup2018.json new file mode 100644 index 0000000000000000000000000000000000000000..44f3e63f56ae005d569335026a79f8f0012d4611 --- /dev/null +++ b/src/common/worldCup2018.json @@ -0,0 +1,129 @@ +{ + "roots": [ + { + "label": "法国", + "children": [ + { + "label": "克罗地亚", + "side": "left", + "children": [ + { + "label": "克罗地亚", + "children": [ + { + "label": "克罗地亚", + "children": [ + { + "label": "克罗地亚" + }, + { + "label": "丹麦" + } + ] + }, + { + "label": "俄罗斯", + "children": [ + { + "label": "俄罗斯" + }, + { + "label": "西班牙" + } + ] + } + ] + }, + { + "label": "英格兰", + "children": [ + { + "label": "英格兰", + "children": [ + { + "label": "英格兰" + }, + { + "label": "哥伦比亚" + } + ] + }, + { + "label": "瑞典", + "children": [ + { + "label": "瑞士" + }, + { + "label": "瑞典" + } + ] + } + ] + } + ] + }, + { + "label": "法国", + "side": "right", + "children": [ + { + "label": "法国", + "children": [ + { + "label": "法国", + "children": [ + { + "label": "法国" + }, + { + "label": "阿根廷" + } + ] + }, + { + "label": "乌拉圭", + "children": [ + { + "label": "乌拉圭" + }, + { + "label": "葡萄牙" + } + ] + } + ] + }, + { + "label": "比利时", + "children": [ + { + "label": "比利时", + "children": [ + { + "label": "比利时" + }, + { + "label": "日本" + } + ] + }, + { + "label": "巴西", + "children": [ + { + "label": "巴西" + }, + { + "label": "墨西哥" + } + ] + } + ] + } + ] + } + ] + } + ] +} diff --git a/src/components/ArticleListContent/index.d.ts b/src/components/ArticleListContent/index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..bb4988a96d3da9a0a233f5dfe61e3ad561ff0592 --- /dev/null +++ b/src/components/ArticleListContent/index.d.ts @@ -0,0 +1,13 @@ +import React from 'react'; + +export interface ApplicationsProps { + data: { + content?: string; + updatedAt?: any; + avatar?: string; + owner?: string; + href?: string; + }; +} + +export default class ArticleListContent extends React.Component {} diff --git a/src/components/Authorized/AuthorizedRoute.d.ts b/src/components/Authorized/AuthorizedRoute.d.ts index fc78000440d3ca375cadee4e581f51532c8c35bb..f94427daddeba278493bd49d1f90ecb47f74dde2 100644 --- a/src/components/Authorized/AuthorizedRoute.d.ts +++ b/src/components/Authorized/AuthorizedRoute.d.ts @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import { RouteProps } from 'react-router'; type authorityFN = (currentAuthority?: string) => boolean; diff --git a/src/components/Authorized/AuthorizedRoute.js b/src/components/Authorized/AuthorizedRoute.js index 39c6a665f1bf522622ac73e2333f0739c587b1a2..a622ed381ac1b7e5c53851ec1c9cb66aad93ae88 100644 --- a/src/components/Authorized/AuthorizedRoute.js +++ b/src/components/Authorized/AuthorizedRoute.js @@ -1,5 +1,5 @@ import React from 'react'; -import { Route, Redirect } from 'react-router-dom'; +import { Route, Redirect } from 'umi'; import Authorized from './Authorized'; // TODO: umi只会返回render和rest diff --git a/src/components/Authorized/CheckPermissions.js b/src/components/Authorized/CheckPermissions.js index ba83f5b9a14ea01db4824df72db79eb91c19506b..4b49d1f877843694db238b280c3986b612db4e43 100644 --- a/src/components/Authorized/CheckPermissions.js +++ b/src/components/Authorized/CheckPermissions.js @@ -2,21 +2,13 @@ import React from 'react'; import PromiseRender from './PromiseRender'; import { CURRENT } from './renderAuthorize'; -function isPromise(obj) { - return ( - !!obj && - (typeof obj === 'object' || typeof obj === 'function') && - typeof obj.then === 'function' - ); -} - /** * 通用权限检查方法 * Common check permissions method - * @param { 权限判定 Permission judgment type string |array | Promise | Function } authority - * @param { 你的权限 Your permission description type:string} currentAuthority - * @param { 通过的组件 Passing components } target - * @param { 未通过的组件 no pass components } Exception + * @param { 权限判定 | Permission judgment } authority + * @param { 你的权限 | Your permission description } currentAuthority + * @param { 通过的组件 | Passing components } target + * @param { 未通过的组件 | no pass components } Exception */ const checkPermissions = (authority, currentAuthority, target, Exception) => { // 没有判定权限.默认查看所有 @@ -26,47 +18,36 @@ const checkPermissions = (authority, currentAuthority, target, Exception) => { } // 数组处理 if (Array.isArray(authority)) { - if (authority.indexOf(currentAuthority) >= 0) { - return target; - } if (Array.isArray(currentAuthority)) { - for (let i = 0; i < currentAuthority.length; i += 1) { - const element = currentAuthority[i]; - if (authority.indexOf(element) >= 0) { - return target; - } + if (currentAuthority.some(item => authority.includes(item))) { + return target; } + } else if (authority.includes(currentAuthority)) { + return target; } return Exception; } - // string 处理 if (typeof authority === 'string') { - if (authority === currentAuthority) { - return target; - } if (Array.isArray(currentAuthority)) { - for (let i = 0; i < currentAuthority.length; i += 1) { - const element = currentAuthority[i]; - if (authority === element) { - return target; - } + if (currentAuthority.some(item => authority === item)) { + return target; } + } else if (authority === currentAuthority) { + return target; } return Exception; } - // Promise 处理 - if (isPromise(authority)) { + if (authority instanceof Promise) { return ; } - // Function 处理 if (typeof authority === 'function') { try { const bool = authority(currentAuthority); // 函数执行后返回值是 Promise - if (isPromise(bool)) { + if (bool instanceof Promise) { return ; } if (bool) { diff --git a/src/components/Authorized/PromiseRender.js b/src/components/Authorized/PromiseRender.js index 8e2a4059d8689ca1e0be623aedd14cc9a2d75134..58de65934a64dab00013d1b61eb9fa731f758e34 100644 --- a/src/components/Authorized/PromiseRender.js +++ b/src/components/Authorized/PromiseRender.js @@ -1,7 +1,9 @@ -import React from 'react'; import { Spin } from 'antd'; +import isEqual from 'lodash/isEqual'; +import React from 'react'; +import { isComponentClass } from './Secured'; -export default class PromiseRender extends React.PureComponent { +export default class PromiseRender extends React.Component { state = { component: null, }; @@ -10,10 +12,14 @@ export default class PromiseRender extends React.PureComponent { this.setRenderComponent(this.props); } - componentDidUpdate(nextProps) { - // new Props enter - this.setRenderComponent(nextProps); - } + shouldComponentUpdate = (nextProps, nextState) => { + const { component } = this.state; + if (!isEqual(nextProps, this.props)) { + this.setRenderComponent(nextProps); + } + if (nextState.component !== component) return true; + return false; + }; // set render Component : ok or error setRenderComponent(props) { @@ -37,8 +43,12 @@ export default class PromiseRender extends React.PureComponent { // Authorized render is already instantiated, children is no instantiated // Secured is not instantiated checkIsInstantiation = target => { - if (!React.isValidElement(target)) { - return target; + if (isComponentClass(target)) { + const Target = target; + return props => ; + } + if (React.isValidElement(target)) { + return props => React.cloneElement(target, props); } return () => target; }; diff --git a/src/components/Authorized/Secured.js b/src/components/Authorized/Secured.js index c935183dac25c82786336cef97cc905220153271..25b961f01649cc232531f800e89bb46959820032 100644 --- a/src/components/Authorized/Secured.js +++ b/src/components/Authorized/Secured.js @@ -1,31 +1,43 @@ import React from 'react'; import Exception from '../Exception'; import CheckPermissions from './CheckPermissions'; + /** * 默认不能访问任何页面 * default is "NULL" */ const Exception403 = () => ; +export const isComponentClass = component => { + if (!component) return false; + const proto = Object.getPrototypeOf(component); + if (proto === React.Component || proto === Function.prototype) return true; + return isComponentClass(proto); +}; + // Determine whether the incoming component has been instantiated // AuthorizedRoute is already instantiated // Authorized render is already instantiated, children is no instantiated // Secured is not instantiated const checkIsInstantiation = target => { - if (!React.isValidElement(target)) { - return target; + if (isComponentClass(target)) { + const Target = target; + return props => ; + } + if (React.isValidElement(target)) { + return props => React.cloneElement(target, props); } return () => target; }; /** - * 用于判断是否拥有权限访问此view权限 - * authority 支持传入 string, function:()=>boolean|Promise - * e.g. 'user' 只有user用户能访问 - * e.g. 'user,admin' user和 admin 都能访问 + * 用于判断是否拥有权限访问此 view 权限 + * authority 支持传入 string, () => boolean | Promise + * e.g. 'user' 只有 user 用户能访问 + * e.g. 'user,admin' user 和 admin 都能访问 * e.g. ()=>boolean 返回true能访问,返回false不能访问 * e.g. Promise then 能访问 catch不能访问 - * e.g. authority support incoming string, function: () => boolean | Promise + * e.g. authority support incoming string, () => boolean | Promise * e.g. 'user' only user user can access * e.g. 'user, admin' user and admin can access * e.g. () => boolean true to be able to visit, return false can not be accessed diff --git a/src/components/Authorized/demo/secured.md b/src/components/Authorized/demo/secured.md index 1e9537af19d3613b9ea6684f8933afa283ba1415..1999852fd609c5aba9475a40caf9d15d3c111ee5 100644 --- a/src/components/Authorized/demo/secured.md +++ b/src/components/Authorized/demo/secured.md @@ -16,7 +16,9 @@ const { Secured } = RenderAuthorized('user'); @Secured('admin') class TestSecuredString extends React.Component { render() { - ; + return ( + + ) } } ReactDOM.render( diff --git a/src/components/Authorized/index.d.ts b/src/components/Authorized/index.d.ts index b3e2f56c6c3784daa62e908286566c954db1675f..72c98587979899e0f172cf48637c6ab4bb3951e8 100644 --- a/src/components/Authorized/index.d.ts +++ b/src/components/Authorized/index.d.ts @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import AuthorizedRoute, { authority } from './AuthorizedRoute'; export type IReactComponent

= | React.StatelessComponent

diff --git a/src/components/AvatarList/AvatarItem.d.ts b/src/components/AvatarList/AvatarItem.d.ts index 5681de77c2b3634ee8a54487fe15d07044fa8ca4..0e809ab458db93321d68388f227e46cd6a34e411 100644 --- a/src/components/AvatarList/AvatarItem.d.ts +++ b/src/components/AvatarList/AvatarItem.d.ts @@ -1,10 +1,15 @@ -import * as React from 'react'; -export interface IAvatarItemProps { +import React from 'react'; + +export declare type SizeType = number | 'small' | 'default' | 'large'; + +export interface AvatarItemProps { tips: React.ReactNode; src: string; + size?: SizeType; style?: React.CSSProperties; + onClick?: () => void; } -export default class AvatarItem extends React.Component { - constructor(props: IAvatarItemProps); +export default class AvatarItem extends React.Component { + constructor(props: AvatarItemProps); } diff --git a/src/components/AvatarList/index.d.ts b/src/components/AvatarList/index.d.ts index f49ca010d9fe19febd4eaed391278012109dd444..e454a8be4e4d0f6bd9d77fa66fd9c8c7447964aa 100644 --- a/src/components/AvatarList/index.d.ts +++ b/src/components/AvatarList/index.d.ts @@ -1,14 +1,14 @@ -import * as React from 'react'; -import AvatarItem from './AvatarItem'; +import React from 'react'; +import AvatarItem, { AvatarItemProps, SizeType } from './AvatarItem'; -export interface IAvatarListProps { - size?: 'large' | 'small' | 'mini' | 'default'; +export interface AvatarListProps { + Item?: React.ReactElement; + size?: SizeType; maxLength?: number; excessItemsStyle?: React.CSSProperties; style?: React.CSSProperties; - children: React.ReactElement | Array>; + children: React.ReactElement | Array>; } - -export default class AvatarList extends React.Component { +export default class AvatarList extends React.Component { public static Item: typeof AvatarItem; } diff --git a/src/components/Charts/AsyncLoadBizCharts.js b/src/components/Charts/AsyncLoadBizCharts.js deleted file mode 100644 index 8d9a2cd059b692da7a7848f71c269610a9d534c1..0000000000000000000000000000000000000000 --- a/src/components/Charts/AsyncLoadBizCharts.js +++ /dev/null @@ -1,44 +0,0 @@ -import React from 'react'; -import PageLoading from '../PageLoading'; -import { importCDN } from '@/utils/utils'; - -let isLoaderBizChart = false; -const loadBizCharts = async () => { - if (isLoaderBizChart) { - return Promise.resolve(true); - } - await Promise.all([ - importCDN('//gw.alipayobjects.com/os/lib/bizcharts/3.4.3/umd/BizCharts.min.js'), - importCDN('//gw.alipayobjects.com/os/lib/antv/data-set/0.10.1/dist/data-set.min.js'), - ]); - // eslint-disable-next-line no-console - console.log('bizCharts load success'); - isLoaderBizChart = true; - return Promise.resolve(true); -}; - -class AsyncLoadBizCharts extends React.Component { - state = { - loading: !isLoaderBizChart, - }; - - async componentDidMount() { - await loadBizCharts(); - requestAnimationFrame(() => { - this.setState({ - loading: false, - }); - }); - } - - render() { - const { children } = this.props; - const { loading } = this.state; - if (!loading) { - return children; - } - return ; - } -} - -export { loadBizCharts, AsyncLoadBizCharts }; diff --git a/src/components/Charts/Bar/index.d.ts b/src/components/Charts/Bar/index.d.ts index 4899082509dacb84701bb2e02fbe69ba1d06e149..67bb1dd0cd4a4f39880bf67f62534d2e1883d732 100644 --- a/src/components/Charts/Bar/index.d.ts +++ b/src/components/Charts/Bar/index.d.ts @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; export interface IBarProps { title: React.ReactNode; color?: string; diff --git a/src/components/Charts/ChartCard/index.d.ts b/src/components/Charts/ChartCard/index.d.ts index 0437c0c857d7f1c63c506c5eb238583a251714d0..5153f5e062589a1b650cd63a79577aaa3dfdd8ea 100644 --- a/src/components/Charts/ChartCard/index.d.ts +++ b/src/components/Charts/ChartCard/index.d.ts @@ -1,5 +1,5 @@ import { CardProps } from 'antd/lib/card'; -import * as React from 'react'; +import React from 'react'; export interface IChartCardProps extends CardProps { title: React.ReactNode; diff --git a/src/components/Charts/Field/index.d.ts b/src/components/Charts/Field/index.d.ts index 975fb667d8db178c1154162f4803e20f1c72a8e4..80b1bf1d7198e5710a8b06435eadd72d327ab895 100644 --- a/src/components/Charts/Field/index.d.ts +++ b/src/components/Charts/Field/index.d.ts @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; export interface IFieldProps { label: React.ReactNode; value: React.ReactNode; diff --git a/src/components/Charts/Gauge/index.d.ts b/src/components/Charts/Gauge/index.d.ts index 66e3c003a957581d88a06e63b32a7a3e76c5cd3a..fe5500918c7173834922d68f2a1f5306f43fe7da 100644 --- a/src/components/Charts/Gauge/index.d.ts +++ b/src/components/Charts/Gauge/index.d.ts @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; export interface IGaugeProps { title: React.ReactNode; color?: string; diff --git a/src/components/Charts/Gauge/index.js b/src/components/Charts/Gauge/index.js index 2249211aeaad53652d578c8dc050a60795129b68..e97f126e6e42b00b131ebdbdbe63fc8de0da70fa 100644 --- a/src/components/Charts/Gauge/index.js +++ b/src/components/Charts/Gauge/index.js @@ -146,7 +146,7 @@ class Gauge extends React.Component {

${title}

- ${data[0].value * 10}% + ${(data[0].value * 10).toFixed(2)}%

`} /> diff --git a/src/components/Charts/MiniArea/index.d.ts b/src/components/Charts/MiniArea/index.d.ts index b223b68ca097e01f1c76e4e2cb4e95e9db4dc39b..8b4e71cab78e8ecdaf1f49559957660e9fc77547 100644 --- a/src/components/Charts/MiniArea/index.d.ts +++ b/src/components/Charts/MiniArea/index.d.ts @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; // g2已经更新到3.0 // 不带的写了 diff --git a/src/components/Charts/MiniBar/index.d.ts b/src/components/Charts/MiniBar/index.d.ts index 0c4bd6cce558f4b948691c553c65d76c8c34fc6b..b2685339eab30833120979e1356c3913654c8305 100644 --- a/src/components/Charts/MiniBar/index.d.ts +++ b/src/components/Charts/MiniBar/index.d.ts @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; export interface IMiniBarProps { color?: string; height: number; diff --git a/src/components/Charts/MiniProgress/index.d.ts b/src/components/Charts/MiniProgress/index.d.ts index aaeb7261d7ea06dfad935faf7c00238035ea921d..6111d88d585000899875e83ec11e4fe9072fe84e 100644 --- a/src/components/Charts/MiniProgress/index.d.ts +++ b/src/components/Charts/MiniProgress/index.d.ts @@ -1,6 +1,7 @@ -import * as React from 'react'; +import React from 'react'; export interface IMiniProgressProps { target: number; + targetLabel: string; color?: string; strokeWidth?: number; percent?: number; diff --git a/src/components/Charts/MiniProgress/index.js b/src/components/Charts/MiniProgress/index.js index 795c79b15951e2bdde85c0a6fa1427ba46c8df1c..dd5712e8a850c8acbd41d959d73f17a96ecb65eb 100644 --- a/src/components/Charts/MiniProgress/index.js +++ b/src/components/Charts/MiniProgress/index.js @@ -1,27 +1,34 @@ import React from 'react'; import { Tooltip } from 'antd'; - import styles from './index.less'; -const MiniProgress = ({ target, color = 'rgb(19, 194, 194)', strokeWidth, percent }) => ( -
- -
- - +const MiniProgress = ({ + targetLabel, + target, + color = 'rgb(19, 194, 194)', + strokeWidth, + percent, +}) => { + return ( +
+ +
+ + +
+
+
+
- -
-
-
-); + ); +}; export default MiniProgress; diff --git a/src/components/Charts/MiniProgress/index.less b/src/components/Charts/MiniProgress/index.less index 40ba70be6bd3d4fb2a52efc34582c6ad81346e37..e1e0b4fc5169615814efe60821f39dc3e1bc58b9 100644 --- a/src/components/Charts/MiniProgress/index.less +++ b/src/components/Charts/MiniProgress/index.less @@ -19,6 +19,8 @@ position: absolute; top: 0; bottom: 0; + z-index: 9; + width: 20px; span { position: absolute; top: 0; diff --git a/src/components/Charts/Pie/index.d.ts b/src/components/Charts/Pie/index.d.ts index 66c93eeb5d856928697335530c090c68492e81a5..63aecfa3d699f2148ca776b50f11f22387466ec3 100644 --- a/src/components/Charts/Pie/index.d.ts +++ b/src/components/Charts/Pie/index.d.ts @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; export interface IPieProps { animate?: boolean; color?: string; diff --git a/src/components/Charts/Radar/index.d.ts b/src/components/Charts/Radar/index.d.ts index 963ac8c37c112c360cd399b039d790e53b83a2a3..6a7dd42afe22ba23cbf0050f7334e3d2e383850a 100644 --- a/src/components/Charts/Radar/index.d.ts +++ b/src/components/Charts/Radar/index.d.ts @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; export interface IRadarProps { title?: React.ReactNode; height: number; diff --git a/src/components/Charts/TagCloud/index.d.ts b/src/components/Charts/TagCloud/index.d.ts index 462650c4dbb7532670d200141f7cbebc52525808..ac25269dfe1c414148bbcdcada429b978c3011a4 100644 --- a/src/components/Charts/TagCloud/index.d.ts +++ b/src/components/Charts/TagCloud/index.d.ts @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; export interface ITagCloudProps { data: Array<{ name: string; diff --git a/src/components/Charts/TagCloud/index.js b/src/components/Charts/TagCloud/index.js index d94699bd551c0c33319bd3d61eac2c4edb613bbe..4898d821a3f9282fdce7d1bb05e85c8e6f7a71d2 100644 --- a/src/components/Charts/TagCloud/index.js +++ b/src/components/Charts/TagCloud/index.js @@ -51,20 +51,16 @@ class TagCloud extends Component { initTagCloud = () => { function getTextAttrs(cfg) { - return Object.assign( - {}, - { - fillOpacity: cfg.opacity, - fontSize: cfg.origin._origin.size, - rotate: cfg.origin._origin.rotate, - text: cfg.origin._origin.text, - textAlign: 'center', - fontFamily: cfg.origin._origin.font, - fill: cfg.color, - textBaseline: 'Alphabetic', - }, - cfg.style - ); + return Object.assign({}, cfg.style, { + fillOpacity: cfg.opacity, + fontSize: cfg.origin._origin.size, + rotate: cfg.origin._origin.rotate, + text: cfg.origin._origin.text, + textAlign: 'center', + fontFamily: cfg.origin._origin.font, + fill: cfg.color, + textBaseline: 'Alphabetic', + }); } // 给point注册一个词云的shape diff --git a/src/components/Charts/TimelineChart/index.d.ts b/src/components/Charts/TimelineChart/index.d.ts index 40b94325a9833e9479846b323387e6515160fb7e..0f547e7736c807790f4b4581262b83c27266a1e0 100644 --- a/src/components/Charts/TimelineChart/index.d.ts +++ b/src/components/Charts/TimelineChart/index.d.ts @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; export interface ITimelineChartProps { data: Array<{ x: number; diff --git a/src/components/Charts/WaterWave/index.d.ts b/src/components/Charts/WaterWave/index.d.ts index 8f5588d29f29baa7a5409eded24fb2cbe82e1c53..e30a7e48f7478618e716757b095929c889797db7 100644 --- a/src/components/Charts/WaterWave/index.d.ts +++ b/src/components/Charts/WaterWave/index.d.ts @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; export interface IWaterWaveProps { title: React.ReactNode; color?: string; diff --git a/src/components/Charts/index.js b/src/components/Charts/index.js index 56a1c565f4a162f4ef0cee14b39116596ed9a9f0..294eeb65f430ea18af184fc27ba9f2d11c188d47 100644 --- a/src/components/Charts/index.js +++ b/src/components/Charts/index.js @@ -1,28 +1,16 @@ -import React, { Suspense } from 'react'; import numeral from 'numeral'; import ChartCard from './ChartCard'; import Field from './Field'; - -const getComponent = Component => { - return props => { - return ( - - - - ); - }; -}; - -const Bar = getComponent(React.lazy(() => import('./Bar'))); -const Pie = getComponent(React.lazy(() => import('./Pie'))); -const Radar = getComponent(React.lazy(() => import('./Radar'))); -const Gauge = getComponent(React.lazy(() => import('./Gauge'))); -const MiniArea = getComponent(React.lazy(() => import('./MiniArea'))); -const MiniBar = getComponent(React.lazy(() => import('./MiniBar'))); -const MiniProgress = getComponent(React.lazy(() => import('./MiniProgress'))); -const WaterWave = getComponent(React.lazy(() => import('./WaterWave'))); -const TagCloud = getComponent(React.lazy(() => import('./TagCloud'))); -const TimelineChart = getComponent(React.lazy(() => import('./TimelineChart'))); +import Bar from './Bar'; +import Pie from './Pie'; +import Radar from './Radar'; +import Gauge from './Gauge'; +import MiniArea from './MiniArea'; +import MiniBar from './MiniBar'; +import MiniProgress from './MiniProgress'; +import WaterWave from './WaterWave'; +import TagCloud from './TagCloud'; +import TimelineChart from './TimelineChart'; const yuan = val => `¥ ${numeral(val).format('0,0')}`; diff --git a/src/components/CountDown/index.d.ts b/src/components/CountDown/index.d.ts index d39a2e951830d5cddca08c8becbdb500847448b3..af658e3f6c4b0af3dfd7e374bc3d247c9577a5c4 100644 --- a/src/components/CountDown/index.d.ts +++ b/src/components/CountDown/index.d.ts @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; export interface ICountDownProps { format?: (time: number) => void; target: Date | number; diff --git a/src/components/DescriptionList/Description.d.ts b/src/components/DescriptionList/Description.d.ts index 2a17be374accc8e2a1ffa9812327398a6c3f7173..41c0497075fe1178108e9903b4eb0d56c9e93fcc 100644 --- a/src/components/DescriptionList/Description.d.ts +++ b/src/components/DescriptionList/Description.d.ts @@ -1,9 +1,11 @@ -import * as React from 'react'; +import React from 'react'; +import { ColProps } from 'antd/es/col'; -export default class Description extends React.Component< - { - term: React.ReactNode; - style?: React.CSSProperties; - }, - any -> {} +export interface DescriptionProps extends ColProps { + column?: number; + key?: string | number; + style?: React.CSSProperties; + term?: React.ReactNode; +} + +export default class Description extends React.Component {} diff --git a/src/components/DescriptionList/index.d.ts b/src/components/DescriptionList/index.d.ts index 96ccfa7da3a21d790e3348a65603488303780669..c0bb071c5a33fe6d593b1722ffe707667c65cc60 100644 --- a/src/components/DescriptionList/index.d.ts +++ b/src/components/DescriptionList/index.d.ts @@ -1,15 +1,17 @@ -import * as React from 'react'; -import Description from './Description'; +import React from 'react'; +import Description, { DescriptionProps } from './Description'; -export interface IDescriptionListProps { - layout?: 'horizontal' | 'vertical'; +export interface DescriptionListProps { + className?: string; col?: number; - title: React.ReactNode; + description?: DescriptionProps[]; gutter?: number; + layout?: 'horizontal' | 'vertical'; size?: 'large' | 'small'; style?: React.CSSProperties; + title?: React.ReactNode; } -export default class DescriptionList extends React.Component { +export default class DescriptionList extends React.Component { public static Description: typeof Description; } diff --git a/src/components/DescriptionList/index.less b/src/components/DescriptionList/index.less index 4048a128ee949cfd5c8ab94ea5b5c331cd1bb22b..c3cf8e69e7cd0269f359b20fa73e868a7e87182b 100644 --- a/src/components/DescriptionList/index.less +++ b/src/components/DescriptionList/index.less @@ -8,6 +8,14 @@ overflow: hidden; } } + // fix margin top error of following descriptionList + & + & { + :global { + .ant-row { + margin-top: 16px; + } + } + } .title { margin-bottom: 16px; @@ -47,6 +55,14 @@ margin-bottom: -8px; } } + // fix margin top error of following descriptionList + & + .descriptionList { + :global { + .ant-row { + margin-top: 8px; + } + } + } .title { margin-bottom: 12px; color: @text-color; diff --git a/src/components/EditableItem/index.d.ts b/src/components/EditableItem/index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..fc69b2748fe5f406a56d6ece4d635e4e52d03e97 --- /dev/null +++ b/src/components/EditableItem/index.d.ts @@ -0,0 +1,7 @@ +import React from 'react'; + +export interface EditableItemProps { + onChange?: (value?: string | string[] | number) => void; +} + +export default class EditableItem extends React.Component {} diff --git a/src/components/EditableLinkGroup/index.d.ts b/src/components/EditableLinkGroup/index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..07a42abecd33f6ec3ad3f3785a902cd79e36deb3 --- /dev/null +++ b/src/components/EditableLinkGroup/index.d.ts @@ -0,0 +1,9 @@ +import React from 'react'; + +export interface EditableLinkGroupProps { + links: any[]; + onAdd: () => void; + linkElement: string; +} + +export default class EditableLinkGroup extends React.Component {} diff --git a/src/components/EditorContextMenu/FlowContextMenu.js b/src/components/EditorContextMenu/FlowContextMenu.js new file mode 100644 index 0000000000000000000000000000000000000000..cbb7041f2003d17f4ef53d7ea8925ff8df2bf537 --- /dev/null +++ b/src/components/EditorContextMenu/FlowContextMenu.js @@ -0,0 +1,36 @@ +import React from 'react'; +import { NodeMenu, EdgeMenu, GroupMenu, MultiMenu, CanvasMenu, ContextMenu } from 'gg-editor'; +import MenuItem from './MenuItem'; +import styles from './index.less'; + +const FlowContextMenu = () => { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default FlowContextMenu; diff --git a/src/components/EditorContextMenu/KoniContextMenu.js b/src/components/EditorContextMenu/KoniContextMenu.js new file mode 100644 index 0000000000000000000000000000000000000000..8b049a5ee7d0d0dae9216d6f01f1f5e40b4a9904 --- /dev/null +++ b/src/components/EditorContextMenu/KoniContextMenu.js @@ -0,0 +1,3 @@ +import FlowContextMenu from './FlowContextMenu'; + +export default FlowContextMenu; diff --git a/src/components/EditorContextMenu/MenuItem.js b/src/components/EditorContextMenu/MenuItem.js new file mode 100644 index 0000000000000000000000000000000000000000..4cbde89e1a9a79f5ee0eb44ac5a443cd58feddb1 --- /dev/null +++ b/src/components/EditorContextMenu/MenuItem.js @@ -0,0 +1,20 @@ +import React from 'react'; +import { Command } from 'gg-editor'; +import upperFirst from 'lodash/upperFirst'; +import IconFont from '../../common/IconFont'; +import styles from './index.less'; + +const MenuItem = props => { + const { command, icon, text } = props; + + return ( + +
+ + {text || upperFirst(command)} +
+
+ ); +}; + +export default MenuItem; diff --git a/src/components/EditorContextMenu/MindContextMenu.js b/src/components/EditorContextMenu/MindContextMenu.js new file mode 100644 index 0000000000000000000000000000000000000000..2a9d43cd28672b2c0afa4d9370f40f3366e00718 --- /dev/null +++ b/src/components/EditorContextMenu/MindContextMenu.js @@ -0,0 +1,24 @@ +import React from 'react'; +import { NodeMenu, CanvasMenu, ContextMenu } from 'gg-editor'; +import MenuItem from './MenuItem'; +import styles from './index.less'; + +const MindContextMenu = () => { + return ( + + + + + + + + + + + + + + ); +}; + +export default MindContextMenu; diff --git a/src/components/EditorContextMenu/index.js b/src/components/EditorContextMenu/index.js new file mode 100644 index 0000000000000000000000000000000000000000..16fcde018fc9e647daea97683cf46a5a9d264cfe --- /dev/null +++ b/src/components/EditorContextMenu/index.js @@ -0,0 +1,5 @@ +import FlowContextMenu from './FlowContextMenu'; +import MindContextMenu from './MindContextMenu'; +import KoniContextMenu from './KoniContextMenu'; + +export { FlowContextMenu, MindContextMenu, KoniContextMenu }; diff --git a/src/components/EditorContextMenu/index.less b/src/components/EditorContextMenu/index.less new file mode 100644 index 0000000000000000000000000000000000000000..8a2cdae3bfbe5ffaaef812f8ab22677f5340dc91 --- /dev/null +++ b/src/components/EditorContextMenu/index.less @@ -0,0 +1,39 @@ +.contextMenu { + display: none; + overflow: hidden; + background: #fff; + border-radius: 4px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); + + .item { + display: flex; + align-items: center; + padding: 5px 12px; + cursor: pointer; + transition: all 0.3s; + user-select: none; + + &:hover { + background: #e6f7ff; + } + + i { + margin-right: 8px; + } + } + + :global { + .disable { + :local { + .item { + color: rgba(0, 0, 0, 0.25); + cursor: auto; + + &:hover { + background: #fff; + } + } + } + } + } +} diff --git a/src/components/EditorDetailPanel/DetailForm.js b/src/components/EditorDetailPanel/DetailForm.js new file mode 100644 index 0000000000000000000000000000000000000000..3d68011530023482b45bf4afb29971b7c33a83d8 --- /dev/null +++ b/src/components/EditorDetailPanel/DetailForm.js @@ -0,0 +1,129 @@ +import React, { Fragment } from 'react'; +import { Card, Form, Input, Select } from 'antd'; +import { withPropsAPI } from 'gg-editor'; +import upperFirst from 'lodash/upperFirst'; + +const { Item } = Form; +const { Option } = Select; + +const inlineFormItemLayout = { + labelCol: { + sm: { span: 8 }, + }, + wrapperCol: { + sm: { span: 16 }, + }, +}; + +class DetailForm extends React.Component { + get item() { + const { propsAPI } = this.props; + + return propsAPI.getSelected()[0]; + } + + handleSubmit = e => { + if (e && e.preventDefault) { + e.preventDefault(); + } + + const { form, propsAPI } = this.props; + const { getSelected, executeCommand, update } = propsAPI; + + setTimeout(() => { + form.validateFieldsAndScroll((err, values) => { + if (err) { + return; + } + + const item = getSelected()[0]; + + if (!item) { + return; + } + + executeCommand(() => { + update(item, { + ...values, + }); + }); + }); + }, 0); + }; + + renderEdgeShapeSelect = () => { + return ( + + ); + }; + + renderNodeDetail = () => { + const { form } = this.props; + const { label } = this.item.getModel(); + + return ( + + {form.getFieldDecorator('label', { + initialValue: label, + })()} + + ); + }; + + renderEdgeDetail = () => { + const { form } = this.props; + const { label = '', shape = 'flow-smooth' } = this.item.getModel(); + + return ( + + + {form.getFieldDecorator('label', { + initialValue: label, + })()} + + + {form.getFieldDecorator('shape', { + initialValue: shape, + })(this.renderEdgeShapeSelect())} + + + ); + }; + + renderGroupDetail = () => { + const { form } = this.props; + const { label = '新建分组' } = this.item.getModel(); + + return ( + + {form.getFieldDecorator('label', { + initialValue: label, + })()} + + ); + }; + + render() { + const { type } = this.props; + + if (!this.item) { + return null; + } + + return ( + +
+ {type === 'node' && this.renderNodeDetail()} + {type === 'edge' && this.renderEdgeDetail()} + {type === 'group' && this.renderGroupDetail()} +
+
+ ); + } +} + +export default Form.create()(withPropsAPI(DetailForm)); diff --git a/src/components/EditorDetailPanel/FlowDetailPanel.js b/src/components/EditorDetailPanel/FlowDetailPanel.js new file mode 100644 index 0000000000000000000000000000000000000000..8d6816186b96e555406d5c5534903e3dc3d98b6b --- /dev/null +++ b/src/components/EditorDetailPanel/FlowDetailPanel.js @@ -0,0 +1,29 @@ +import React from 'react'; +import { Card } from 'antd'; +import { NodePanel, EdgePanel, GroupPanel, MultiPanel, CanvasPanel, DetailPanel } from 'gg-editor'; +import DetailForm from './DetailForm'; +import styles from './index.less'; + +const FlowDetailPanel = () => { + return ( + + + + + + + + + + + + + + + + + + ); +}; + +export default FlowDetailPanel; diff --git a/src/components/EditorDetailPanel/KoniDetailPanel.js b/src/components/EditorDetailPanel/KoniDetailPanel.js new file mode 100644 index 0000000000000000000000000000000000000000..18aea9a44f5d96009d696e6bf145b3715c0d824c --- /dev/null +++ b/src/components/EditorDetailPanel/KoniDetailPanel.js @@ -0,0 +1,3 @@ +import FlowDetailPanel from './FlowDetailPanel'; + +export default FlowDetailPanel; diff --git a/src/components/EditorDetailPanel/MindDetailPanel.js b/src/components/EditorDetailPanel/MindDetailPanel.js new file mode 100644 index 0000000000000000000000000000000000000000..6b4d5c9eadd0a6f5d656d3c2f772dde7af45f85d --- /dev/null +++ b/src/components/EditorDetailPanel/MindDetailPanel.js @@ -0,0 +1,20 @@ +import React from 'react'; +import { Card } from 'antd'; +import { NodePanel, CanvasPanel, DetailPanel } from 'gg-editor'; +import DetailForm from './DetailForm'; +import styles from './index.less'; + +const MindDetailPanel = () => { + return ( + + + + + + + + + ); +}; + +export default MindDetailPanel; diff --git a/src/components/EditorDetailPanel/index.js b/src/components/EditorDetailPanel/index.js new file mode 100644 index 0000000000000000000000000000000000000000..8df063eff1c22b6ce5a3ecffbd004b7de681b73b --- /dev/null +++ b/src/components/EditorDetailPanel/index.js @@ -0,0 +1,5 @@ +import FlowDetailPanel from './FlowDetailPanel'; +import MindDetailPanel from './MindDetailPanel'; +import KoniDetailPanel from './KoniDetailPanel'; + +export { FlowDetailPanel, MindDetailPanel, KoniDetailPanel }; diff --git a/src/components/EditorDetailPanel/index.less b/src/components/EditorDetailPanel/index.less new file mode 100644 index 0000000000000000000000000000000000000000..081945be43c093076bab1744984f5377a34f0fe2 --- /dev/null +++ b/src/components/EditorDetailPanel/index.less @@ -0,0 +1,10 @@ +.detailPanel { + flex: 1; + background: #fafafa; + + :global { + .ant-card { + background: #fafafa; + } + } +} diff --git a/src/components/EditorItemPanel/FlowItemPanel.js b/src/components/EditorItemPanel/FlowItemPanel.js new file mode 100644 index 0000000000000000000000000000000000000000..b3b46930c86e407e100984bf6d253f480e3c244e --- /dev/null +++ b/src/components/EditorItemPanel/FlowItemPanel.js @@ -0,0 +1,55 @@ +import React from 'react'; +import { Card } from 'antd'; +import { ItemPanel, Item } from 'gg-editor'; +import styles from './index.less'; + +const FlowItemPanel = () => { + return ( + + + + + + + + + ); +}; + +export default FlowItemPanel; diff --git a/src/components/EditorItemPanel/KoniItemPanel.js b/src/components/EditorItemPanel/KoniItemPanel.js new file mode 100644 index 0000000000000000000000000000000000000000..655ea99a6682da3ae814f29a2bdffa27d827512e --- /dev/null +++ b/src/components/EditorItemPanel/KoniItemPanel.js @@ -0,0 +1,51 @@ +import React from 'react'; +import { Card } from 'antd'; +import { ItemPanel, Item } from 'gg-editor'; +import styles from './index.less'; + +const KoniItemPanel = () => { + return ( + + + + + + + + ); +}; + +export default KoniItemPanel; diff --git a/src/components/EditorItemPanel/index.js b/src/components/EditorItemPanel/index.js new file mode 100644 index 0000000000000000000000000000000000000000..2ba03fbb700d78600d6ea668a57ffaad4e0586a6 --- /dev/null +++ b/src/components/EditorItemPanel/index.js @@ -0,0 +1,4 @@ +import FlowItemPanel from './FlowItemPanel'; +import KoniItemPanel from './KoniItemPanel'; + +export { FlowItemPanel, KoniItemPanel }; diff --git a/src/components/EditorItemPanel/index.less b/src/components/EditorItemPanel/index.less new file mode 100644 index 0000000000000000000000000000000000000000..a7acc366d1715dc50003f7e7c1335e2844112a41 --- /dev/null +++ b/src/components/EditorItemPanel/index.less @@ -0,0 +1,20 @@ +.itemPanel { + flex: 1; + background: #fafafa; + + :global { + .ant-card { + background: #fafafa; + } + + .ant-card-body { + display: flex; + flex-direction: column; + align-items: center; + + > div { + margin-bottom: 16px; + } + } + } +} diff --git a/src/components/EditorKoniCustomNode/index.js b/src/components/EditorKoniCustomNode/index.js new file mode 100644 index 0000000000000000000000000000000000000000..4c13bb4f42cb3c20e55b26e63de9cdb5c9448e5d --- /dev/null +++ b/src/components/EditorKoniCustomNode/index.js @@ -0,0 +1,33 @@ +import React from 'react'; +import { RegisterNode } from 'gg-editor'; + +class KoniCustomNode extends React.Component { + render() { + const config = { + draw(item) { + const keyShape = this.drawKeyShape(item); + + // draw label + this.drawLabel(item); + + // draw image + const group = item.getGraphicGroup(); + const model = item.getModel(); + + group.addShape('image', { + attrs: { + x: -7, + y: -7, + img: model.icon, + }, + }); + + return keyShape; + }, + }; + + return ; + } +} + +export default KoniCustomNode; diff --git a/src/components/EditorMinimap/index.js b/src/components/EditorMinimap/index.js new file mode 100644 index 0000000000000000000000000000000000000000..8c86b242845629d533e8d55ce436c0cd63ae59d5 --- /dev/null +++ b/src/components/EditorMinimap/index.js @@ -0,0 +1,13 @@ +import React from 'react'; +import { Card } from 'antd'; +import { Minimap } from 'gg-editor'; + +const EditorMinimap = () => { + return ( + + + + ); +}; + +export default EditorMinimap; diff --git a/src/components/EditorToolbar/FlowToolbar.js b/src/components/EditorToolbar/FlowToolbar.js new file mode 100644 index 0000000000000000000000000000000000000000..374c1858bcd07f1a68368fd437ac11e0c7eb5113 --- /dev/null +++ b/src/components/EditorToolbar/FlowToolbar.js @@ -0,0 +1,32 @@ +import React from 'react'; +import { Divider } from 'antd'; +import { Toolbar } from 'gg-editor'; +import ToolbarButton from './ToolbarButton'; +import styles from './index.less'; + +const FlowToolbar = () => { + return ( + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default FlowToolbar; diff --git a/src/components/EditorToolbar/KoniToolbar.js b/src/components/EditorToolbar/KoniToolbar.js new file mode 100644 index 0000000000000000000000000000000000000000..f222007aff66a7d41abfd1f6bd459d7d7138c116 --- /dev/null +++ b/src/components/EditorToolbar/KoniToolbar.js @@ -0,0 +1,3 @@ +import FlowToolbar from './FlowToolbar'; + +export default FlowToolbar; diff --git a/src/components/EditorToolbar/MindToolbar.js b/src/components/EditorToolbar/MindToolbar.js new file mode 100644 index 0000000000000000000000000000000000000000..1c83286ac0b06abfe634b141bb7bf4beee266cba --- /dev/null +++ b/src/components/EditorToolbar/MindToolbar.js @@ -0,0 +1,27 @@ +import React from 'react'; +import { Divider } from 'antd'; +import { Toolbar } from 'gg-editor'; +import ToolbarButton from './ToolbarButton'; +import styles from './index.less'; + +const FlowToolbar = () => { + return ( + + + + + + + + + + + + + + + + ); +}; + +export default FlowToolbar; diff --git a/src/components/EditorToolbar/ToolbarButton.js b/src/components/EditorToolbar/ToolbarButton.js new file mode 100644 index 0000000000000000000000000000000000000000..eb5b4ffa2f0fab721aeb8de278d243dca99d9f85 --- /dev/null +++ b/src/components/EditorToolbar/ToolbarButton.js @@ -0,0 +1,24 @@ +import React from 'react'; +import { Tooltip } from 'antd'; +import { Command } from 'gg-editor'; +import upperFirst from 'lodash/upperFirst'; +import IconFont from '../../common/IconFont'; +import styles from './index.less'; + +const ToolbarButton = props => { + const { command, icon, text } = props; + + return ( + + + + + + ); +}; + +export default ToolbarButton; diff --git a/src/components/EditorToolbar/index.js b/src/components/EditorToolbar/index.js new file mode 100644 index 0000000000000000000000000000000000000000..ac08e3dc54a84c9d2f292878f706d34c01091474 --- /dev/null +++ b/src/components/EditorToolbar/index.js @@ -0,0 +1,5 @@ +import FlowToolbar from './FlowToolbar'; +import MindToolbar from './MindToolbar'; +import KoniToolbar from './KoniToolbar'; + +export { FlowToolbar, MindToolbar, KoniToolbar }; diff --git a/src/components/EditorToolbar/index.less b/src/components/EditorToolbar/index.less new file mode 100644 index 0000000000000000000000000000000000000000..a5cca37c2931b149d39c94410e0d105922173e29 --- /dev/null +++ b/src/components/EditorToolbar/index.less @@ -0,0 +1,39 @@ +.toolbar { + display: flex; + align-items: center; + + :global { + .command i { + display: inline-block; + width: 27px; + height: 27px; + margin: 0 6px; + padding-top: 6px; + text-align: center; + border: 1px solid #fff; + cursor: pointer; + + &:hover { + border: 1px solid #e6e9ed; + } + } + + .disable i { + color: rgba(0, 0, 0, 0.25); + cursor: auto; + + &:hover { + border: 1px solid #fff; + } + } + } +} + +.tooltip { + :global { + .ant-tooltip-inner { + font-size: 12px; + border-radius: 0; + } + } +} diff --git a/src/components/Ellipsis/index.d.ts b/src/components/Ellipsis/index.d.ts index 37d508d77335048de87287fc52fb9f457e89dc33..075fa789a40ec7904dd39e9c293206bf86ac0db8 100644 --- a/src/components/Ellipsis/index.d.ts +++ b/src/components/Ellipsis/index.d.ts @@ -1,13 +1,13 @@ -import * as React from 'react'; +import React from 'react'; import { TooltipProps } from 'antd/lib/tooltip'; -export interface IEllipsisTooltipProps extends TooltipProps { +export interface EllipsisTooltipProps extends TooltipProps { title?: undefined; overlayStyle?: undefined; } -export interface IEllipsisProps { - tooltip?: boolean | IEllipsisTooltipProps; +export interface EllipsisProps { + tooltip?: boolean | EllipsisTooltipProps; length?: number; lines?: number; style?: React.CSSProperties; @@ -18,4 +18,4 @@ export interface IEllipsisProps { export function getStrFullLength(str: string): number; export function cutStrByFullLength(str: string, maxLength: number): string; -export default class Ellipsis extends React.Component {} +export default class Ellipsis extends React.Component {} diff --git a/src/components/Exception/index.d.ts b/src/components/Exception/index.d.ts index a74abb1fa6334cb2b8ef987aab5a1b5dc1f0d531..b8cb65dd92d4a896e745821ddb8dc6aea2cc08da 100644 --- a/src/components/Exception/index.d.ts +++ b/src/components/Exception/index.d.ts @@ -1,15 +1,23 @@ -import * as React from 'react'; -export interface IExceptionProps { +import React from 'react'; +import * as H from 'history'; + +export interface ExceptionProps< + L = { + to: H.LocationDescriptor; + href?: H.LocationDescriptor; + replace?: boolean; + innerRef?: (node: HTMLAnchorElement | null) => void; + } +> { type?: '403' | '404' | '500'; title?: React.ReactNode; desc?: React.ReactNode; img?: string; actions?: React.ReactNode; - linkElement?: string | React.ComponentType; + linkElement?: string | React.ComponentType; style?: React.CSSProperties; className?: string; backText?: React.ReactNode; redirect?: string; } - -export default class Exception extends React.Component {} +export default class Exception extends React.Component {} diff --git a/src/components/FooterToolbar/index.d.ts b/src/components/FooterToolbar/index.d.ts index 9c6ac5b4cad95ade8f24a1b02e6de72f4770bfeb..9ec202c1c5b3d986fc5f11ea94560ea2cdb90501 100644 --- a/src/components/FooterToolbar/index.d.ts +++ b/src/components/FooterToolbar/index.d.ts @@ -1,7 +1,8 @@ -import * as React from 'react'; -export interface IFooterToolbarProps { +import React from 'react'; +export interface FooterToolbarProps { extra: React.ReactNode; style?: React.CSSProperties; + className?: string; } -export default class FooterToolbar extends React.Component {} +export default class FooterToolbar extends React.Component {} diff --git a/src/components/GlobalFooter/index.d.ts b/src/components/GlobalFooter/index.d.ts index 3fa5c423eba263aa4c9d39eb49f395781c5e8f43..efde77dbd4bfd58ed27da72a56e6328b3eefdee5 100644 --- a/src/components/GlobalFooter/index.d.ts +++ b/src/components/GlobalFooter/index.d.ts @@ -1,5 +1,5 @@ -import * as React from 'react'; -export interface IGlobalFooterProps { +import React from 'react'; +export interface GlobalFooterProps { links?: Array<{ key?: string; title: React.ReactNode; @@ -8,6 +8,7 @@ export interface IGlobalFooterProps { }>; copyright?: React.ReactNode; style?: React.CSSProperties; + className?: string; } -export default class GlobalFooter extends React.Component {} +export default class GlobalFooter extends React.Component {} diff --git a/src/components/GlobalHeader/RightContent.d.ts b/src/components/GlobalHeader/RightContent.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..275d9996a06d881735b6bcc70af5887ca2769f67 --- /dev/null +++ b/src/components/GlobalHeader/RightContent.d.ts @@ -0,0 +1,26 @@ +import React from 'react'; +import { DropDownProps } from 'antd/lib/dropdown'; +import { ClickParam } from 'antd/es/menu'; +import { SiderTheme } from 'antd/es/Layout/Sider'; + +export interface GlobalHeaderRightProps { + notices?: any[]; + dispatch?: (args: any) => void; + currentUser?: { + avatar?: string; + name?: string; + title?: string; + group?: string; + signature?: string; + geographic?: any; + tags?: any[]; + unreadCount: number; + }; + fetchingNotices?: boolean; + onNoticeVisibleChange?: (visible: boolean) => void; + onMenuClick?: (param: ClickParam) => void; + onNoticeClear?: (tabName: string) => void; + theme?: SiderTheme; +} + +export default class GlobalHeaderRight extends React.Component {} diff --git a/src/components/GlobalHeader/RightContent.js b/src/components/GlobalHeader/RightContent.js index dad360ff08299518c7d3fdc7026c2b3b289b883f..d40e1166c670af5955030dff1278d2747aa2e655 100644 --- a/src/components/GlobalHeader/RightContent.js +++ b/src/components/GlobalHeader/RightContent.js @@ -1,6 +1,6 @@ import React, { PureComponent } from 'react'; -import { FormattedMessage, formatMessage } from 'umi/locale'; -import { Spin, Tag, Menu, Icon, Avatar, Tooltip } from 'antd'; +import { FormattedMessage, formatMessage } from 'umi-plugin-react/locale'; +import { Spin, Tag, Menu, Icon, Avatar, Tooltip, message } from 'antd'; import moment from 'moment'; import groupBy from 'lodash/groupBy'; import NoticeIcon from '../NoticeIcon'; @@ -63,30 +63,13 @@ export default class GlobalHeaderRight extends PureComponent { }); }; - fetchMoreNotices = tabProps => { - const { list, name } = tabProps; - const { dispatch, notices = [] } = this.props; - const lastItemId = notices[notices.length - 1].id; - dispatch({ - type: 'global/fetchMoreNotices', - payload: { - lastItemId, - type: name, - offset: list.length, - }, - }); - }; - render() { const { currentUser, - fetchingMoreNotices, fetchingNotices, - loadedAllNotices, onNoticeVisibleChange, onMenuClick, onNoticeClear, - skeletonCount, theme, } = this.props; const menu = ( @@ -110,11 +93,6 @@ export default class GlobalHeaderRight extends PureComponent { ); - const loadMoreProps = { - skeletonCount, - loadedAll: loadedAllNotices, - loading: fetchingMoreNotices, - }; const noticeData = this.getNoticeData(); const unreadMsg = this.getUnreadData(noticeData); let className = styles.right; @@ -155,44 +133,43 @@ export default class GlobalHeaderRight extends PureComponent { console.log(item, tabProps); // eslint-disable-line this.changeReadState(item, tabProps); }} + loading={fetchingNotices} locale={{ emptyText: formatMessage({ id: 'component.noticeIcon.empty' }), clear: formatMessage({ id: 'component.noticeIcon.clear' }), - loadedAll: formatMessage({ id: 'component.noticeIcon.loaded' }), - loadMore: formatMessage({ id: 'component.noticeIcon.loading-more' }), + viewMore: formatMessage({ id: 'component.noticeIcon.view-more' }), + notification: formatMessage({ id: 'component.globalHeader.notification' }), + message: formatMessage({ id: 'component.globalHeader.message' }), + event: formatMessage({ id: 'component.globalHeader.event' }), }} onClear={onNoticeClear} - onLoadMore={this.fetchMoreNotices} onPopupVisibleChange={onNoticeVisibleChange} - loading={fetchingNotices} + onViewMore={() => message.info('Click on view more')} clearClose > {currentUser.name ? ( diff --git a/src/components/GlobalHeader/index.d.ts b/src/components/GlobalHeader/index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..7d2fcf6e3c7ada8f269842152a955eaf510213bb --- /dev/null +++ b/src/components/GlobalHeader/index.d.ts @@ -0,0 +1,13 @@ +import React from 'react'; + +export interface GlobalHeaderProps { + collapsed?: boolean; + onCollapse?: (collapsed: boolean) => void; + isMobile?: boolean; + logo?: string; + onNoticeClear?: (type: string) => void; + onMenuClick?: ({ key: string }) => void; + onNoticeVisibleChange?: (b: boolean) => void; +} + +export default class GlobalHeader extends React.Component {} diff --git a/src/components/HeaderDropdown/index.d.ts b/src/components/HeaderDropdown/index.d.ts index e9dac7e532570e2f85a6a220d5d4ff9b97194927..a1fd50aa0f0deb8db3effed9e65e5e9c6a066286 100644 --- a/src/components/HeaderDropdown/index.d.ts +++ b/src/components/HeaderDropdown/index.d.ts @@ -1,2 +1,12 @@ -import * as React from 'react'; -export default class HeaderDropdown extends React.Component {} +import React from 'react'; +import { DropDownProps } from 'antd/lib/dropdown'; + +declare type OverlayFunc = () => React.ReactNode; + +export interface HeaderDropdownProps extends DropDownProps { + overlayClassName?: string; + overlay: React.ReactNode | OverlayFunc; + placement?: 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topCenter' | 'topRight' | 'bottomCenter'; +} + +export default class HeaderDropdown extends React.Component {} diff --git a/src/components/HeaderSearch/index.d.ts b/src/components/HeaderSearch/index.d.ts index d78fde471ccd522d821f77b790647f5620efdb7e..fcf7c11d2205b5a75ca6c797c8e936be00ddb2b7 100644 --- a/src/components/HeaderSearch/index.d.ts +++ b/src/components/HeaderSearch/index.d.ts @@ -1,5 +1,5 @@ -import * as React from 'react'; -export interface IHeaderSearchProps { +import React from 'react'; +export interface HeaderSearchProps { placeholder?: string; dataSource?: string[]; defaultOpen?: boolean; @@ -12,4 +12,4 @@ export interface IHeaderSearchProps { className?: string; } -export default class HeaderSearch extends React.Component {} +export default class HeaderSearch extends React.Component {} diff --git a/src/components/Login/LoginItem.d.ts b/src/components/Login/LoginItem.d.ts index bcfb73b86b75ee39f3f7b609e426ea4f1f6f2ce1..563e94e0489802e9f70b9e407776817f2d20bb25 100644 --- a/src/components/Login/LoginItem.d.ts +++ b/src/components/Login/LoginItem.d.ts @@ -1,11 +1,28 @@ -import * as React from 'react'; -export interface ILoginItemProps { +import React from 'react'; +import { WrappedFormUtils } from 'antd/es/form/Form'; +import ItemMap from './map'; +import { Omit } from 'antd/es/_util/type'; + +export type WrappedLoginItemProps = Omit; +export type LoginItemType = { [K in keyof typeof ItemMap]: React.FC }; + +export interface LoginItemProps { name?: string; rules?: any[]; style?: React.CSSProperties; - onGetCaptcha?: () => void; + onGetCaptcha?: (event?: MouseEvent) => void; placeholder?: string; buttonText?: React.ReactNode; + onPressEnter?: (e: any) => void; + countDown?: number; + getCaptchaButtonText?: string; + getCaptchaSecondText?: string; + updateActive: (activeItem: any) => void; + form: WrappedFormUtils; + type: string; + defaultValue?: string; + customprops?: any; + onChange?: (e: any) => void; } -export default class LoginItem extends React.Component {} +export default class LoginItem extends React.Component {} diff --git a/src/components/Login/LoginTab.d.ts b/src/components/Login/LoginTab.d.ts index db651f7b40c6194d1cd0cb8430736fc4d369e34d..c3f13ecb45cbe659d62d60f8bd3864681a336720 100644 --- a/src/components/Login/LoginTab.d.ts +++ b/src/components/Login/LoginTab.d.ts @@ -1,7 +1,11 @@ -import * as React from 'react'; +import React from 'react'; -export interface ILoginTabProps { +export interface LoginTabProps { key?: string; tab?: React.ReactNode; + tabUtil: { + addTab: (id: any) => void; + removeTab: (id: any) => void; + }; } -export default class LoginTab extends React.Component {} +export default class LoginTab extends React.Component {} diff --git a/src/components/Login/demo/basic.md b/src/components/Login/demo/basic.md index 5fbd0ca25448f92e964538c545edaf07d595ff27..05475384c0878cec7c5c13bf7d0678e58d1599be 100644 --- a/src/components/Login/demo/basic.md +++ b/src/components/Login/demo/basic.md @@ -18,65 +18,94 @@ class LoginDemo extends React.Component { notice: '', type: 'tab2', autoLogin: true, - } + }; onSubmit = (err, values) => { - console.log('value collected ->', { ...values, autoLogin: this.state.autoLogin }); + console.log('value collected ->', { + ...values, + autoLogin: this.state.autoLogin, + }); if (this.state.type === 'tab1') { - this.setState({ - notice: '', - }, () => { - if (!err && (values.username !== 'admin' || values.password !== '888888')) { - setTimeout(() => { - this.setState({ - notice: 'The combination of username and password is incorrect!', - }); - }, 500); - } - }); + this.setState( + { + notice: '', + }, + () => { + if ( + !err && + (values.username !== 'admin' || values.password !== '888888') + ) { + setTimeout(() => { + this.setState({ + notice: + 'The combination of username and password is incorrect!', + }); + }, 500); + } + }, + ); } - } + }; onTabChange = (key) => { this.setState({ type: key, }); - } + }; changeAutoLogin = (e) => { this.setState({ autoLogin: e.target.checked, }); - } + }; render() { return ( - - - { - this.state.notice && - - } - - - - - - console.log('Get captcha!')} name="captcha" /> - -
- Keep me logged in - Forgot password -
- Login -
- Other login methods - - - - Register -
-
+
+ + + {this.state.notice && ( + + )} + + + + + + console.log('Get captcha!')} + name="captcha" + /> + +
+ + Keep me logged in + + + Forgot password + +
+ Login +
+ Other login methods + + + + + Register + +
+
+
); } } @@ -85,6 +114,10 @@ ReactDOM.render(, mountNode); ```` diff --git a/src/components/PageHeader/demo/simple.md b/src/components/PageHeader/demo/simple.md deleted file mode 100644 index d0ad1f7d2f4e07208900b9e57891952cb7d39942..0000000000000000000000000000000000000000 --- a/src/components/PageHeader/demo/simple.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -order: 3 -title: Simple ---- - -简单的页头。 - -````jsx -import PageHeader from 'ant-design-pro/lib/PageHeader'; - -const breadcrumbList = [{ - title: '一级菜单', - href: '/', -}, { - title: '二级菜单', - href: '/', -}, { - title: '三级菜单', -}]; - -ReactDOM.render( -
- -
-, mountNode); -```` - - diff --git a/src/components/PageHeader/demo/standard.md b/src/components/PageHeader/demo/standard.md deleted file mode 100644 index 5c59c933c282b913b4bb56d69ee915feb56fc29f..0000000000000000000000000000000000000000 --- a/src/components/PageHeader/demo/standard.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -order: 1 -title: Standard ---- - -标准页头。 - -````jsx -import PageHeader from 'ant-design-pro/lib/PageHeader'; -import DescriptionList from 'ant-design-pro/lib/DescriptionList'; -import { Button, Menu, Dropdown, Icon, Row, Col } from 'antd'; - -const { Description } = DescriptionList; -const ButtonGroup = Button.Group; - -const description = ( - - 曲丽丽 - XX 服务 - 2017-07-07 - 12421 - -); - -const menu = ( - - 选项一 - 选项二 - 选项三 - -); - -const action = ( -
- - - - - - - - -
-); - -const extra = ( - - -
状态
-
待审批
- - -
订单金额
-
¥ 568.08
- -
-); - -const breadcrumbList = [{ - title: '一级菜单', - href: '/', -}, { - title: '二级菜单', - href: '/', -}, { - title: '三级菜单', -}]; - -const tabList = [{ - key: 'detail', - tab: '详情', -}, { - key: 'rule', - tab: '规则', -}]; - -function onTabChange(key) { - console.log(key); -} - -ReactDOM.render( -
- } - action={action} - content={description} - extraContent={extra} - breadcrumbList={breadcrumbList} - tabList={tabList} - tabActiveKey="detail" - onTabChange={onTabChange} - /> -
-, mountNode); -```` - - diff --git a/src/components/PageHeader/demo/structure.md b/src/components/PageHeader/demo/structure.md deleted file mode 100644 index 429eed6319f6f483da6ac724242a07f0626e3f0c..0000000000000000000000000000000000000000 --- a/src/components/PageHeader/demo/structure.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -order: 0 -title: Structure ---- - -基本结构,具备响应式布局功能,主要断点为 768px 和 576px,拖动窗口改变大小试试看。 - -````jsx -import PageHeader from 'ant-design-pro/lib/PageHeader'; - -const breadcrumbList = [{ - title: '面包屑', -}]; - -const tabList = [{ - key: '1', - tab: '页签一', -}, { - key: '2', - tab: '页签二', -}, { - key: '3', - tab: '页签三', -}]; - -ReactDOM.render( -
- Title
} - logo={
logo
} - action={
action
} - content={
content
} - extraContent={
extraContent
} - breadcrumbList={breadcrumbList} - tabList={tabList} - tabActiveKey="1" - /> -
-, mountNode); -```` - - diff --git a/src/components/PageHeader/index.d.ts b/src/components/PageHeader/index.d.ts deleted file mode 100644 index eacbb2de903681f1eee250d83c71e4642ca41d0d..0000000000000000000000000000000000000000 --- a/src/components/PageHeader/index.d.ts +++ /dev/null @@ -1,23 +0,0 @@ -import * as React from 'react'; -export interface IPageHeaderProps { - title?: React.ReactNode | string; - logo?: React.ReactNode | string; - action?: React.ReactNode | string; - content?: React.ReactNode; - extraContent?: React.ReactNode; - routes?: any[]; - params?: any; - breadcrumbList?: Array<{ title: React.ReactNode; href?: string }>; - tabList?: Array<{ key: string; tab: React.ReactNode }>; - tabActiveKey?: string; - tabDefaultActiveKey?: string; - onTabChange?: (key: string) => void; - tabBarExtraContent?: React.ReactNode; - linkElement?: React.ReactNode; - style?: React.CSSProperties; - home?: React.ReactNode; - wide?: boolean; - hiddenBreadcrumb?: boolean; -} - -export default class PageHeader extends React.Component {} diff --git a/src/components/PageHeader/index.js b/src/components/PageHeader/index.js deleted file mode 100644 index 17c1a7e28299bee95bd9181e2ed435a3fb0232e9..0000000000000000000000000000000000000000 --- a/src/components/PageHeader/index.js +++ /dev/null @@ -1,82 +0,0 @@ -import React, { PureComponent } from 'react'; -import { Tabs, Skeleton } from 'antd'; -import classNames from 'classnames'; -import styles from './index.less'; -import BreadcrumbView from './breadcrumb'; - -const { TabPane } = Tabs; -export default class PageHeader extends PureComponent { - onChange = key => { - const { onTabChange } = this.props; - if (onTabChange) { - onTabChange(key); - } - }; - - render() { - const { - title = '', - logo, - action, - content, - extraContent, - tabList, - className, - tabActiveKey, - tabDefaultActiveKey, - tabBarExtraContent, - loading = false, - wide = false, - hiddenBreadcrumb = false, - } = this.props; - - const clsString = classNames(styles.pageHeader, className); - const activeKeyProps = {}; - if (tabDefaultActiveKey !== undefined) { - activeKeyProps.defaultActiveKey = tabDefaultActiveKey; - } - if (tabActiveKey !== undefined) { - activeKeyProps.activeKey = tabActiveKey; - } - return ( -
-
- - {hiddenBreadcrumb ? null : } -
- {logo &&
{logo}
} -
-
-

{title}

- {action &&
{action}
} -
-
- {content &&
{content}
} - {extraContent &&
{extraContent}
} -
-
-
- {tabList && tabList.length ? ( - - {tabList.map(item => ( - - ))} - - ) : null} -
-
-
- ); - } -} diff --git a/src/components/PageHeader/index.less b/src/components/PageHeader/index.less deleted file mode 100644 index 81125bbd5b064e5eda41cc70616abfd0fd138f53..0000000000000000000000000000000000000000 --- a/src/components/PageHeader/index.less +++ /dev/null @@ -1,161 +0,0 @@ -@import '~antd/lib/style/themes/default.less'; - -.pageHeader { - padding: 16px 32px 0 32px; - background: @component-background; - border-bottom: @border-width-base @border-style-base @border-color-split; - .wide { - max-width: 1200px; - margin: auto; - } - .detail { - display: flex; - } - - .row { - display: flex; - width: 100%; - } - - .breadcrumb { - margin-bottom: 16px; - } - - .tabs { - margin: 0 0 0 -8px; - - :global { - // 1px 可以让选中效果显示完成 - .ant-tabs-bar { - margin-bottom: 1px; - border-bottom: none; - } - } - } - - .logo { - flex: 0 1 auto; - margin-right: 16px; - padding-top: 1px; - > img { - display: block; - width: 28px; - height: 28px; - border-radius: @border-radius-base; - } - } - - .title { - color: @heading-color; - font-weight: 500; - font-size: 20px; - } - - .action { - min-width: 266px; - margin-left: 56px; - - :global { - .ant-btn-group:not(:last-child), - .ant-btn:not(:last-child) { - margin-right: 8px; - } - - .ant-btn-group > .ant-btn { - margin-right: 0; - } - } - } - - .title, - .content { - flex: auto; - } - - .action, - .extraContent, - .main { - flex: 0 1 auto; - } - - .main { - width: 100%; - } - - .title, - .action { - margin-bottom: 16px; - } - - .logo, - .content, - .extraContent { - margin-bottom: 16px; - } - - .action, - .extraContent { - text-align: right; - } - - .extraContent { - min-width: 242px; - margin-left: 88px; - } -} - -@media screen and (max-width: @screen-xl) { - .pageHeader { - .extraContent { - margin-left: 44px; - } - } -} - -@media screen and (max-width: @screen-lg) { - .pageHeader { - .extraContent { - margin-left: 20px; - } - } -} - -@media screen and (max-width: @screen-md) { - .pageHeader { - .row { - display: block; - } - - .action, - .extraContent { - margin-left: 0; - text-align: left; - } - } -} - -@media screen and (max-width: @screen-sm) { - .pageHeader { - .detail { - display: block; - } - } -} - -@media screen and (max-width: @screen-xs) { - .pageHeader { - .action { - :global { - .ant-btn-group, - .ant-btn { - display: block; - margin-bottom: 8px; - } - .ant-btn-group > .ant-btn { - display: inline-block; - margin-bottom: 0; - } - } - } - } -} diff --git a/src/components/PageHeader/index.md b/src/components/PageHeader/index.md deleted file mode 100644 index 48543f5f4dcad7012984fddc045f35292ca7bc88..0000000000000000000000000000000000000000 --- a/src/components/PageHeader/index.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: PageHeader -subtitle: 页头 -cols: 1 -order: 11 ---- - -页头用来声明页面的主题,包含了用户所关注的最重要的信息,使用户可以快速理解当前页面是什么以及它的功能。 - -## API - -| 参数 | 说明 | 类型 | 默认值 | -|----------|------------------------------------------|-------------|-------| -| title | title 区域 | ReactNode | - | -| logo | logo区域 | ReactNode | - | -| action | 操作区,位于 title 行的行尾 | ReactNode | - | -| home | 默认的主页说明文字 | ReactNode | - | -| content | 内容区 | ReactNode | - | -| extraContent | 额外内容区,位于content的右侧 | ReactNode | - | -| breadcrumbList | 面包屑数据,配置了此属性时 `routes` `params` `location` `breadcrumbNameMap` 无效 | array<{title: ReactNode, href?: string}> | - | -| hiddenBreadcrumb |隐藏面包屑 | boolean | false | -| routes | 面包屑相关属性,router 的路由栈信息 | object[] | - | -| params | 面包屑相关属性,路由的参数 | object | - | -| location | 面包屑相关属性,当前的路由信息 | object | - | -| breadcrumbNameMap | 面包屑相关属性,路由的地址-名称映射表 | object | - | -| tabList | tab 标题列表 | array<{key: string, tab: ReactNode}> | - | -| tabActiveKey | 当前高亮的 tab 项 | string | - | -| tabDefaultActiveKey | 默认高亮的 tab 项 | string | 第一项 | -| wide | 是否定宽 | boolean | false | -| onTabChange | 切换面板的回调 | (key) => void | - | -| itemRender | 自定义节点方法 | (menuItem) => ReactNode | - | -| linkElement | 定义链接的元素,默认为 `a`,可传入 react-router 的 Link | string\|ReactElement | - | - -> 面包屑的配置方式有三种,一是直接配置 `breadcrumbList`,二是结合 `react-router@2` `react-router@3`,配置 `routes` 及 `params` 实现,类似 [面包屑 Demo](https://ant.design/components/breadcrumb-cn/#components-breadcrumb-demo-router),三是结合 `react-router@4`,配置 `location` `breadcrumbNameMap`,优先级依次递减,脚手架中使用最后一种。 对于后两种用法,你也可以将 `routes` `params` 及 `location` `breadcrumbNameMap` 放到 context 中,组件会自动获取。 diff --git a/src/components/PageHeader/index.test.js b/src/components/PageHeader/index.test.js deleted file mode 100644 index d22706e9c231db2c8c7e3e2981b5d26f04c86750..0000000000000000000000000000000000000000 --- a/src/components/PageHeader/index.test.js +++ /dev/null @@ -1,43 +0,0 @@ -import { getBreadcrumb } from './breadcrumb'; -import { urlToList } from '../_utils/pathTools'; - -const routerData = { - '/dashboard/analysis': { - name: '分析页', - }, - '/userinfo': { - name: '用户列表', - }, - '/userinfo/:id': { - name: '用户信息', - }, - '/userinfo/:id/addr': { - name: '收货订单', - }, -}; -describe('test getBreadcrumb', () => { - it('Simple url', () => { - expect(getBreadcrumb(routerData, '/dashboard/analysis').name).toEqual('分析页'); - }); - it('Parameters url', () => { - expect(getBreadcrumb(routerData, '/userinfo/2144').name).toEqual('用户信息'); - }); - it('The middle parameter url', () => { - expect(getBreadcrumb(routerData, '/userinfo/2144/addr').name).toEqual('收货订单'); - }); - it('Loop through the parameters', () => { - const urlNameList = urlToList('/userinfo/2144/addr').map( - url => getBreadcrumb(routerData, url).name - ); - expect(urlNameList).toEqual(['用户列表', '用户信息', '收货订单']); - }); - - it('a path', () => { - const urlNameList = urlToList('/userinfo').map(url => getBreadcrumb(routerData, url).name); - expect(urlNameList).toEqual(['用户列表']); - }); - it('Secondary path', () => { - const urlNameList = urlToList('/userinfo/2144').map(url => getBreadcrumb(routerData, url).name); - expect(urlNameList).toEqual(['用户列表', '用户信息']); - }); -}); diff --git a/src/components/PageHeaderWrapper/GridContent.d.ts b/src/components/PageHeaderWrapper/GridContent.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..a3d3a308f2aa5cd3688e8de8092d54cc3094572e --- /dev/null +++ b/src/components/PageHeaderWrapper/GridContent.d.ts @@ -0,0 +1,8 @@ +import React from 'react'; + +export interface GridContentProps { + contentWidth: string; + children: React.ReactNode; +} + +export default class GridContent extends React.Component {} diff --git a/src/components/PageHeaderWrapper/breadcrumb.js b/src/components/PageHeaderWrapper/breadcrumb.js new file mode 100644 index 0000000000000000000000000000000000000000..02fe66fd26530f68bd99e6a3c863f384a82e611d --- /dev/null +++ b/src/components/PageHeaderWrapper/breadcrumb.js @@ -0,0 +1,116 @@ +import React from 'react'; +import pathToRegexp from 'path-to-regexp'; +import Link from 'umi/link'; +import { FormattedMessage } from 'umi-plugin-react/locale'; +import { urlToList } from '../_utils/pathTools'; + +// 渲染Breadcrumb 子节点 +// Render the Breadcrumb child node +const itemRender = (route, params, routes, paths) => { + const last = routes.indexOf(route) === routes.length - 1; + return last || !route.component ? ( + {route.breadcrumbName} + ) : ( + {route.breadcrumbName} + ); +}; + +const renderItemLocal = item => { + if (item.locale) { + return ; + } + return item.name; +}; + +export const getBreadcrumb = (breadcrumbNameMap, url) => { + let breadcrumb = breadcrumbNameMap[url]; + if (!breadcrumb) { + Object.keys(breadcrumbNameMap).forEach(item => { + if (pathToRegexp(item).test(url)) { + breadcrumb = breadcrumbNameMap[item]; + } + }); + } + return breadcrumb || {}; +}; + +export const getBreadcrumbProps = props => { + const { routes, params, location, breadcrumbNameMap } = props; + return { + routes, + params, + routerLocation: location, + breadcrumbNameMap, + }; +}; + +// Generated according to props +const conversionFromProps = props => { + const { breadcrumbList } = props; + return breadcrumbList.map(item => { + const { title, href } = item; + return { + path: href, + breadcrumbName: title, + }; + }); +}; + +const conversionFromLocation = (routerLocation, breadcrumbNameMap, props) => { + const { home } = props; + // Convert the url to an array + const pathSnippets = urlToList(routerLocation.pathname); + // Loop data mosaic routing + const extraBreadcrumbItems = pathSnippets.map(url => { + const currentBreadcrumb = getBreadcrumb(breadcrumbNameMap, url); + if (currentBreadcrumb.inherited) { + return null; + } + const name = renderItemLocal(currentBreadcrumb); + const { hideInBreadcrumb } = currentBreadcrumb; + return name && !hideInBreadcrumb + ? { + path: url, + breadcrumbName: name, + } + : null; + }); + // Add home breadcrumbs to your head if defined + if (home) { + extraBreadcrumbItems.unshift({ + path: '/', + breadcrumbName: home, + }); + } + return extraBreadcrumbItems; +}; + +/** + * 将参数转化为面包屑 + * Convert parameters into breadcrumbs + */ +export const conversionBreadcrumbList = props => { + const { breadcrumbList } = props; + const { routes, params, routerLocation, breadcrumbNameMap } = getBreadcrumbProps(props); + if (breadcrumbList && breadcrumbList.length) { + return conversionFromProps(); + } + // 如果传入 routes 和 params 属性 + // If pass routes and params attributes + if (routes && params) { + return { + routes: routes.filter(route => route.breadcrumbName), + params, + itemRender, + }; + } + // 根据 location 生成 面包屑 + // Generate breadcrumbs based on location + if (routerLocation && routerLocation.pathname) { + return { + routes: conversionFromLocation(routerLocation, breadcrumbNameMap, props), + itemRender, + }; + } + return {}; +}; diff --git a/src/components/PageHeaderWrapper/index.d.ts b/src/components/PageHeaderWrapper/index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..21c8759b1563cecad6ee36e1d39a54247984489a --- /dev/null +++ b/src/components/PageHeaderWrapper/index.d.ts @@ -0,0 +1,12 @@ +import React from 'react'; +export interface ResultProps { + actions?: React.ReactNode; + className?: string; + description?: React.ReactNode; + extra?: React.ReactNode; + style?: React.CSSProperties; + title?: React.ReactNode; + type: 'success' | 'error'; +} + +export default class Result extends React.Component {} diff --git a/src/components/PageHeaderWrapper/index.js b/src/components/PageHeaderWrapper/index.js index cd745f66e8db1182493560238cc60762235dad09..7a766834c4ac39cd3628409d45fe3cd09bff1fe7 100644 --- a/src/components/PageHeaderWrapper/index.js +++ b/src/components/PageHeaderWrapper/index.js @@ -1,40 +1,103 @@ import React from 'react'; -import { FormattedMessage } from 'umi/locale'; +import { FormattedMessage } from 'umi-plugin-react/locale'; import Link from 'umi/link'; -import PageHeader from '@/components/PageHeader'; +import { PageHeader, Tabs, Typography } from 'antd'; import { connect } from 'dva'; +import classNames from 'classnames'; import GridContent from './GridContent'; import styles from './index.less'; import MenuContext from '@/layouts/MenuContext'; +import { conversionBreadcrumbList } from './breadcrumb'; -const PageHeaderWrapper = ({ children, contentWidth, wrapperClassName, top, ...restProps }) => ( -
- {top} - - {value => ( - } - {...value} - key="pageheader" - {...restProps} - linkElement={Link} - itemRender={item => { - if (item.locale) { - return ; - } - return item.title; +const { Title } = Typography; + +/** + * render Footer tabList + * In order to be compatible with the old version of the PageHeader + * basically all the functions are implemented. + */ +const renderFooter = ({ tabList, activeKeyProps, onTabChange, tabBarExtraContent }) => { + return tabList && tabList.length ? ( + { + if (onTabChange) { + onTabChange(key); + } + }} + tabBarExtraContent={tabBarExtraContent} + > + {tabList.map(item => ( + + ))} + + ) : null; +}; + +const PageHeaderWrapper = ({ + children, + contentWidth, + wrapperClassName, + top, + title, + content, + logo, + extraContent, + ...restProps +}) => { + return ( +
+ {top} + {title && content && ( + + {value => { + return ( + + {title} + + } + key="pageheader" + {...restProps} + breadcrumb={conversionBreadcrumbList({ + ...value, + ...restProps, + home: , + })} + className={styles.pageHeader} + linkElement={Link} + footer={renderFooter(restProps)} + > +
+ {logo &&
{logo}
} +
+
+ {content &&
{content}
} + {extraContent &&
{extraContent}
} +
+
+
+
+ ); }} - /> +
)} - - {children ? ( -
- {children} -
- ) : null} -
-); + {children ? ( +
+ {children} +
+ ) : null} +
+ ); +}; export default connect(({ setting }) => ({ contentWidth: setting.contentWidth, diff --git a/src/components/PageHeaderWrapper/index.less b/src/components/PageHeaderWrapper/index.less index 39a449657a98b039c29e6654fd117267cbb5283a..119585bbaef2af9a3a3f4dd90ce882a50a5a98e8 100644 --- a/src/components/PageHeaderWrapper/index.less +++ b/src/components/PageHeaderWrapper/index.less @@ -1,11 +1,110 @@ @import '~antd/lib/style/themes/default.less'; -.content { +.children-content { margin: 24px 24px 0; } -@media screen and (max-width: @screen-sm) { +.main { + :global { + .ant-page-header { + padding: 16px 32px 0; + background: #fff; + border-bottom: 1px solid #e8e8e8; + } + } + + .wide { + max-width: 1200px; + margin: auto; + } + .detail { + display: flex; + } + + .row { + display: flex; + width: 100%; + } + + .logo { + flex: 0 1 auto; + margin-right: 16px; + padding-top: 1px; + > img { + display: block; + width: 28px; + height: 28px; + border-radius: @border-radius-base; + } + } + + .title-content { + margin-bottom: 16px; + } + + @media screen and (max-width: @screen-sm) { + .content { + margin: 24px 0 0; + } + } + + .title, .content { - margin: 24px 0 0; + flex: auto; + } + + .extraContent, + .main { + flex: 0 1 auto; + } + + .main { + width: 100%; + } + + .title { + margin-bottom: 16px; + } + + .logo, + .content, + .extraContent { + margin-bottom: 16px; + } + + .extraContent { + min-width: 242px; + margin-left: 88px; + text-align: right; + } +} + +@media screen and (max-width: @screen-xl) { + .extraContent { + margin-left: 44px; + } +} + +@media screen and (max-width: @screen-lg) { + .extraContent { + margin-left: 20px; + } +} + +@media screen and (max-width: @screen-md) { + .row { + display: block; + } + + .action, + .extraContent { + margin-left: 0; + text-align: left; + } +} + +@media screen and (max-width: @screen-sm) { + .detail { + display: block; } } diff --git a/src/components/Result/index.d.ts b/src/components/Result/index.d.ts index 0c34c254014f49c0d7322acc1dab47cbd2fd52b4..21c8759b1563cecad6ee36e1d39a54247984489a 100644 --- a/src/components/Result/index.d.ts +++ b/src/components/Result/index.d.ts @@ -1,11 +1,12 @@ -import * as React from 'react'; -export interface IResultProps { - type: 'success' | 'error'; - title: React.ReactNode; +import React from 'react'; +export interface ResultProps { + actions?: React.ReactNode; + className?: string; description?: React.ReactNode; extra?: React.ReactNode; - actions?: React.ReactNode; style?: React.CSSProperties; + title?: React.ReactNode; + type: 'success' | 'error'; } -export default class Result extends React.Component {} +export default class Result extends React.Component {} diff --git a/src/components/SelectLang/index.d.ts b/src/components/SelectLang/index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..d2c53fa32b8c1fe1934d70835d09992ea8475d87 --- /dev/null +++ b/src/components/SelectLang/index.d.ts @@ -0,0 +1,7 @@ +import React from 'react'; + +export interface SelectLangProps { + className?: string; +} + +export default class SelectLang extends React.Component {} diff --git a/src/components/SelectLang/index.js b/src/components/SelectLang/index.js index f6abe2f279ef9c8c34463406f0c2a94503e6650d..3ce3fb8d3634b21f8471135e0a5da1db9c63d9d0 100644 --- a/src/components/SelectLang/index.js +++ b/src/components/SelectLang/index.js @@ -1,5 +1,5 @@ import React, { PureComponent } from 'react'; -import { formatMessage, setLocale, getLocale } from 'umi/locale'; +import { formatMessage, setLocale, getLocale } from 'umi-plugin-react/locale'; import { Menu, Icon } from 'antd'; import classNames from 'classnames'; import HeaderDropdown from '../HeaderDropdown'; diff --git a/src/components/SettingDrawer/BlockCheckbox.d.ts b/src/components/SettingDrawer/BlockCheckbox.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..1012294ec0d129e79c936ed8c9cdce681eaad980 --- /dev/null +++ b/src/components/SettingDrawer/BlockCheckbox.d.ts @@ -0,0 +1,9 @@ +import React from 'react'; + +export interface BlockChecboxProps { + value: string; + onChange: (key: string) => void; + list: any[]; +} + +export default class BlockChecbox extends React.Component {} diff --git a/src/components/SettingDrawer/ThemeColor.d.ts b/src/components/SettingDrawer/ThemeColor.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..17bc3e8dec81b3695fa21a459d826b9e5f220937 --- /dev/null +++ b/src/components/SettingDrawer/ThemeColor.d.ts @@ -0,0 +1,10 @@ +import React from 'react'; + +export interface TagProps { + color: string; + check: boolean; + className?: string; + onClick?: () => void; +} + +export default class ThemeColor extends React.Component {} diff --git a/src/components/SettingDrawer/ThemeColor.js b/src/components/SettingDrawer/ThemeColor.js index e5d66d4be5cb29a2684eff46734e06fba17d6923..9765b737e44a3a8168f5561306cdca56fc9c5e88 100644 --- a/src/components/SettingDrawer/ThemeColor.js +++ b/src/components/SettingDrawer/ThemeColor.js @@ -1,6 +1,6 @@ import React from 'react'; import { Tooltip, Icon } from 'antd'; -import { formatMessage } from 'umi/locale'; +import { formatMessage } from 'umi-plugin-react/locale'; import styles from './ThemeColor.less'; const Tag = ({ color, check, ...rest }) => ( diff --git a/src/components/SettingDrawer/index.d.ts b/src/components/SettingDrawer/index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..22273089eb54c481a581cd0e53635b05fbae8234 --- /dev/null +++ b/src/components/SettingDrawer/index.d.ts @@ -0,0 +1,24 @@ +import React from 'react'; +import { SiderTheme } from 'antd/es/Layout/Sider'; + +export interface SettingModelState { + navTheme: string | SiderTheme; + primaryColor: string; + layout: string; + contentWidth: string; + fixedHeader: boolean; + autoHideHeader: boolean; + fixSiderbar: boolean; + menu: { disableLocal: boolean }; + title: string; + pwa: boolean; + iconfontUrl: string; + colorWeak: boolean; +} + +export interface SettingDrawerProps { + setting?: SettingModelState; + dispatch?: (args: any) => void; +} + +export default class SettingDrawer extends React.Component {} diff --git a/src/components/SettingDrawer/index.js b/src/components/SettingDrawer/index.js index 4b279f593ec8cf032d00bb6783b01b001a4b016d..dcf341a0212ff943c7bafd7654f37b1cfbfa7470 100644 --- a/src/components/SettingDrawer/index.js +++ b/src/components/SettingDrawer/index.js @@ -1,6 +1,6 @@ -import React, { PureComponent } from 'react'; +import React, { Component } from 'react'; import { Select, message, Drawer, List, Switch, Divider, Icon, Button, Alert, Tooltip } from 'antd'; -import { formatMessage } from 'umi/locale'; +import { formatMessage } from 'umi-plugin-react/locale'; import { CopyToClipboard } from 'react-copy-to-clipboard'; import { connect } from 'dva'; import omit from 'omit.js'; @@ -23,7 +23,7 @@ const Body = ({ children, title, style }) => ( ); @connect(({ setting }) => ({ setting })) -class SettingDrawer extends PureComponent { +class SettingDrawer extends Component { state = { collapse: false, }; @@ -137,7 +137,7 @@ class SettingDrawer extends PureComponent { onClose={this.togglerContent} placement="right" handler={ -
+
} - onHandleClick={this.togglerContent} style={{ zIndex: 999, }} @@ -208,17 +207,22 @@ class SettingDrawer extends PureComponent { - this.changeSetting('colorWeak', checked)} - />, + this.changeSetting('colorWeak', checked)} + /> + ), + }, ]} - > - {formatMessage({ id: 'app.setting.weakmode' })} - + /> void; + isMobile?: boolean; + openKeys?: any; + theme?: SiderTheme; + mode?: MenuMode; + className?: string; + collapsed?: boolean; + handleOpenChange?: (openKeys: any[]) => void; + menuData?: any[]; + style?: React.CSSProperties; + onOpenChange?: (openKeys: string[]) => void; +} + +export default class BaseMenu extends React.Component {} diff --git a/src/components/SiderMenu/BaseMenu.js b/src/components/SiderMenu/BaseMenu.js index 6c8c7022219e552b1b5696c16e50eac0070ad052..9ab66ec3c03111edb1920d7d61e14dfef92838a2 100644 --- a/src/components/SiderMenu/BaseMenu.js +++ b/src/components/SiderMenu/BaseMenu.js @@ -33,13 +33,13 @@ export default class BaseMenu extends PureComponent { * 获得菜单子节点 * @memberof SiderMenu */ - getNavMenuItems = (menusData, parent) => { + getNavMenuItems = menusData => { if (!menusData) { return []; } return menusData .filter(item => item.name && !item.hideInMenu) - .map(item => this.getSubMenuOrItem(item, parent)) + .map(item => this.getSubMenuOrItem(item)) .filter(item => item); }; diff --git a/src/components/SiderMenu/SiderMenu.d.ts b/src/components/SiderMenu/SiderMenu.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..c18162a8df526f009d9575742eb24748d5e66afb --- /dev/null +++ b/src/components/SiderMenu/SiderMenu.d.ts @@ -0,0 +1,11 @@ +import React from 'react'; +import * as H from 'history'; +import { BaseMenuProps } from './BaseMenu'; +import { SiderTheme } from 'antd/es/Layout/Sider'; + +export interface SiderMenuProps extends BaseMenuProps { + logo?: string; + fixSiderbar?: boolean; +} + +export default class SiderMenu extends React.Component {} diff --git a/src/components/SiderMenu/index.d.ts b/src/components/SiderMenu/index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..383df9e11d934270685cadc6d6b38d3f2449f9bc --- /dev/null +++ b/src/components/SiderMenu/index.d.ts @@ -0,0 +1,13 @@ +import React from 'react'; +import { SiderTheme } from 'antd/es/Layout/Sider'; + +export interface SiderMenuProps { + isMobile: boolean; + menuData: any[]; + collapsed: boolean; + logo?: string; + theme?: SiderTheme; + onCollapse: (payload: boolean) => void; +} + +export default class SiderMenuWrapper extends React.Component {} diff --git a/src/components/StandardFormRow/index.d.ts b/src/components/StandardFormRow/index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..de06c9b8292f54373292089364281688eb8a95bc --- /dev/null +++ b/src/components/StandardFormRow/index.d.ts @@ -0,0 +1,11 @@ +import React from 'react'; + +export interface StandardFormRowProps { + title: string; + last?: boolean; + block?: boolean; + grid?: boolean; + style?: React.CSSProperties; +} + +export default class StandardFormRow extends React.Component {} diff --git a/src/components/StandardTable/index.d.ts b/src/components/StandardTable/index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..d9addeffae1b59d9a7ea2bbc1924e6c9543e94f5 --- /dev/null +++ b/src/components/StandardTable/index.d.ts @@ -0,0 +1,19 @@ +import React from 'react'; +import { PaginationConfig, SorterResult, TableCurrentDataSource } from 'antd/lib/table'; + +export interface StandardTableProps { + columns: any; + onSelectRow: (row: any) => void; + data: any; + rowKey?: string; + selectedRows: any[]; + onChange?: ( + pagination: PaginationConfig, + filters: Record, + sorter: SorterResult, + extra?: TableCurrentDataSource + ) => void; + loading?: boolean; +} + +export default class StandardTable extends React.Component {} diff --git a/src/components/TagSelect/TagSelectOption.d.ts b/src/components/TagSelect/TagSelectOption.d.ts index 366b297a7d3ff01c2a07a5c219b1b04558b8f8ab..3343d744ce1f5ae5e4ad252146e6c891447292ee 100644 --- a/src/components/TagSelect/TagSelectOption.d.ts +++ b/src/components/TagSelect/TagSelectOption.d.ts @@ -1,8 +1,12 @@ -import * as React from 'react'; +import React from 'react'; -export interface ITagSelectOptionProps { - value: string | number; +export interface TagSelectOptionProps { + value?: string | number; style?: React.CSSProperties; + checked?: boolean; + onChange?: (value: string | number, state: boolean) => void; } -export default class TagSelectOption extends React.Component {} +export default class TagSelectOption extends React.Component { + public static isTagSelectOption?: boolean; +} diff --git a/src/components/TagSelect/index.d.ts b/src/components/TagSelect/index.d.ts index 9de30263f1795b5cb323085b9eb3109d720c14cb..c225a86fe676fafbca8c4ff2f2ab9ebb06651994 100644 --- a/src/components/TagSelect/index.d.ts +++ b/src/components/TagSelect/index.d.ts @@ -1,16 +1,23 @@ -import * as React from 'react'; -import TagSelectOption from './TagSelectOption'; +import React from 'react'; +import TagSelectOption, { TagSelectOptionProps } from './TagSelectOption'; -export interface ITagSelectProps { +export interface TagSelectProps { onChange?: (value: string[]) => void; expandable?: boolean; value?: string[] | number[]; style?: React.CSSProperties; hideCheckAll?: boolean; - actionsText?: { expandText?: string; collapseText?: string; selectAllText?: string }; + actionsText?: { + expandText?: React.ReactNode; + collapseText?: React.ReactNode; + selectAllText?: React.ReactNode; + }; + className: string; + Option: TagSelectOptionProps; + children: React.ReactElement | Array>; } -export default class TagSelect extends React.Component { +export default class TagSelect extends React.Component { public static Option: typeof TagSelectOption; private children: | React.ReactElement diff --git a/src/components/TopNavHeader/index.d.ts b/src/components/TopNavHeader/index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..2d6631be39d999010264de2771e960f887eb4966 --- /dev/null +++ b/src/components/TopNavHeader/index.d.ts @@ -0,0 +1,25 @@ +import React from 'react'; +import { SiderTheme, CollapseType } from 'antd/es/Layout/Sider'; +import { MenuMode } from 'antd/es/menu'; + +export interface TopNavHeaderProps { + theme: SiderTheme; + contentWidth?: string; + menuData?: any[]; + logo?: string; + mode?: MenuMode; + flatMenuKeys?: any[]; + onCollapse?: (collapsed: boolean, type?: CollapseType) => void; + isMobile?: boolean; + openKeys?: any; + className?: string; + collapsed?: boolean; + handleOpenChange?: (openKeys: any[]) => void; + style?: React.CSSProperties; + onOpenChange?: (openKeys: string[]) => void; + onNoticeClear?: (type: string) => void; + onMenuClick?: ({ key: string }) => void; + onNoticeVisibleChange?: (b: boolean) => void; +} + +export default class TopNavHeader extends React.Component {} diff --git a/src/components/TopNavHeader/index.js b/src/components/TopNavHeader/index.js index 2d0e06561e0ef053594f157cd428b68874cc951d..0b6440e6d40f147fc083daf4fb9ce9a21eb60df0 100644 --- a/src/components/TopNavHeader/index.js +++ b/src/components/TopNavHeader/index.js @@ -13,7 +13,11 @@ export default class TopNavHeader extends PureComponent { static getDerivedStateFromProps(props) { return { - maxWidth: (props.contentWidth === 'Fixed' ? 1200 : window.innerWidth) - 280 - 165 - 40, + maxWidth: + (props.contentWidth === 'Fixed' && window.innerWidth > 1200 ? 1200 : window.innerWidth) - + 280 - + 120 - + 40, }; } diff --git a/src/components/Trend/index.d.ts b/src/components/Trend/index.d.ts index 7dc02010301cb3194c41d91b6bf01ac1dbdce1b8..a7775ae9b53ea3e5390f31a7df113ce4b6c3a5e6 100644 --- a/src/components/Trend/index.d.ts +++ b/src/components/Trend/index.d.ts @@ -1,10 +1,11 @@ -import * as React from 'react'; +import React from 'react'; export interface ITrendProps { colorful?: boolean; flag: 'up' | 'down'; style?: React.CSSProperties; reverseColor?: boolean; + className?: string; } export default class Trend extends React.Component {} diff --git a/src/defaultSettings.js b/src/defaultSettings.js index 4ba7eb390c49069b68053d9823f194a76f99391d..4e7e8018c5ed602b27f28cacff272e8f788383ca 100644 --- a/src/defaultSettings.js +++ b/src/defaultSettings.js @@ -11,8 +11,9 @@ module.exports = { }, title: 'Ant Design Pro', pwa: true, - // your iconfont Symbol Scrip Url + // Your custom iconfont Symbol script Url // eg://at.alicdn.com/t/font_1039637_btcrd5co4w.js - // 注意:如果需要图标多色,Iconfont图标项目里要进行批量去色处理 + // 注意:如果需要图标多色,Iconfont 图标项目里要进行批量去色处理 + // Usage: https://github.com/ant-design/ant-design-pro/pull/3517 iconfontUrl: '', }; diff --git a/src/e2e/baseLayout.e2e.js b/src/e2e/baseLayout.e2e.js index 74938719d5a2c071fba3f1e407ca18af1c36720e..70bb984df31a07311ef8a8f49df3554b56917400 100644 --- a/src/e2e/baseLayout.e2e.js +++ b/src/e2e/baseLayout.e2e.js @@ -5,13 +5,17 @@ const BASE_URL = `http://localhost:${process.env.PORT || 8000}`; function formatter(data) { return data .reduce((pre, item) => { - pre.push(item.path); + if (item.routes) { + pre.push(item.routes[0].path); + } else { + pre.push(item.path); + } return pre; }, []) .filter(item => item); } -describe('Homepage', async () => { +describe('Homepage', () => { const testPage = path => async () => { await page.goto(`${BASE_URL}${path}`); await page.waitForSelector('footer', { diff --git a/src/e2e/topMenu.e2e.js b/src/e2e/topMenu.e2e.js index 51ff9f35c632e3c6471b153b45f76b40e9a11cc9..d90983b9fef9d63ab2a64ce3c36ee7aed66622f5 100644 --- a/src/e2e/topMenu.e2e.js +++ b/src/e2e/topMenu.e2e.js @@ -4,6 +4,7 @@ describe('Homepage', () => { beforeAll(async () => { jest.setTimeout(1000000); }); + it('topmenu should have footer', async () => { const params = '/form/basic-form?navTheme=light&layout=topmenu'; await page.goto(`${BASE_URL}${params}`); diff --git a/src/global.js b/src/global.js index bebe4829c63d4f4a47f4aa7bf649f23e2deef90d..a0ecf97a027f3c687d6856e67d80817a002c94e7 100644 --- a/src/global.js +++ b/src/global.js @@ -1,6 +1,6 @@ import React from 'react'; import { notification, Button, message } from 'antd'; -import { formatMessage } from 'umi/locale'; +import { formatMessage } from 'umi-plugin-react/locale'; import defaultSettings from './defaultSettings'; window.React = React; diff --git a/src/layouts/BasicLayout.js b/src/layouts/BasicLayout.js index 338968764205ff7caed5c6042f0e5c459f237e5d..3b4ae35c112b1f6d5ab5c2be017e85a7dd6c5973 100644 --- a/src/layouts/BasicLayout.js +++ b/src/layouts/BasicLayout.js @@ -4,15 +4,11 @@ import DocumentTitle from 'react-document-title'; import { connect } from 'dva'; import { ContainerQuery } from 'react-container-query'; import classNames from 'classnames'; -import pathToRegexp from 'path-to-regexp'; import Media from 'react-media'; -import Authorized from '@/utils/Authorized'; import logo from '../assets/logo.svg'; import Footer from './Footer'; import Header from './Header'; import Context from './MenuContext'; -import Exception403 from '../pages/Exception/403'; -import PageLoading from '@/components/PageLoading'; import SiderMenu from '@/components/SiderMenu'; import getPageTitle from '@/utils/getPageTitle'; import styles from './BasicLayout.less'; @@ -49,10 +45,7 @@ const query = { class BasicLayout extends React.Component { componentDidMount() { - const { - dispatch, - route: { routes, authority }, - } = this.props; + const { dispatch } = this.props; dispatch({ type: 'user/fetchCurrent', }); @@ -61,7 +54,6 @@ class BasicLayout extends React.Component { }); dispatch({ type: 'menu/getMenuData', - payload: { routes, authority }, }); } @@ -73,29 +65,6 @@ class BasicLayout extends React.Component { }; } - getRouteAuthority = (pathname, routeData) => { - const routes = routeData.slice(); // clone - - const getAuthority = (routeDatas, path) => { - let authorities; - routeDatas.forEach(route => { - // check partial route - if (pathToRegexp(`${route.path}(.*)`).test(path)) { - if (route.authority) { - authorities = route.authority; - } - // is exact route? - if (!pathToRegexp(route.path).test(path) && route.routes) { - authorities = getAuthority(route.routes, path); - } - } - }); - return authorities; - }; - - return getAuthority(routes, pathname); - }; - getLayoutStyle = () => { const { fixSiderbar, isMobile, collapsed, layout } = this.props; if (fixSiderbar && layout !== 'topmenu' && !isMobile) { @@ -132,12 +101,10 @@ class BasicLayout extends React.Component { isMobile, menuData, breadcrumbNameMap, - route: { routes }, fixedHeader, } = this.props; const isTop = PropsLayout === 'topmenu'; - const routerConfig = this.getRouteAuthority(pathname, routes); const contentStyle = !fixedHeader ? { paddingTop: 0 } : {}; const layout = ( @@ -165,9 +132,7 @@ class BasicLayout extends React.Component { {...this.props} /> - }> - {children} - + {children}