diff --git a/README.md b/README.md index eb6f03fe..b926cb09 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,54 @@ -# Ionic React Conference Demo App +# Ionic React Conference Application + + +This application is purely a kitchen-sink demo of the Ionic Framework and React. + +**There is not an actual Ionic Conference at this time.** This project is just to show off Ionic components in a real-world application. + +## Table of Contents +- [Getting Started](#getting-started) +- [App Preview](#app-preview) + +## Getting Started + +* [Download the installer](https://nodejs.org/) for Node LTS. +* Install the ionic CLI globally: `npm install -g ionic` +* Clone this repository: `git clone https://github.com/ionic-team/ionic-react-conference-app.git`. +* Run `npm install` from the project root. +* Run `ionic serve` in a terminal from the project root. +* Profit. :tada: + +## App Preview + +### [Menu](https://github.com/ionic-team/ionic-conference-app/blob/master/src/app/pages/menu/menu.html) + +| Material Design | iOS | +| -----------------| -----| +| ![Android Menu](/resources/screenshots/android-menu.png) | ![iOS Menu](/resources/screenshots/ios-menu.png) | + + +### [Schedule Page](https://github.com/ionic-team/ionic-conference-app/blob/master/src/app/pages/schedule/schedule.html) + +| Material Design | iOS | +| -----------------| -----| +| ![Android Schedule](/resources/screenshots/android-schedule.png) | ![iOS Schedule](/resources/screenshots/ios-schedule.png) | + +### [Speakers Page](https://github.com/ionic-team/ionic-conference-app/blob/master/src/app/pages/speaker-list/speaker-list.html) + +| Material Design | iOS | +| -----------------| -----| +| ![Android Speakers](/resources/screenshots/android-speakers.png) | ![iOS Speakers](/resources/screenshots/ios-speakers.png) | + +### [Speaker Detail Page](https://github.com/ionic-team/ionic-conference-app/blob/master/src/app/pages/speaker-detail/speaker-detail.html) + +| Material Design | iOS | +| -----------------| -----| +| ![Android Speaker Detail](/resources/screenshots/android-speaker-detail.png) | ![iOS Speaker Detail](/resources/screenshots/ios-speaker-detail.png) | + +### [About Page](https://github.com/ionic-team/ionic-conference-app/blob/master/src/app/pages/about/about.html) + +| Material Design | iOS | +| -----------------| -----| +| ![Android About](/resources/screenshots/android-about.png) | ![iOS About](/resources/screenshots/ios-about.png) | + -You can see a live demo here. (https://ionic-react-conference-app.firebaseapp.com/) \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 60ce3d73..3342ae50 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1042,27 +1042,28 @@ } }, "@ionic/core": { - "version": "4.11.4", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-4.11.4.tgz", - "integrity": "sha512-g3UbS52eW5/bVvxk8Rj0TCvo8reJV54rw2FoxwVpKA+COTeNW3sAytdy+fJyAXmj/w3/5XipkvWXRxHdcvFnWw==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.0.5.tgz", + "integrity": "sha512-k0O5V/3sFB55E+hKSqio1iDfwibZdlI97PuaI4PcGQDytzUCyGTlGAZn6iLi82NZqBRWWLOpwy+8N/cySiTWKg==", "requires": { - "ionicons": "^4.6.3", + "ionicons": "^5.0.1", "tslib": "^1.10.0" } }, "@ionic/react": { - "version": "4.11.4", - "resolved": "https://registry.npmjs.org/@ionic/react/-/react-4.11.4.tgz", - "integrity": "sha512-2y6cfxYSNXuiZYciN81jLRWh3TVO/S4nbcQWqMSwnwCfvd+iOnuJ9he8aJSZGAnnN+gysvmh7oPMkrzC8UZqSw==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ionic/react/-/react-5.0.5.tgz", + "integrity": "sha512-zto/u25D0mYaK2+cVpYZsHHseG0W9idtPEopjCGcCKuSCFBl8nQvwootz2x3VyVN53NbsqP6BfYkztE8aPzJuA==", "requires": { - "@ionic/core": "4.11.4", + "@ionic/core": "5.0.5", + "ionicons": "^5.0.1", "tslib": "*" } }, "@ionic/react-router": { - "version": "4.11.4", - "resolved": "https://registry.npmjs.org/@ionic/react-router/-/react-router-4.11.4.tgz", - "integrity": "sha512-4m08/s0qj4zAxi/vYG36+rYOu4Jnih5OaCFUjI1MQcXnDEOnaKQoGvQdcJ21+EoyvIG5wgcBpupBTRiEQlC9nQ==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@ionic/react-router/-/react-router-5.0.5.tgz", + "integrity": "sha512-P+VSCleOX2NA8GoCj57/3i/EBjQjML7Ww0E5Nk8yIvFGOB4fY1csZeRDhCmxZq2IdlIHfTBLFJnKNG0HXX2dfw==", "requires": { "tslib": "*" } @@ -1454,9 +1455,9 @@ "dev": true }, "@types/history": { - "version": "4.7.3", - "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.3.tgz", - "integrity": "sha512-cS5owqtwzLN5kY+l+KgKdRJ/Cee8tlmQoGQuIE9tWnSmS3JMKzmxo2HIAk2wODMifGwO20d62xZQLYz+RLfXmw==" + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.5.tgz", + "integrity": "sha512-wLD/Aq2VggCJXSjxEwrMafIP51Z+13H78nXIX0ABEuIGhmB5sNGbR113MOKo+yfw+RDo1ZU3DM6yfnnRF/+ouw==" }, "@types/istanbul-lib-coverage": { "version": "2.0.1", @@ -1514,35 +1515,35 @@ "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==" }, "@types/react": { - "version": "16.9.4", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.4.tgz", - "integrity": "sha512-ItGNmJvQ0IvWt8rbk5PLdpdQhvBVxAaXI9hDlx7UMd8Ie1iMIuwMNiKeTfmVN517CdplpyXvA22X4zm4jGGZnw==", + "version": "16.9.23", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.23.tgz", + "integrity": "sha512-SsGVT4E7L2wLN3tPYLiF20hmZTPGuzaayVunfgXzUn1x4uHVsKH6QDJQ/TdpHqwsTLd4CwrmQ2vOgxN7gE24gw==", "requires": { "@types/prop-types": "*", "csstype": "^2.2.0" } }, "@types/react-dom": { - "version": "16.9.1", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.1.tgz", - "integrity": "sha512-1S/akvkKr63qIUWVu5IKYou2P9fHLb/P2VAwyxVV85JGaGZTcUniMiTuIqM3lXFB25ej6h+CYEQ27ERVwi6eGA==", + "version": "16.9.5", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.5.tgz", + "integrity": "sha512-BX6RQ8s9D+2/gDhxrj8OW+YD4R+8hj7FEM/OJHGNR0KipE1h1mSsf39YeyC81qafkq+N3rU3h3RFbLSwE5VqUg==", "requires": { "@types/react": "*" } }, "@types/react-router": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.1.tgz", - "integrity": "sha512-S7SlFAPb7ZKr6HHMW0kLHGcz8pyJSL0UdM+JtlWthDqKUWwr7E6oPXuHgkofDI8dKCm16slg8K8VCf5pZJquaA==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.4.tgz", + "integrity": "sha512-PZtnBuyfL07sqCJvGg3z+0+kt6fobc/xmle08jBiezLS8FrmGeiGkJnuxL/8Zgy9L83ypUhniV5atZn/L8n9MQ==", "requires": { "@types/history": "*", "@types/react": "*" } }, "@types/react-router-dom": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-4.3.5.tgz", - "integrity": "sha512-eFajSUASYbPHg2BDM1G8Btx+YqGgvROPIg6sBhl3O4kbDdYXdFdfrgQFf/pcBuQVObjfT9AL/dd15jilR5DIEA==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.1.3.tgz", + "integrity": "sha512-pCq7AkOvjE65jkGS5fQwQhvUp4+4PVD9g39gXLZViP2UqFiFzsEpB3PKf0O6mdbKsewSK8N14/eegisa/0CwnA==", "requires": { "@types/history": "*", "@types/react": "*", @@ -4259,9 +4260,9 @@ } }, "csstype": { - "version": "2.6.6", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.6.tgz", - "integrity": "sha512-RpFbQGUE74iyPgvr46U9t1xoQBM8T4BL8SxrN66Le2xYAPSaDJJKeztV3awugusb3g3G9iL8StmkBBXhcbbXhg==" + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.9.tgz", + "integrity": "sha512-xz39Sb4+OaTsULgUERcCk+TJj8ylkL4aSVDQiX/ksxbELSqwkgt4d4RD7fovIdgJGSuNYqwZEiVjYY5l0ask+Q==" }, "currently-unhandled": { "version": "0.4.1", @@ -4320,11 +4321,6 @@ } } }, - "date-fns": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.6.0.tgz", - "integrity": "sha512-F55YxqRdEfP/eYQmQjLN798v0AwLjmZ8nMBjdQvNwEE3N/zWVrlkkqT+9seBlPlsbkybG4JmWg3Ee3dIV9BcGQ==" - }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -6927,9 +6923,9 @@ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==" }, "ionicons": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-4.6.3.tgz", - "integrity": "sha512-cgP+VIr2cTJpMfFyVHTerq6n2jeoiGboVoe3GlaAo5zoSBDAEXORwUZhv6m+lCyxlsHCS3nqPUE+MKyZU71t8Q==" + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.0.1.tgz", + "integrity": "sha512-P9GHr7pgCJcG211W0wute49NZ9AvJZvFJf4OwYybakjX6j7tu0q5t5HNWn9bcb9YjI7SxBblJg8iqQ1Yb59DXw==" }, "ip": { "version": "1.1.5", diff --git a/package.json b/package.json index 4318977e..5e63bd2d 100644 --- a/package.json +++ b/package.json @@ -4,16 +4,15 @@ "private": true, "dependencies": { "@capacitor/core": "1.3.0", - "@ionic/react": "^4.11.4", - "@ionic/react-router": "^4.11.4", + "@ionic/react": "^5.0.5", + "@ionic/react-router": "^5.0.5", "@types/jest": "24.0.18", "@types/node": "12.7.5", - "@types/react": "^16.9.2", - "@types/react-dom": "^16.9.0", - "@types/react-router": "^5.0.3", - "@types/react-router-dom": "^4.3.1", - "date-fns": "^2.6.0", - "ionicons": "^4.6.3", + "@types/react": "^16.9.23", + "@types/react-dom": "^16.9.5", + "@types/react-router": "^5.1.4", + "@types/react-router-dom": "^5.1.3", + "ionicons": "^5.0.1", "node-sass": "^4.13.0", "react": "^16.9.0", "react-dom": "^16.9.0", diff --git a/public/assets/data/data.json b/public/assets/data/data.json new file mode 100644 index 00000000..7599c727 --- /dev/null +++ b/public/assets/data/data.json @@ -0,0 +1,467 @@ +{ + "schedule": [ + { + "date": "2047-05-17", + "groups": [ + { + "time": "8:00 am", + "sessions": [ + { + "name": "Breakfast", + "timeStart": "8:00 am", + "timeEnd": "9:00 am", + "location": "Dining Hall", + "tracks": ["Food"], + "id": "1" + } + ] + }, + { + "time": "9:15 am", + "sessions": [ + { + "name": "Getting Started with Ionic", + "location": "Hall 2", + "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", + "speakerNames": ["Ted Turtle"], + "timeStart": "9:30 am", + "timeEnd": "9:45 am", + "tracks": ["Ionic"], + "id": "2" + }, + { + "name": "Ionic Tooling", + "location": "Executive Ballroom", + "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", + "speakerNames": ["Rachel Rabbit"], + "timeStart": "9:45 am", + "timeEnd": "10:00 am", + "tracks": ["Tooling"], + "id": "3" + }, + { + "name": "University of Ionic", + "location": "Hall 3", + "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", + "speakerNames": ["Ellie Elephant"], + "timeStart": "9:15 am", + "timeEnd": "9:30 am", + "tracks": ["Ionic"], + "id": "4" + } + ] + }, + { + "time": "10:00 am", + "sessions": [ + { + "name": "Migrating to Ionic", + "location": "Hall 1", + "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", + "speakerNames": ["Eva Eagle", "Lionel Lion"], + "timeStart": "10:00 am", + "timeEnd": "10:15 am", + "tracks": ["Ionic"], + "id": "5" + }, + { + "name": "What's New in Angular", + "location": "Hall 3", + "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", + "speakerNames": ["Rachel Rabbit"], + "timeStart": "10:15 am", + "timeEnd": "10:30 am", + "tracks": ["Angular"], + "id": "6" + }, + { + "name": "The Evolution of Ionicons", + "location": "Hall 2", + "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", + "speakerNames": ["Isabella Iguana", "Eva Eagle"], + "timeStart": "10:15 am", + "timeEnd": "10:30 am", + "tracks": ["Design"], + "id": "7" + }, + { + "name": "Ionic Pro", + "location": "Grand Ballroom A", + "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", + "speakerNames": ["Charlie Cheetah"], + "timeStart": "10:45 am", + "timeEnd": "11:00 am", + "tracks": ["Services"], + "id": "8" + } + ] + }, + { + "time": "11:00 am", + "sessions": [ + { + "name": "Ionic Workshop", + "location": "Hall 1", + "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", + "speakerNames": ["Karl Kitten", "Lionel Lion"], + "timeStart": "11:00 am", + "timeEnd": "11:45 am", + "tracks": ["Workshop"], + "id": "9" + }, + { + "name": "Community Interaction", + "location": "Hall 3", + "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", + "speakerNames": ["Lionel Lion", "Gino Giraffe"], + "timeStart": "11:30 am", + "timeEnd": "11:50 am", + "tracks": ["Communication"], + "id": "10" + }, + { + "name": "Navigation in Ionic", + "location": "Grand Ballroom A", + "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", + "speakerNames": ["Rachel Rabbit", "Eva Eagle"], + "timeStart": "11:30 am", + "timeEnd": "12:00 pm", + "tracks": ["Navigation"], + "id": "11" + } + ] + }, + { + "time": "12:00 pm", + "sessions": [ + { + "name": "Lunch", + "location": "Dining Hall", + "description": "Come grab lunch with all the Ionic fanatics and talk all things Ionic", + "timeStart": "12:00 pm", + "timeEnd": "1:00 pm", + "tracks": ["Food"], + "id": "12" + } + ] + }, + { + "time": "1:00 pm", + "sessions": [ + { + "name": "Ionic in the Enterprise", + "location": "Hall 1", + "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", + "speakerNames": ["Paul Puppy"], + "timeStart": "1:00 pm", + "timeEnd": "1:15 pm", + "tracks": ["Communication"], + "id": "13" + }, + { + "name": "Ionic Worldwide", + "location": "Hall 1", + "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", + "speakerNames": ["Gino Giraffe"], + "timeStart": "1:15 pm", + "timeEnd": "1:30 pm", + "tracks": ["Communication"], + "id": "14" + }, + { + "name": "The Ionic Package", + "location": "Grand Ballroom B", + "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", + "speakerNames": ["Molly Mouse", "Burt Bear"], + "timeStart": "1:30 pm", + "timeEnd": "2:00 pm", + "tracks": ["Services"], + "id": "15" + } + ] + }, + { + "time": "2:00 pm", + "sessions": [ + { + "name": "Push Notifications in Ionic", + "location": "Hall 2", + "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", + "speakerNames": ["Burt Bear", "Charlie Cheetah"], + "timeStart": "2:00 pm", + "timeEnd": "2:30 pm", + "tracks": ["Services"], + "id": "16" + }, + { + "name": "Ionic Documentation", + "location": "Grand Ballroom B", + "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", + "speakerNames": ["Donald Duck"], + "timeStart": "2:30 pm", + "timeEnd": "2:45 pm", + "tracks": ["Documentation"], + "id": "17" + }, + { + "name": "UX in Ionic", + "location": "Hall 3", + "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", + "speakerNames": ["Isabella Iguana", "Ellie Elephant"], + "timeStart": "2:45 pm", + "timeEnd": "3:00 pm", + "tracks": ["Design"], + "id": "18" + } + ] + }, + { + "time": "3:00", + "sessions": [ + { + "name": "Angular Directives in Ionic", + "location": "Hall 1", + "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", + "speakerNames": ["Ted Turtle"], + "timeStart": "3:00 pm", + "timeEnd": "3:30 pm", + "tracks": ["Angular"], + "id": "19" + }, + { + "name": "Mobile States", + "location": "Hall 2", + "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", + "speakerNames": ["Rachel Rabbit"], + "timeStart": "3:30 pm", + "timeEnd": "3:45 pm", + "tracks": ["Navigation"], + "id": "20" + } + ] + } + ] + } + ], + + "speakers": [ + { + "name": "Burt Bear", + "profilePic": "/assets/img/speakers/bear.jpg", + "instagram": "ionicframework", + "twitter": "ionicframework", + "about": "Burt is a Bear. Burt's interests include poetry, dashing space heroes, and lions.", + "title": "Software Engineer", + "location": "Everywhere", + "email": "burt@example.com", + "phone": "+1-541-754-3010", + "id": "1" + }, + { + "name": "Charlie Cheetah", + "profilePic": "/assets/img/speakers/cheetah.jpg", + "instagram": "ionicframework", + "twitter": "ionicframework", + "about": "Charlie is a Cheetah. Charlie's interests include country music, plush animals, pyrotechnics, and skeletons.", + "title": "Software Engineer", + "location": "Everywhere", + "email": "charlie@example.com", + "phone": "+1-541-754-3010", + "id": "2" + }, + { + "name": "Donald Duck", + "profilePic": "/assets/img/speakers/duck.jpg", + "instagram": "ionicframework", + "twitter": "ionicframework", + "about": "Donald is a Duck. Donald's interests include carpentry, superheroes, merpeople, and glam rock.", + "title": "Software Engineer", + "location": "Everywhere", + "email": "donald@example.com", + "phone": "+1-541-754-3010", + "id": "3" + }, + { + "name": "Eva Eagle", + "profilePic": "/assets/img/speakers/eagle.jpg", + "instagram": "ionicframework", + "twitter": "ionicframework", + "about": "Eva is an Eagle. Eva's interests include ants, seashells, and cupcakes.", + "title": "Developer Advocate", + "location": "Everywhere", + "email": "eva@example.com", + "phone": "+1-541-754-3010", + "id": "4" + }, + { + "name": "Ellie Elephant", + "profilePic": "/assets/img/speakers/elephant.jpg", + "instagram": "ionicframework", + "twitter": "ionicframework", + "about": "Ellie is an Elephant. Ellie's interests include pocket watches, pool, hand fans, and ninjas.", + "title": "Software Engineer", + "location": "Everywhere", + "email": "ellie@example.com", + "phone": "+1-541-754-3010", + "id": "5" + }, + { + "name": "Gino Giraffe", + "profilePic": "/assets/img/speakers/giraffe.jpg", + "instagram": "ionicframework", + "twitter": "ionicframework", + "about": "Gino is a Giraffe. Gino's interests include candy-making, unicorns, and birdhouses.", + "title": "Software Engineer", + "location": "Everywhere", + "email": "gino@example.com", + "phone": "+1-541-754-3010", + "id": "6" + }, + { + "name": "Isabella Iguana", + "profilePic": "/assets/img/speakers/iguana.jpg", + "instagram": "ionicframework", + "twitter": "ionicframework", + "about": "Isabella is an Iguana. Isabella's interests include crystals, architecture, and candle-making.", + "title": "Software Engineer", + "location": "Everywhere", + "email": "isabella@example.com", + "phone": "+1-541-754-3010", + "id": "7" + }, + { + "name": "Karl Kitten", + "profilePic": "/assets/img/speakers/kitten.jpg", + "instagram": "ionicframework", + "twitter": "ionicframework", + "about": "Karl is a Kitten. Karl's interests include skiing, jewelry, and needlepoint.", + "title": "Developer Advocate", + "location": "Everywhere", + "email": "karl@example.com", + "phone": "+1-541-754-3010", + "id": "8" + }, + { + "name": "Lionel Lion", + "profilePic": "/assets/img/speakers/lion.jpg", + "instagram": "ionicframework", + "twitter": "ionicframework", + "about": "Lionel is a Lion. Lionel's interests include lizards and mathematics.", + "title": "Developer Advocate", + "location": "Everywhere", + "email": "lionel@example.com", + "phone": "+1-541-754-3010", + "id": "9" + }, + { + "name": "Molly Mouse", + "profilePic": "/assets/img/speakers/mouse.jpg", + "instagram": "ionicframework", + "twitter": "ionicframework", + "about": "Molly is a Mouse. Molly's interests include werewolves and magic.", + "title": "Software Engineer", + "location": "Everywhere", + "email": "molly@example.com", + "phone": "+1-541-754-3010", + "id": "10" + }, + { + "name": "Paul Puppy", + "profilePic": "/assets/img/speakers/puppy.jpg", + "instagram": "ionicframework", + "twitter": "ionicframework", + "about": "Paul is a Puppy. Paul's interests include maps, whales, and dragons.", + "title": "Software Engineer", + "location": "Everywhere", + "email": "paul@example.com", + "phone": "+1-541-754-3010", + "id": "11" + }, + { + "name": "Rachel Rabbit", + "profilePic": "/assets/img/speakers/rabbit.jpg", + "instagram": "ionicframework", + "twitter": "ionicframework", + "about": "Rachel is a Rabbit. Rachel's interests include clowns, skeletons, and yo-yos.", + "title": "Senior Software Engineer", + "location": "Everywhere", + "email": "rachel@example.com", + "phone": "+1-541-754-3010", + "id": "12" + }, + { + "name": "Ted Turtle", + "profilePic": "/assets/img/speakers/turtle.jpg", + "instagram": "ionicframework", + "twitter": "ionicframework", + "about": "Ted is a Turtle. Ted's interests include butterflies, skiing, and cupcakes.", + "title": "Software Engineer", + "location": "Everywhere", + "email": "ted@example.com", + "phone": "+1-541-754-3010", + "id": "13" + } + ], + + "map": [ + { + "name": "Monona Terrace Convention Center", + "lat": 43.071584, + "lng": -89.38012, + "center": true + }, + { + "name": "Ionic HQ", + "lat": 43.074395, + "lng": -89.381056 + }, + { + "name": "Afterparty - Brocach Irish Pub", + "lat": 43.07336, + "lng": -89.38335 + } + ], + + "tracks": [ + { + "name": "Angular", + "icon": "logo-angular" + }, + { + "name": "Documentation", + "icon": "document" + }, + { + "name": "Food", + "icon": "restaurant" + }, + { + "name": "Ionic", + "icon": "logo-ionic" + }, + { + "name": "Tooling", + "icon": "hammer" + }, + { + "name": "Design", + "icon": "color-palette" + }, + { + "name": "Services", + "icon": "cog" + }, + { + "name": "Workshop", + "icon": "construct" + }, + { + "name": "Communication", + "icon": "call" + }, + { + "name": "Navigation", + "icon": "compass" + } + ] +} \ No newline at end of file diff --git a/public/assets/data/sessions.json b/public/assets/data/sessions.json deleted file mode 100755 index 4ea11e2c..00000000 --- a/public/assets/data/sessions.json +++ /dev/null @@ -1,172 +0,0 @@ -[{ - "id": 1, - "dateTimeStart": "2047-05-17T08:00", - "dateTimeEnd": "2047-05-17T09:00", - "name": "Breakfast", - "location": "Main hallway", - "description": "Come grab breakfast with all the Ionic fanatics and talk all things Ionic", - "speakerIds": [], - "tracks": ["Food"] -}, { - "id": 2, - "dateTimeStart": "2047-05-17T09:00", - "dateTimeEnd": "2047-05-17T09:30", - "name": "Introduction to Appcamp.io", - "location": "Room 2203", - "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", - "speakerIds": [5], - "tracks": ["Ionic"] -}, { - "id": 3, - "dateTimeStart": "2047-05-17T09:30", - "dateTimeEnd": "2047-05-17T09:45", - "name": "Getting started with Ionic", - "location": "Room 2202", - "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", - "speakerIds": [13], - "tracks": ["Ionic"] -}, { - "id": 4, - "dateTimeStart": "2047-05-17T09:45", - "dateTimeEnd": "2047-05-17T10:00", - "name": "Tooling for Ionic", - "location": "Room 2201", - "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", - "speakerIds": [12], - "tracks": ["Tooling"] -}, { - "id": 5, - "dateTimeStart": "2047-05-17T10:00", - "dateTimeEnd": "2047-05-17T10:15", - "name": "Migrating to Ionic2", - "location": "Room 2201", - "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", - "speakerIds": [4, 9], - "tracks": ["Ionic"] -}, { - "id": 6, - "dateTimeStart": "2047-05-17T10:15", - "dateTimeEnd": "2047-05-17T10:30", - "name": "The evolution of Ionicons", - "location": "Room 2202", - "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", - "speakerIds": [7, 4], - "tracks": ["Design"] -}, { - "id": 7, - "dateTimeStart": "2047-05-17T10:30", - "dateTimeEnd": "2047-05-17T11:00", - "name": "Ionic.io Services", - "location": "Room 2202", - "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", - "speakerIds": [2], - "tracks": ["Services"] -}, { - "id": 8, - "dateTimeStart": "2047-05-17T11:00", - "dateTimeEnd": "2047-05-17T11:45", - "name": "Ionic Workshop", - "location": "Room 2201", - "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", - "speakerIds": [8, 9], - "tracks": ["Workshop"] -}, { - "id": 9, - "dateTimeStart": "2047-05-17T11:30", - "dateTimeEnd": "2047-05-17T11:50", - "name": "Community Interaction", - "location": "Room 2203", - "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", - "speakerIds": [9, 6], - "tracks": ["Communication"] -}, { - "id": 10, - "dateTimeStart": "2047-05-17T11:30", - "dateTimeEnd": "2047-05-17T12:00", - "name": "Navigation in Ionic", - "location": "Room 2203", - "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", - "speakerIds": [12, 4], - "tracks": ["Navigation"] -}, { - "id": 11, - "dateTimeStart": "2047-05-17T12:00", - "dateTimeEnd": "2047-05-17T13:00", - "name": "Lunch", - "location": "Auditorium", - "description": "Come grab lunch with all the Ionic fanatics and talk all things Ionic", - "speakerIds": [], - "tracks": ["Food"] -}, { - "id": 12, - "dateTimeStart": "2047-05-17T13:00", - "dateTimeEnd": "2047-05-17T13:15", - "name": "Ionic in the Enterprise", - "location": "Room 2201", - "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", - "speakerIds": [11], - "tracks": ["Communication"] -}, { - "id": 13, - "dateTimeStart": "2047-05-17T13:15", - "dateTimeEnd": "2047-05-17T13:30", - "name": "Ionic Worldwide", - "location": "Room 2201", - "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", - "speakerIds": [6], - "tracks": ["Communication"] -}, { - "id": 14, - "dateTimeStart": "2047-05-17T13:30", - "dateTimeEnd": "2047-05-17T14:00", - "name": "The Ionic package service", - "location": "Room 2203", - "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", - "speakerIds": [10, 1], - "tracks": ["Services"] -}, { - "id": 15, - "dateTimeStart": "2047-05-17T14:00", - "dateTimeEnd": "2047-05-17T14:30", - "name": "Push Notifications in Ionic", - "location": "Room 2202", - "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", - "speakerIds": [1, 2], - "tracks": ["Services"] -}, { - "id": 16, - "dateTimeStart": "2047-05-17T14:30", - "dateTimeEnd": "2047-05-17T14:45", - "name": "Ionic Documentation", - "location": "Room 2202", - "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", - "speakerIds": [3], - "tracks": ["Documentation"] -}, { - "id": 17, - "dateTimeStart": "2047-05-17T14:45", - "dateTimeEnd": "2047-05-17T15:00", - "name": "UX planning in Ionic", - "location": "Room 2203", - "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", - "speakerIds": [7, 5], - "tracks": ["Design"] -}, { - "id": 18, - "dateTimeStart": "2047-05-17T15:00", - "dateTimeEnd": "2047-05-17T15:30", - "name": "Directives in Ionic", - "location": "Room 2201", - "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", - "speakerIds": [13], - "tracks": ["Angular"] -}, { - "id": 19, - "dateTimeStart": "2047-05-17T15:30", - "dateTimeEnd": "2047-05-17T15:45", - "name": "Mobile States", - "location": "Room 2202", - "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", - "speakerIds": [12], - "tracks": ["Navigation"] -}] diff --git a/public/assets/data/speakers.json b/public/assets/data/speakers.json deleted file mode 100644 index 1bc98b5f..00000000 --- a/public/assets/data/speakers.json +++ /dev/null @@ -1,118 +0,0 @@ -[{ - "id": 1, - "name": "Burt Bear", - "profilePic": "/assets/img/speakers/bear.jpg", - "twitter": "ionicframework", - "about": "Burt is a Bear.", - "location": "Everywhere", - "email": "burt@example.com", - "phone": "+1-541-754-3010" -}, { - "id": 2, - "name": "Charlie Cheetah", - "profilePic": "/assets/img/speakers/cheetah.jpg", - "twitter": "ionicframework", - "about": "Charlie is a Cheetah.", - "location": "Everywhere", - "email": "charlie@example.com", - "phone": "+1-541-754-3010" -}, { - "id": 3, - "name": "Donald Duck", - "profilePic": "/assets/img/speakers/duck.jpg", - "twitter": "ionicframework", - "about": "Donald is a Duck.", - "location": "Everywhere", - "email": "donald@example.com", - "phone": "+1-541-754-3010" -}, { - "id": 4, - "name": "Eva Eagle", - "profilePic": "/assets/img/speakers/eagle.jpg", - "twitter": "ionicframework", - "about": "Eva is an Eagle.", - "location": "Everywhere", - "email": "eva@example.com", - "phone": "+1-541-754-3010" -}, { - "id": 5, - "name": "Ellie Elephant", - "profilePic": "/assets/img/speakers/elephant.jpg", - "twitter": "ionicframework", - "about": "Ellie is an Elephant.", - "location": "Everywhere", - "email": "ellie@example.com", - "phone": "+1-541-754-3010" -}, { - "id": 6, - "name": "Gino Giraffe", - "profilePic": "/assets/img/speakers/giraffe.jpg", - "twitter": "ionicframework", - "about": "Gino is a Giraffe.", - "location": "Everywhere", - "email": "gino@example.com", - "phone": "+1-541-754-3010" -}, { - "id": 7, - "name": "Isabella Iguana", - "profilePic": "/assets/img/speakers/iguana.jpg", - "twitter": "ionicframework", - "about": "Isabella is an Iguana.", - "location": "Everywhere", - "email": "isabella@example.com", - "phone": "+1-541-754-3010" -}, { - "id": 8, - "name": "Karl Kitten", - "profilePic": "/assets/img/speakers/kitten.jpg", - "twitter": "ionicframework", - "about": "Karl is a Kitten.", - "location": "Everywhere", - "email": "karl@example.com", - "phone": "+1-541-754-3010" -}, { - "id": 9, - "name": "Lionel Lion", - "profilePic": "/assets/img/speakers/lion.jpg", - "twitter": "ionicframework", - "about": "Lionel is a Lion.", - "location": "Everywhere", - "email": "lionel@example.com", - "phone": "+1-541-754-3010" -}, { - "id": 10, - "name": "Molly Mouse", - "profilePic": "/assets/img/speakers/mouse.jpg", - "twitter": "ionicframework", - "about": "Molly is a Mouse.", - "location": "Everywhere", - "email": "molly@example.com", - "phone": "+1-541-754-3010" -}, { - "id": 11, - "name": "Paul Puppy", - "profilePic": "/assets/img/speakers/puppy.jpg", - "twitter": "ionicframework", - "about": "Paul is a Puppy.", - "location": "Everywhere", - "email": "paul@example.com", - "phone": "+1-541-754-3010" -}, { - "id": 12, - "name": "Rachel Rabbit", - "profilePic": "/assets/img/speakers/rabbit.jpg", - "twitter": "ionicframework", - "about": "Rachel is a Rabbit.", - "location": "Everywhere", - "email": "rachel@example.com", - "phone": "+1-541-754-3010" -}, { - "id": 13, - "name": "Ted Turtle", - "profilePic": "/assets/img/speakers/turtle.jpg", - "twitter": "ionicframework", - "about": "Ted is a Turtle.", - "location": "Everywhere", - "email": "ted@example.com", - "phone": "+1-541-754-3010" -}] diff --git a/public/assets/img/about/austin.jpg b/public/assets/img/about/austin.jpg new file mode 100644 index 00000000..b4eb3297 Binary files /dev/null and b/public/assets/img/about/austin.jpg differ diff --git a/public/assets/img/about/chicago.jpg b/public/assets/img/about/chicago.jpg new file mode 100644 index 00000000..b982b652 Binary files /dev/null and b/public/assets/img/about/chicago.jpg differ diff --git a/public/assets/img/about/madison.jpg b/public/assets/img/about/madison.jpg new file mode 100644 index 00000000..c46fbf06 Binary files /dev/null and b/public/assets/img/about/madison.jpg differ diff --git a/public/assets/img/about/seattle.jpg b/public/assets/img/about/seattle.jpg new file mode 100644 index 00000000..4c5946ac Binary files /dev/null and b/public/assets/img/about/seattle.jpg differ diff --git a/public/assets/img/speaker-background.png b/public/assets/img/speaker-background.png new file mode 100644 index 00000000..220634e2 Binary files /dev/null and b/public/assets/img/speaker-background.png differ diff --git a/public/index.html b/public/index.html index 0fa45402..4ffbafc8 100644 --- a/public/index.html +++ b/public/index.html @@ -2,7 +2,7 @@ - Ionic App + Ionic Conference App @@ -17,13 +17,13 @@ - +
- + diff --git a/resources/screenshots/android-about.png b/resources/screenshots/android-about.png new file mode 100644 index 00000000..4a742f22 Binary files /dev/null and b/resources/screenshots/android-about.png differ diff --git a/resources/screenshots/android-menu.png b/resources/screenshots/android-menu.png new file mode 100644 index 00000000..22277643 Binary files /dev/null and b/resources/screenshots/android-menu.png differ diff --git a/resources/screenshots/android-schedule.png b/resources/screenshots/android-schedule.png new file mode 100644 index 00000000..7c7629ab Binary files /dev/null and b/resources/screenshots/android-schedule.png differ diff --git a/resources/screenshots/android-speaker-detail.png b/resources/screenshots/android-speaker-detail.png new file mode 100644 index 00000000..9aca16f0 Binary files /dev/null and b/resources/screenshots/android-speaker-detail.png differ diff --git a/resources/screenshots/android-speakers.png b/resources/screenshots/android-speakers.png new file mode 100644 index 00000000..b59ab00d Binary files /dev/null and b/resources/screenshots/android-speakers.png differ diff --git a/resources/screenshots/ios-about.png b/resources/screenshots/ios-about.png new file mode 100644 index 00000000..86a8e814 Binary files /dev/null and b/resources/screenshots/ios-about.png differ diff --git a/resources/screenshots/ios-menu.png b/resources/screenshots/ios-menu.png new file mode 100644 index 00000000..4803f318 Binary files /dev/null and b/resources/screenshots/ios-menu.png differ diff --git a/resources/screenshots/ios-schedule.png b/resources/screenshots/ios-schedule.png new file mode 100644 index 00000000..c581de19 Binary files /dev/null and b/resources/screenshots/ios-schedule.png differ diff --git a/resources/screenshots/ios-speaker-detail.png b/resources/screenshots/ios-speaker-detail.png new file mode 100644 index 00000000..761a9ec5 Binary files /dev/null and b/resources/screenshots/ios-speaker-detail.png differ diff --git a/resources/screenshots/ios-speakers.png b/resources/screenshots/ios-speakers.png new file mode 100644 index 00000000..b938fd1b Binary files /dev/null and b/resources/screenshots/ios-speakers.png differ diff --git a/src/App.tsx b/src/App.tsx index e9028dda..d947408c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -34,7 +34,7 @@ import Signup from './pages/Signup'; import Support from './pages/Support'; import Tutorial from './pages/Tutorial'; import HomeOrTutorial from './components/HomeOrTutorial'; -import { Session } from "./models/Session"; +import { Schedule } from "./models/Schedule"; const App: React.FC = () => { return ( @@ -45,8 +45,8 @@ const App: React.FC = () => { }; interface StateProps { - darkMode: boolean, - sessions: Session[], + darkMode: boolean; + schedule: Schedule; } interface DispatchProps { @@ -58,7 +58,7 @@ interface DispatchProps { interface IonicAppProps extends StateProps, DispatchProps { } -const IonicApp: React.FC = ({ darkMode, sessions, setIsLoggedIn, setUsername, loadConfData, loadUserData }) => { +const IonicApp: React.FC = ({ darkMode, schedule, setIsLoggedIn, setUsername, loadConfData, loadUserData }) => { useEffect(() => { loadUserData(); @@ -67,7 +67,7 @@ const IonicApp: React.FC = ({ darkMode, sessions, setIsLoggedIn, }, []); return ( - sessions.length === 0 ? ( + schedule.groups.length === 0 ? (
) : ( @@ -100,7 +100,7 @@ export default App; const IonicAppConnected = connect<{}, StateProps, DispatchProps>({ mapStateToProps: (state) => ({ darkMode: state.user.darkMode, - sessions: state.data.sessions + schedule: state.data.schedule }), mapDispatchToProps: { loadConfData, loadUserData, setIsLoggedIn, setUsername }, component: IonicApp diff --git a/src/components/Menu.css b/src/components/Menu.css new file mode 100644 index 00000000..c533f2ea --- /dev/null +++ b/src/components/Menu.css @@ -0,0 +1,87 @@ +ion-menu ion-content { + --padding-top: 20px; + --padding-bottom: 20px; + + --background: var(--ion-item-background, var(--ion-background-color, #fff)); +} + +/* Remove background transitions for switching themes */ +ion-menu ion-item { + --transition: none; +} + +ion-item.selected { + --color: var(--ion-color-primary); +} + +/* + * Material Design Menu +*/ +ion-menu.md ion-list { + padding: 20px 0; +} + +ion-menu.md ion-list-header { + padding-left: 18px; + padding-right: 18px; + + text-transform: uppercase; + letter-spacing: .1em; + font-weight: 450; +} + +ion-menu.md ion-item { + --padding-start: 18px; + + margin-right: 10px; + + border-radius: 0 50px 50px 0; + + font-weight: 500; +} + +ion-menu.md ion-item.selected { + --background: rgba(var(--ion-color-primary-rgb), 0.14); +} + +ion-menu.md ion-item.selected ion-icon { + color: var(--ion-color-primary); +} + +ion-menu.md ion-list-header, +ion-menu.md ion-item ion-icon { + color: var(--ion-color-step-650, #5f6368); +} + +ion-menu.md ion-list:not(:last-of-type) { + border-bottom: 1px solid var(--ion-color-step-150, #d7d8da); +} + + +/* + * iOS Menu +*/ +ion-menu.ios ion-list-header { + padding-left: 16px; + padding-right: 16px; + + margin-bottom: 8px; +} + +ion-menu.ios ion-list { + padding: 20px 0 0; +} + +ion-menu.ios ion-item { + --padding-start: 16px; + --min-height: 50px; +} + +ion-menu.ios ion-item ion-icon { + font-size: 24px; + color: #73849a; +} + +ion-menu.ios ion-item.selected ion-icon { + color: var(--ion-color-primary); +} diff --git a/src/components/Menu.tsx b/src/components/Menu.tsx index 3673b73b..1429b43a 100644 --- a/src/components/Menu.tsx +++ b/src/components/Menu.tsx @@ -1,29 +1,20 @@ -import { - IonContent, - IonHeader, - IonIcon, - IonItem, - IonLabel, - IonList, - IonListHeader, - IonMenu, - IonMenuToggle, - IonTitle, - IonToolbar, - IonToggle -} from '@ionic/react'; -import { calendar, contacts, hammer, help, informationCircle, logIn, logOut, map, person, personAdd } from 'ionicons/icons'; import React, { useState } from 'react'; +import { RouteComponentProps, withRouter, useLocation } from 'react-router'; + +import { IonContent, IonIcon, IonItem, IonLabel, IonList, IonListHeader, IonMenu, IonMenuToggle, IonToggle } from '@ionic/react'; +import { calendarOutline, hammer, moonOutline, help, informationCircleOutline, logIn, logOut, mapOutline, peopleOutline, person, personAdd } from 'ionicons/icons'; + import { connect } from '../data/connect'; -import { RouteComponentProps, withRouter } from 'react-router'; import { setDarkMode } from '../data/user/user.actions'; +import './Menu.css' + const routes = { appPages: [ - { title: 'Schedule', path: '/tabs/schedule', icon: calendar }, - { title: 'Speakers', path: '/tabs/speakers', icon: contacts }, - { title: 'Map', path: '/tabs/map', icon: map }, - { title: 'About', path: '/tabs/about', icon: informationCircle } + { title: 'Schedule', path: '/tabs/schedule', icon: calendarOutline }, + { title: 'Speakers', path: '/tabs/speakers', icon: peopleOutline }, + { title: 'Map', path: '/tabs/map', icon: mapOutline }, + { title: 'About', path: '/tabs/about', icon: informationCircleOutline } ], loggedInPages: [ { title: 'Account', path: '/account', icon: person }, @@ -40,12 +31,13 @@ const routes = { interface Pages { title: string, path: string, - icon: { ios: string, md: string }, + icon: string, routerDirection?: string } interface StateProps { darkMode: boolean; isAuthenticated: boolean; + menuEnabled: boolean; } interface DispatchProps { @@ -54,15 +46,15 @@ interface DispatchProps { interface MenuProps extends RouteComponentProps, StateProps, DispatchProps { } -const Menu: React.FC = ({ darkMode, history, isAuthenticated, setDarkMode }) => { - const [disableMenu, setDisableMenu] = useState(false); +const Menu: React.FC = ({ darkMode, history, isAuthenticated, setDarkMode, menuEnabled }) => { + const location = useLocation(); function renderlistItems(list: Pages[]) { return list .filter(route => !!route.path) .map(p => ( - + {p.title} @@ -71,37 +63,30 @@ const Menu: React.FC = ({ darkMode, history, isAuthenticated, setDark } return ( - - - - Menu - - - - - Navigate + + + + Conference {renderlistItems(routes.appPages)} - + Account {isAuthenticated ? renderlistItems(routes.loggedInPages) : renderlistItems(routes.loggedOutPages)} + + + Dark Mode + setDarkMode(!darkMode)} /> + - + Tutorial - { - setDisableMenu(true); + { history.push('/tutorial'); }}> Show Tutorial - - - Dark Theme - setDarkMode(!darkMode)} /> - - ); @@ -110,7 +95,8 @@ const Menu: React.FC = ({ darkMode, history, isAuthenticated, setDark export default connect<{}, StateProps, {}>({ mapStateToProps: (state) => ({ darkMode: state.user.darkMode, - isAuthenticated: state.user.isLoggedin + isAuthenticated: state.user.isLoggedin, + menuEnabled: state.data.menuEnabled }), mapDispatchToProps: ({ setDarkMode diff --git a/src/components/SessionList.tsx b/src/components/SessionList.tsx index afb1f9e3..cde543a1 100644 --- a/src/components/SessionList.tsx +++ b/src/components/SessionList.tsx @@ -1,15 +1,13 @@ import { IonItemDivider, IonItemGroup, IonLabel, IonList, IonListHeader, IonAlert, AlertButton } from '@ionic/react'; import React, { useState, useCallback } from 'react'; -import { Session } from '../models/Session'; +import { Schedule, Session } from '../models/Schedule'; import SessionListItem from './SessionListItem'; -import { SessionGroup } from '../models/SessionGroup'; -import { Time } from '../components/Time'; import { connect } from '../data/connect'; import { addFavorite, removeFavorite } from '../data/sessions/sessions.actions'; interface OwnProps { - sessionGroups: SessionGroup[] - listType: 'all' | 'favorites' + schedule: Schedule; + listType: 'all' | 'favorites'; hide: boolean; } @@ -24,7 +22,7 @@ interface DispatchProps { interface SessionListProps extends OwnProps, StateProps, DispatchProps { }; -const SessionList: React.FC = ({ addFavorite, removeFavorite, favoriteSessions, hide, sessionGroups, listType }) => { +const SessionList: React.FC = ({ addFavorite, removeFavorite, favoriteSessions, hide, schedule, listType }) => { const [showAlert, setShowAlert] = useState(false); const [alertHeader, setAlertHeader] = useState(''); @@ -36,7 +34,7 @@ const SessionList: React.FC = ({ addFavorite, removeFavorite, setShowAlert(true); }, []); - if (sessionGroups.length === 0 && !hide) { + if (schedule.groups.length === 0 && !hide) { return ( @@ -49,11 +47,11 @@ const SessionList: React.FC = ({ addFavorite, removeFavorite, return ( <> - {sessionGroups.map((group, index: number) => ( + {schedule.groups.map((group, index: number) => ( - {group.sessions.map((session: Session, sessionIndex: number) => ( @@ -80,7 +78,7 @@ const SessionList: React.FC = ({ addFavorite, removeFavorite, ); }; -export default connect({ +export default connect({ mapStateToProps: (state) => ({ favoriteSessions: state.data.favorites }), diff --git a/src/components/SessionListFilter.css b/src/components/SessionListFilter.css index f4ef7d3c..94045a19 100644 --- a/src/components/SessionListFilter.css +++ b/src/components/SessionListFilter.css @@ -1,4 +1,32 @@ +/* + * Material Design + */ -.filter-icon { - margin: 7px 16px 7px 0; -} \ No newline at end of file +.session-list-filter .md ion-toolbar ion-button { + text-transform: capitalize; + letter-spacing: 0; +} + +.session-list-filter .md ion-checkbox { + --background-checked: transparent; + --border-color: transparent; + --border-color-checked: transparent; + --checkmark-color: var(--ion-color-primary); +} + +.session-list-filter .md ion-list { + background: inherit; +} + + +/* + * iOS + */ + +.session-list-filter .ios ion-list-header { + margin-top: 10px; +} + +.session-list-filter .ios ion-label { + color: var(--ion-color-primary); +} diff --git a/src/components/SessionListFilter.tsx b/src/components/SessionListFilter.tsx index b0766eb6..cc126b4a 100644 --- a/src/components/SessionListFilter.tsx +++ b/src/components/SessionListFilter.tsx @@ -1,7 +1,11 @@ import React from 'react'; -import { IonHeader, IonToolbar, IonButtons, IonButton, IonTitle, IonContent, IonList, IonListHeader, IonItem, IonLabel, IonToggle, IonFooter, IonIcon } from '@ionic/react'; + +import { getMode } from '@ionic/core'; +import { IonHeader, IonToolbar, IonButtons, IonButton, IonTitle, IonContent, IonList, IonListHeader, IonItem, IonLabel, IonCheckbox, IonFooter, IonIcon } from '@ionic/react'; import { logoAngular, call, document, logoIonic, hammer, restaurant, cog, colorPalette, construct, compass } from 'ionicons/icons'; + import './SessionListFilter.css' + import { connect } from '../data/connect'; import { updateFilteredTracks } from '../data/sessions/sessions.actions'; @@ -21,6 +25,7 @@ interface DispatchProps { type SessionListFilterProps = OwnProps & StateProps & DispatchProps; const SessionListFilter: React.FC = ({ allTracks, filteredTracks, onDismissModal, updateFilteredTracks }) => { + const ios = getMode() === 'ios'; const toggleTrackFilter = (track: string) => { if (filteredTracks.indexOf(track) > -1) { @@ -53,45 +58,60 @@ const SessionListFilter: React.FC = ({ allTracks, filter return ( <> - + + + { ios && + Cancel + } + { !ios && + Reset + } + + Filter Sessions - + + Done - - + + Tracks + {allTracks.map((track, index) => ( - + { ios && + + } {track} - toggleTrackFilter(track)} checked={filteredTracks.indexOf(track) !== -1} - color="success" + color="primary" value={track} - > + > ))} - - - - Deselect All - - - Select All - - - + { ios && + + + + Deselect All + + + Select All + + + + } ); }; diff --git a/src/components/SessionListItem.tsx b/src/components/SessionListItem.tsx index 0dc0b18f..87f3385d 100644 --- a/src/components/SessionListItem.tsx +++ b/src/components/SessionListItem.tsx @@ -1,7 +1,6 @@ -import React, { useRef, useState } from 'react'; -import { IonItemSliding, IonAlert, IonItem, IonLabel, IonItemOptions, IonItemOption, AlertButton } from '@ionic/react'; -import { Time } from './Time'; -import { Session } from '../models/Session'; +import React, { useRef } from 'react'; +import { IonItemSliding, IonItem, IonLabel, IonItemOptions, IonItemOption, AlertButton } from '@ionic/react'; +import { Session } from '../models/Schedule'; interface SessionListItemProps { session: Session; @@ -14,7 +13,7 @@ interface SessionListItemProps { const SessionListItem: React.FC = ({ isFavorite, onAddFavorite, onRemoveFavorite, onShowAlert, session, listType }) => { const ionItemSlidingRef = useRef(null) - + const dismissAlert = () => { ionItemSlidingRef.current && ionItemSlidingRef.current.close(); } @@ -59,8 +58,8 @@ const SessionListItem: React.FC = ({ isFavorite, onAddFavo

{session.name}

-

diff --git a/src/components/ShareSocialFab.tsx b/src/components/ShareSocialFab.tsx index 1161d864..24204759 100644 --- a/src/components/ShareSocialFab.tsx +++ b/src/components/ShareSocialFab.tsx @@ -1,16 +1,16 @@ import { IonLoading, IonFab, IonFabButton, IonIcon, IonFabList } from "@ionic/react" -import { share, logoVimeo, logoGoogleplus, logoTwitter, logoFacebook } from "ionicons/icons" +import { shareSocial, logoVimeo, logoInstagram, logoTwitter, logoFacebook } from "ionicons/icons" import React, { useState } from "react" const ShareSocialFab: React.FC = () => { const [loadingMessage, setLoadingMessage] = useState('') const [showLoading, setShowLoading] = useState(false); - const openSocial = (network: string) => { + const openSocial = (network: string) => { setLoadingMessage(`Posting to ${network}`); setShowLoading(true); }; - + return( <> { /> - + openSocial('Vimeo')}> - openSocial('Google+')}> - + openSocial('Instagram')}> + openSocial('Twitter')}> diff --git a/src/components/SpeakerItem.tsx b/src/components/SpeakerItem.tsx index 71a6db8d..cf00d1b2 100644 --- a/src/components/SpeakerItem.tsx +++ b/src/components/SpeakerItem.tsx @@ -1,9 +1,8 @@ -import React, { useState } from 'react'; -import { Session } from '../models/Session'; +import React from 'react'; +import { Session } from '../models/Schedule'; import { Speaker } from '../models/Speaker'; -import { IonCard, IonCardHeader, IonItem, IonAvatar, IonCardContent, IonList, IonRow, IonCol, IonButton, IonIcon, IonActionSheet } from '@ionic/react'; -import { logoTwitter, shareAlt, chatboxes } from 'ionicons/icons'; -import { ActionSheetButton } from '@ionic/core'; +import { IonCard, IonCardHeader, IonItem, IonLabel, IonAvatar, IonCardContent, IonList } from '@ionic/react'; + interface SpeakerItemProps { speaker: Speaker; @@ -11,113 +10,38 @@ interface SpeakerItemProps { } const SpeakerItem: React.FC = ({ speaker, sessions }) => { - const [showActionSheet, setShowActionSheet] = useState(false); - const [actionSheetButtons, setActionSheetButtons] = useState([]); - const [actionSheetHeader, setActionSheetHeader] = useState(''); - - function openSpeakerShare(speaker: Speaker) { - setActionSheetButtons([ - { - text: 'Copy Link', - handler: () => { - console.log('Copy Link clicked'); - } - }, - { - text: 'Share via ...', - handler: () => { - console.log('Share via clicked'); - } - }, - { - text: 'Cancel', - role: 'cancel', - handler: () => { - console.log('Cancel clicked'); - } - } - ]); - setActionSheetHeader(`Share ${speaker.name}`); - setShowActionSheet(true); - } - - function openContact(speaker: Speaker) { - setActionSheetButtons([ - { - text: `Email ( ${speaker.email} )`, - handler: () => { - window.open('mailto:' + speaker.email); - } - }, - { - text: `Call ( ${speaker.phone} )`, - handler: () => { - window.open('tel:' + speaker.phone); - } - } - ]); - setActionSheetHeader(`Share ${speaker.name}`); - setShowActionSheet(true); - } - return ( <> - + Speaker profile pic - {speaker.name} + +

{speaker.name}

+

{speaker.title}

+
- - + + {sessions.map(session => ( - -

{session.name}

+ + +

{session.name}

+
))} - -

About {speaker.name}

+ + +

About {speaker.name}

+
- - - - - - Tweet - - - - openSpeakerShare(speaker)}> - - Share - - - - openContact(speaker)}> - - Contact - - -
- setShowActionSheet(false)} - buttons={actionSheetButtons} - /> ); }; diff --git a/src/components/Time.tsx b/src/components/Time.tsx deleted file mode 100644 index 836292b2..00000000 --- a/src/components/Time.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; -import { format, parseISO as parseDate } from 'date-fns'; - -export const Time: React.FC<{ date: string }> = ({ date }) => ( - <> - {format(parseDate(date), "h:mm aaaaa")}m - -) diff --git a/src/data/connect.tsx b/src/data/connect.tsx index ce907bdb..c752a81c 100644 --- a/src/data/connect.tsx +++ b/src/data/connect.tsx @@ -1,4 +1,4 @@ -import React, { useContext, useEffect, useState, useMemo } from 'react'; +import React, { useContext, useMemo } from 'react'; import { AppContext } from './AppContext'; import { DispatchObject } from '../util/types'; import { AppState } from './state'; @@ -36,11 +36,13 @@ export function connect { return Object.assign({}, ownProps, mapStateToProps(context.state, ownProps), dispatchFuncs); + // eslint-disable-next-line }, [ownProps, context.state]); return React.createElement(component, props); diff --git a/src/data/dataApi.ts b/src/data/dataApi.ts index e3f84d81..9f338870 100644 --- a/src/data/dataApi.ts +++ b/src/data/dataApi.ts @@ -1,13 +1,12 @@ import { Plugins } from '@capacitor/core'; -import { Session } from '../models/Session'; +import { Schedule, Session } from '../models/Schedule'; import { Speaker } from '../models/Speaker'; import { Location } from '../models/Location'; const { Storage } = Plugins; +const dataUrl = '/assets/data/data.json'; const locationsUrl = '/assets/data/locations.json'; -const sessionsUrl = '/assets/data/sessions.json'; -const speakersUrl = '/assets/data/speakers.json'; const HAS_LOGGED_IN = 'hasLoggedIn'; const HAS_SEEN_TUTORIAL = 'hasSeenTutorial'; @@ -15,17 +14,20 @@ const USERNAME = 'username'; export const getConfData = async () => { const response = await Promise.all([ - fetch(sessionsUrl), - fetch(locationsUrl), - fetch(speakersUrl)]); - const sessions = await response[0].json() as Session[]; + fetch(dataUrl), + fetch(locationsUrl)]); + const responseData = await response[0].json(); + const schedule = responseData.schedule[0] as Schedule; + const sessions = parseSessions(schedule); + const speakers = responseData.speakers as Speaker[]; const locations = await response[1].json() as Location[]; - const speakers = await response[2].json() as Speaker[]; const allTracks = sessions .reduce((all, session) => all.concat(session.tracks), [] as string[]) .filter((trackName, index, array) => array.indexOf(trackName) === index) .sort(); + const data = { + schedule, sessions, locations, speakers, @@ -66,3 +68,11 @@ export const setUsernameData = async (username?: string) => { await Storage.set({ key: USERNAME, value: username }); } } + +function parseSessions(schedule: Schedule) { + const sessions: Session[] = []; + schedule.groups.forEach(g => { + g.sessions.forEach(s => sessions.push(s)) + }); + return sessions; +} diff --git a/src/data/selectors.ts b/src/data/selectors.ts index 7f20db31..31d3f88b 100644 --- a/src/data/selectors.ts +++ b/src/data/selectors.ts @@ -1,92 +1,109 @@ import { createSelector } from 'reselect'; -import { parseISO as parseDate } from 'date-fns'; -import { Session } from '../models/Session'; -import { SessionGroup } from '../models/SessionGroup'; +import { Schedule, Session, ScheduleGroup } from '../models/Schedule'; import { AppState } from './state'; -const getSessions = (state: AppState) => state.data.sessions; +const getSchedule = (state: AppState) => { + + return state.data.schedule +}; export const getSpeakers = (state: AppState) => state.data.speakers; +const getSessions = (state: AppState) => state.data.sessions; const getFilteredTracks = (state: AppState) => state.data.filteredTracks; const getFavoriteIds = (state: AppState) => state.data.favorites; const getSearchText = (state: AppState) => state.data.searchText; -export const getFilteredSessions = createSelector( - getSessions, getFilteredTracks, - (sessions, filteredTracks) => { - return sessions.filter(session => { - let include = false; - session.tracks.forEach(track => { - if (filteredTracks.indexOf(track) > -1) { - include = true; +export const getFilteredSchedule = createSelector( + getSchedule, getFilteredTracks, + (schedule, filteredTracks) => { + const groups: ScheduleGroup[] = []; + schedule.groups.forEach(group => { + const sessions: Session[] = []; + group.sessions.forEach(session => { + session.tracks.forEach(track => { + if (filteredTracks.indexOf(track) > -1) { + sessions.push(session); + } + }) + }) + if (sessions.length) { + const groupToAdd: ScheduleGroup = { + time: group.time, + sessions } - }); - return include; + groups.push(groupToAdd); + } }); + + return { + date: schedule.date, + groups + } as Schedule; } ); -export const getSearchedSessions = createSelector( - getFilteredSessions, getSearchText, - (sessions, searchText) => { +export const getSearchedSchedule = createSelector( + getFilteredSchedule, getSearchText, + (schedule, searchText) => { if (!searchText) { - return sessions; + return schedule; } - return sessions.filter(session => session.name.toLowerCase().indexOf(searchText.toLowerCase()) > -1); - } -) + const groups: ScheduleGroup[] = []; + schedule.groups.forEach(group => { -export const getGroupedSessions = createSelector( - getSearchedSessions, - (sessions) => { - return groupSessions(sessions); + const sessions = group.sessions.filter(s => s.name.toLowerCase().indexOf(searchText.toLowerCase()) > -1) + if (sessions.length) { + const groupToAdd: ScheduleGroup = { + time: group.time, + sessions + } + groups.push(groupToAdd); + } + }); + return { + date: schedule.date, + groups + } as Schedule; } -); +) -export const getFavorites = createSelector( - getSearchedSessions, getFavoriteIds, - (sessions, favoriteIds) => sessions.filter(x => favoriteIds.indexOf(x.id) > -1) +export const getScheduleList = createSelector( + getSearchedSchedule, + (schedule) => schedule ); export const getGroupedFavorites = createSelector( - getFavorites, - (sessions) => { - return groupSessions(sessions); + getScheduleList, getFavoriteIds, + (schedule, favoriteIds) => { + const groups: ScheduleGroup[] = []; + schedule.groups.forEach(group => { + const sessions = group.sessions.filter(s => favoriteIds.indexOf(s.id) > -1) + if (sessions.length) { + const groupToAdd: ScheduleGroup = { + time: group.time, + sessions + } + groups.push(groupToAdd); + } + }); + return { + date: schedule.date, + groups + } as Schedule; } -) +); + const getIdParam = (_state: AppState, props: any) => { - const stringParam = props.match.params['id']; - return parseInt(stringParam, 10); + return props.match.params['id']; } export const getSession = createSelector( getSessions, getIdParam, - (sessions, id) => sessions.find(x => x.id === id) + (sessions, id) => { + return sessions.find(s => s.id === id); + } ); -function groupSessions(sessions: Session[]) { - return sessions - .sort((a, b) => ( - parseDate(a.dateTimeStart).valueOf() - parseDate(b.dateTimeStart).valueOf() - )) - .reduce((groups, session) => { - let starterHour = parseDate(session.dateTimeStart); - starterHour.setMinutes(0); - starterHour.setSeconds(0); - const starterHourStr = starterHour.toJSON(); - const foundGroup = groups.find(group => group.startTime === starterHourStr); - if (foundGroup) { - foundGroup.sessions.push(session); - } else { - groups.push({ - startTime: starterHourStr, - sessions: [session] - }); - } - return groups; - }, [] as SessionGroup[]); -} - export const getSpeaker = createSelector( getSpeakers, getIdParam, (speakers, id) => speakers.find(x => x.id === id) @@ -95,13 +112,14 @@ export const getSpeaker = createSelector( export const getSpeakerSessions = createSelector( getSessions, (sessions) => { - const speakerSessions: {[key: number]: Session[]} = {}; + const speakerSessions: { [key: string]: Session[] } = {}; + sessions.forEach(session => { - session.speakerIds.forEach(speakerId => { - if(speakerSessions[speakerId]) { - speakerSessions[speakerId].push(session); + session.speakerNames && session.speakerNames.forEach(name => { + if (speakerSessions[name]) { + speakerSessions[name].push(session); } else { - speakerSessions[speakerId] = [session]; + speakerSessions[name] = [session]; } }) }); diff --git a/src/data/sessions/sessions.state.ts b/src/data/sessions/conf.state.ts similarity index 70% rename from src/data/sessions/sessions.state.ts rename to src/data/sessions/conf.state.ts index c4e885d9..1217baf2 100644 --- a/src/data/sessions/sessions.state.ts +++ b/src/data/sessions/conf.state.ts @@ -1,7 +1,8 @@ import { Location } from '../../models/Location'; import { Speaker } from '../../models/Speaker'; -import { Session } from '../../models/Session'; -export interface SessionsState { +import { Schedule, Session } from '../../models/Schedule'; +export interface ConfState { + schedule: Schedule; sessions: Session[]; speakers: Speaker[]; favorites: number[]; @@ -11,4 +12,5 @@ export interface SessionsState { mapCenterId?: number; loading?: boolean; allTracks: string[]; + menuEnabled: boolean; } diff --git a/src/data/sessions/sessions.actions.ts b/src/data/sessions/sessions.actions.ts index 575e290b..54214a30 100644 --- a/src/data/sessions/sessions.actions.ts +++ b/src/data/sessions/sessions.actions.ts @@ -1,6 +1,6 @@ import { getConfData } from '../dataApi'; import { ActionType } from '../../util/types'; -import { SessionsState } from './sessions.state'; +import { ConfState } from './conf.state'; export const loadConfData = () => async (dispatch: React.Dispatch) => { dispatch(setLoading(true)); @@ -14,7 +14,7 @@ export const setLoading = (isLoading: boolean) => ({ isLoading } as const); -export const setData = (data: Partial) => ({ +export const setData = (data: Partial) => ({ type: 'set-conf-data', data } as const); @@ -39,6 +39,11 @@ export const setSearchText = (searchText?: string) => ({ searchText } as const); +export const setMenuEnabled = (menuEnabled: boolean) => ({ + type: 'set-menu-enabled', + menuEnabled +} as const); + export type SessionsActions = | ActionType | ActionType @@ -46,3 +51,4 @@ export type SessionsActions = | ActionType | ActionType | ActionType + | ActionType diff --git a/src/data/sessions/sessions.reducer.ts b/src/data/sessions/sessions.reducer.ts index 651c530f..252b9830 100644 --- a/src/data/sessions/sessions.reducer.ts +++ b/src/data/sessions/sessions.reducer.ts @@ -1,7 +1,7 @@ import { SessionsActions } from './sessions.actions'; -import { SessionsState } from './sessions.state'; +import { ConfState } from './conf.state'; -export const sessionsReducer = (state: SessionsState, action: SessionsActions): SessionsState => { +export const sessionsReducer = (state: ConfState, action: SessionsActions): ConfState => { switch (action.type) { case 'set-conf-loading': { return { ...state, loading: action.isLoading }; @@ -21,5 +21,8 @@ export const sessionsReducer = (state: SessionsState, action: SessionsActions): case 'set-search-text': { return { ...state, searchText: action.searchText }; } + case 'set-menu-enabled': { + return { ...state, menuEnabled: action.menuEnabled }; + } } } \ No newline at end of file diff --git a/src/data/state.ts b/src/data/state.ts index d4605015..64ae8606 100644 --- a/src/data/state.ts +++ b/src/data/state.ts @@ -4,6 +4,7 @@ import { userReducer } from './user/user.reducer'; export const initialState: AppState = { data: { + schedule: { groups: [] } as any, sessions: [], speakers: [], favorites: [], @@ -11,7 +12,8 @@ export const initialState: AppState = { allTracks: [], filteredTracks: [], mapCenterId: 0, - loading: false + loading: false, + menuEnabled: true }, user: { hasSeenTutorial: false, diff --git a/src/models/Schedule.ts b/src/models/Schedule.ts new file mode 100644 index 00000000..76669cd6 --- /dev/null +++ b/src/models/Schedule.ts @@ -0,0 +1,20 @@ +export interface Schedule { + date: string; + groups: ScheduleGroup[] +} + +export interface ScheduleGroup { + time: string; + sessions: Session[]; +} + +export interface Session { + id: number; + timeStart: string; + timeEnd: string; + name: string; + location: string; + description: string; + speakerNames: string[]; + tracks: string[]; +} diff --git a/src/models/Session.ts b/src/models/Session.ts deleted file mode 100644 index beee620f..00000000 --- a/src/models/Session.ts +++ /dev/null @@ -1,10 +0,0 @@ -export interface Session { - id: number; - dateTimeStart: string; - dateTimeEnd: string; - name: string; - location: string; - description: string; - speakerIds: number[]; - tracks: string[]; -} diff --git a/src/models/SessionGroup.ts b/src/models/SessionGroup.ts index df66b6b7..93d46ada 100644 --- a/src/models/SessionGroup.ts +++ b/src/models/SessionGroup.ts @@ -1,4 +1,4 @@ -import { Session } from './Session'; +import { Session } from './Schedule'; export interface SessionGroup { startTime: string; sessions: Session[]; diff --git a/src/models/Speaker.ts b/src/models/Speaker.ts index 82a0133d..35d8c785 100644 --- a/src/models/Speaker.ts +++ b/src/models/Speaker.ts @@ -3,7 +3,9 @@ export interface Speaker { name: string; profilePic: string; twitter: string; + instagram: string; about: string; + title: string; location: string; email: string; phone: string; diff --git a/src/pages/About.scss b/src/pages/About.scss index b657cbe6..4ac723b1 100644 --- a/src/pages/About.scss +++ b/src/pages/About.scss @@ -1,26 +1,96 @@ #about-page { + ion-toolbar { + position: absolute; + + top: 0; + left: 0; + right: 0; + + --background: transparent; + --color: white; + } + + ion-toolbar ion-back-button, + ion-toolbar ion-button, + ion-toolbar ion-menu-button { + --color: white; + } + .about-header { - background-color: #222; - padding: 16px; + position: relative; + width: 100%; height: 30%; - text-align: center; } - - .about-header img { - max-height: 100%; + + .about-header .about-image { + position: absolute; + + top: 0; + left: 0; + bottom: 0; + right: 0; + + background-position: center; + background-size: cover; + background-repeat: no-repeat; + + opacity: 0; + + transition: opacity 500ms ease-in-out; + } + + .about-header .madison { + background-image: url("/assets/img/about/madison.jpg"); + } + + .about-header .austin { + background-image: url("/assets/img/about/austin.jpg"); + } + + .about-header .chicago { + background-image: url("/assets/img/about/chicago.jpg"); + } + + .about-header .seattle { + background-image: url("/assets/img/about/seattle.jpg"); } - + + .about-info { + position: absolute; + margin-top: -10px; + border-radius: 10px; + background: var(--ion-background-color, #fff); + } + + .about-info h3 { + margin-top: 0; + } + + .about-info ion-list { + padding-top: 0; + } + .about-info p { + line-height: 130%; + color: var(--ion-color-dark); - text-align: left; } - + .about-info ion-icon { margin-inline-end: 32px; } - + + /* + * iOS Only + */ + .ios .about-info { - text-align: center; - } -} \ No newline at end of file + --ion-padding: 19px; + } + + .ios .about-info h3 { + font-weight: 700; + } + +} diff --git a/src/pages/About.tsx b/src/pages/About.tsx index bdcd9d04..62a5db20 100644 --- a/src/pages/About.tsx +++ b/src/pages/About.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; -import { IonHeader, IonToolbar, IonTitle, IonContent, IonPage, IonButtons, IonMenuButton, IonButton, IonIcon, IonDatetime, IonSelectOption, IonList, IonItem, IonLabel, IonSelect, IonPopover } from '@ionic/react'; +import { IonHeader, IonToolbar, IonContent, IonPage, IonButtons, IonMenuButton, IonButton, IonIcon, IonDatetime, IonSelectOption, IonList, IonItem, IonLabel, IonSelect, IonPopover } from '@ionic/react'; import './About.scss'; -import { calendar, pin, more } from 'ionicons/icons'; +import { ellipsisHorizontal, ellipsisVertical } from 'ionicons/icons'; import AboutPopover from '../components/AboutPopover'; interface AboutProps { } @@ -10,69 +10,122 @@ const About: React.FC = () => { const [showPopover, setShowPopover] = useState(false); const [popoverEvent, setPopoverEvent] = useState(); + const [location, setLocation] = useState<'madison' | 'austin' | 'chicago' | 'seattle'>('madison'); + const [conferenceDate, setConferenceDate] = useState('2047-05-17T00:00:00-05:00'); + + const selectOptions = { + header: 'Select a Location' + }; const presentPopover = (e: React.MouseEvent) => { setPopoverEvent(e.nativeEvent); setShowPopover(true); }; - const conferenceDate = '2047-05-17'; + + // momentjs would be a better way to do this https://momentjs.com/ + function displayDate(date: string, format: string) { + const monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; + + const d = new Date(date); + const year = d.getFullYear(); + + if (format === 'y') { + return year; + } else { + const month = monthNames[d.getMonth()]; + const day = d.getDate(); + + return month + ' ' + day + ', ' + year; + } + } return ( - - - - - - About - - - - - - - + + + + + + + + + + + +
- ionic logo + {/* Instead of loading an image each time the select changes, use opacity to transition them */} +
+
+
+
-

Ionic Conference

+

About

- - - - Date - - +

+ The Ionic Conference is a one-day conference on { displayDate(conferenceDate, 'mediumDate') } featuring talks from the Ionic team. It is focused on Ionic applications being built with Ionic Framework. This includes migrating apps to the latest version of the framework, Angular concepts, Webpack, Sass, and many other technologies used in Ionic 2. Tickets are completely sold out, and we’re expecting more than 1000 developers – making this the largest Ionic conference ever! +

+ +

Details

+ - - Location - - Madison, WI + + Location + + setLocation(e.detail.value as any)}> + Madison, WI Austin, TX Chicago, IL Seattle, WA + + + Date + + setConferenceDate(e.detail.value as any)}> + + + + +

Internet

+ + + + + Wifi network + + + ica{ displayDate(conferenceDate, 'y') } + + + + + Password + + + makegoodthings + + -

- The Ionic Conference is a one-day conference featuring talks from the Ionic team. It is focused on Ionic applications being - built with Ionic 2. This includes migrating apps from Ionic 1 to Ionic 2, Angular concepts, Webpack, Sass, and many - other technologies used in Ionic 2. Tickets are completely sold out, and we’re expecting more than 1000 developers - – making this the largest Ionic conference ever! -

+ setShowPopover(false)} > - setShowPopover(false)} /> + setShowPopover(false)} />
); diff --git a/src/pages/MainTabs.tsx b/src/pages/MainTabs.tsx index 1e576eba..8338e377 100644 --- a/src/pages/MainTabs.tsx +++ b/src/pages/MainTabs.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { IonTabs, IonRouterOutlet, IonTabBar, IonTabButton, IonIcon, IonLabel } from '@ionic/react'; import { Route, Redirect } from 'react-router'; -import { calendar, contacts, map, informationCircle } from 'ionicons/icons'; +import { calendar, location, informationCircle, people } from 'ionicons/icons'; import SchedulePage from './SchedulePage'; import SpeakerList from './SpeakerList'; import SpeakerDetail from './SpeakerDetail'; @@ -17,9 +17,9 @@ const MainTabs: React.FC = () => { - {/* + {/* Using the render method prop cuts down the number of renders your components will have due to route changes. - Use the component prop when your component depends on the RouterComponentProps passed in automatically. + Use the component prop when your component depends on the RouterComponentProps passed in automatically. */} } exact={true} /> } exact={true} /> @@ -35,11 +35,11 @@ const MainTabs: React.FC = () => { Schedule - + Speakers - + Map diff --git a/src/pages/SchedulePage.scss b/src/pages/SchedulePage.scss index 9ea30160..8ad29093 100644 --- a/src/pages/SchedulePage.scss +++ b/src/pages/SchedulePage.scss @@ -1,4 +1,20 @@ #schedule-page { + ion-fab-button { + --background: var(--ion-color-step-150, #fff); + --background-hover: var(--ion-color-step-200, #f2f2f2); + --background-focused: var(--ion-color-step-250, #d9d9d9); + + --color: var(--ion-color-primary, #3880ff); + } + + /* + * Material Design uses the ripple for activated + * so only style the iOS activated background + */ + .ios ion-fab-button { + --background-activated: var(--ion-color-step-250, #d9d9d9); + } + ion-item-sliding.track-ionic ion-label { border-left: 2px solid var(--ion-color-primary); padding-left: 10px; diff --git a/src/pages/SchedulePage.tsx b/src/pages/SchedulePage.tsx index 03ca7283..fd1712f1 100644 --- a/src/pages/SchedulePage.tsx +++ b/src/pages/SchedulePage.tsx @@ -1,20 +1,24 @@ import React, { useState, useRef } from 'react'; -import { IonToolbar, IonContent, IonPage, IonButtons, IonMenuButton, IonSegment, IonSegmentButton, IonButton, IonIcon, IonSearchbar, IonRefresher, IonRefresherContent, IonToast, IonModal, IonHeader, getConfig } from '@ionic/react'; -import { connect } from '../data/connect'; -import { options } from 'ionicons/icons'; + +import { IonToolbar, IonContent, IonPage, IonButtons, IonTitle, IonMenuButton, IonSegment, IonSegmentButton, IonButton, IonIcon, IonSearchbar, IonRefresher, IonRefresherContent, IonToast, IonModal, IonHeader, getConfig } from '@ionic/react'; +import { options, search } from 'ionicons/icons'; + import SessionList from '../components/SessionList'; import SessionListFilter from '../components/SessionListFilter'; import './SchedulePage.scss' -import * as selectors from '../data/selectors'; -import { setSearchText, addFavorite, removeFavorite } from '../data/sessions/sessions.actions'; + import ShareSocialFab from '../components/ShareSocialFab'; -import { SessionGroup } from '../models/SessionGroup'; + +import * as selectors from '../data/selectors'; +import { connect } from '../data/connect'; +import { setSearchText } from '../data/sessions/sessions.actions'; +import { Schedule } from '../models/Schedule'; interface OwnProps { } interface StateProps { - sessionGroups: SessionGroup[]; - favoriteGroups: SessionGroup[]; + schedule: Schedule; + favoritesSchedule: Schedule; mode: 'ios' | 'md' } @@ -24,12 +28,17 @@ interface DispatchProps { type SchedulePageProps = OwnProps & StateProps & DispatchProps; -const SchedulePage: React.FC = ({ favoriteGroups, sessionGroups, setSearchText, mode }) => { +const SchedulePage: React.FC = ({ favoritesSchedule, schedule, setSearchText, mode }) => { const [segment, setSegment] = useState<'all' | 'favorites'>('all'); + const [showSearchbar, setShowSearchbar] = useState(false); const [showFilterModal, setShowFilterModal] = useState(false); const ionRefresherRef = useRef(null); const [showCompleteToast, setShowCompleteToast] = useState(false); + const pageRef = useRef(null); + + const ios = mode === 'ios'; + const doRefresh = () => { setTimeout(() => { ionRefresherRef.current!.complete(); @@ -38,41 +47,73 @@ const SchedulePage: React.FC = ({ favoriteGroups, sessionGrou }; return ( - - + + - - - - - setSegment(e.detail.value as any)}> - - All - - - Favorites - - + {!showSearchbar && + + + + } + {ios && + setSegment(e.detail.value as any)}> + + All + + + Favorites + + + } + {!ios && !showSearchbar && + Schedule + } + {showSearchbar && + setSearchText(e.detail.value)} onIonCancel={() => setShowSearchbar(false)}> + } - setShowFilterModal(true)}> - {mode === 'ios' ? 'Filter' : } - + {!ios && !showSearchbar && + setShowSearchbar(true)}> + + + } + {!showSearchbar && + setShowFilterModal(true)}> + {mode === 'ios' ? 'Filter' : } + + } - - setSearchText(e.detail.value)} - /> - + {!ios && + + setSegment(e.detail.value as any)}> + + All + + + Favorites + + + + } - + + + + Schedule + + + setSearchText(e.detail.value)}> + + + + = ({ favoriteGroups, sessionGrou /> @@ -95,6 +137,9 @@ const SchedulePage: React.FC = ({ favoriteGroups, sessionGrou setShowFilterModal(false)} + swipeToClose={true} + presentingElement={pageRef.current!} + cssClass="session-list-filter" > setShowFilterModal(false)} @@ -109,8 +154,8 @@ const SchedulePage: React.FC = ({ favoriteGroups, sessionGrou export default connect({ mapStateToProps: (state) => ({ - sessionGroups: selectors.getGroupedSessions(state), - favoriteGroups: selectors.getGroupedFavorites(state), + schedule: selectors.getSearchedSchedule(state), + favoritesSchedule: selectors.getGroupedFavorites(state), mode: getConfig()!.get('mode') }), mapDispatchToProps: { diff --git a/src/pages/SessionDetail.tsx b/src/pages/SessionDetail.tsx index c91b03b6..96f334f4 100644 --- a/src/pages/SessionDetail.tsx +++ b/src/pages/SessionDetail.tsx @@ -5,9 +5,8 @@ import { withRouter, RouteComponentProps } from 'react-router'; import * as selectors from '../data/selectors'; import { starOutline, star, share, cloudDownload } from 'ionicons/icons'; import './SessionDetail.scss'; -import { Time } from '../components/Time'; import { addFavorite, removeFavorite } from '../data/sessions/sessions.actions'; -import { Session } from '../models/Session'; +import { Session } from '../models/Schedule'; interface OwnProps extends RouteComponentProps { }; @@ -67,7 +66,7 @@ const SessionDetail: React.FC = ({ session, addFavorite, rem ))}

{session.description}

- diff --git a/src/pages/SpeakerDetail.scss b/src/pages/SpeakerDetail.scss index 6cf08098..5b2bfc62 100644 --- a/src/pages/SpeakerDetail.scss +++ b/src/pages/SpeakerDetail.scss @@ -1,11 +1,78 @@ #speaker-detail { - img { - max-width: 140px; + /* + * Speaker Background + */ + + ion-toolbar { + position: absolute; + + top: 0; + left: 0; + right: 0; + + --background: transparent; + --color: white; + } + + ion-toolbar ion-back-button, + ion-toolbar ion-button, + ion-toolbar ion-menu-button { + --color: white; + } + + .speaker-background { + position: relative; + + display: flex; + + padding-top: var(--ion-safe-area-top); + + align-items: center; + justify-content: center; + + flex-direction: column; + + height: calc(250px + var(--ion-safe-area-top)); + + background: center / cover url("/assets/img/speaker-background.png") no-repeat; + } + + .speaker-background img { + width: 70px; border-radius: 50%; + margin-top: calc(-1 * var(--ion-safe-area-top)); } - p { - color: #60646B; + + .speaker-background h2 { + position: absolute; + + bottom: 10px; + + color: white; + } + + .md .speaker-background { + box-shadow: rgba(0, 0, 0, 0.2) 0 3px 1px -2px, rgba(0, 0, 0, 0.14) 0 2px 2px 0px, rgba(0, 0, 0, 0.12) 0 1px 5px 0; + } + + .ios .speaker-background { + box-shadow: rgba(0, 0, 0, 0.12) 0 4px 16px; + } + + /* + * Speaker Details + */ + + .speaker-detail p { + margin-left: 6px; + margin-right: 6px; } -} + .speaker-detail hr { + margin-top: 20px; + margin-bottom: 20px; + background: var(--ion-color-step-150, #d7d8da); + } + +} diff --git a/src/pages/SpeakerDetail.tsx b/src/pages/SpeakerDetail.tsx index a9e7eb72..fe24594a 100644 --- a/src/pages/SpeakerDetail.tsx +++ b/src/pages/SpeakerDetail.tsx @@ -1,12 +1,18 @@ -import React from 'react'; +import React, { useState } from 'react'; import { RouteComponentProps } from 'react-router'; -import { IonIcon, IonHeader, IonToolbar, IonButtons, IonTitle, IonContent, IonButton, IonBackButton, IonPage } from '@ionic/react' + import './SpeakerDetail.scss'; -import { logoTwitter, logoGithub, logoInstagram } from 'ionicons/icons'; + +import { ActionSheetButton } from '@ionic/core'; +import { IonActionSheet, IonChip, IonIcon, IonHeader, IonLabel, IonToolbar, IonButtons, IonContent, IonButton, IonBackButton, IonPage } from '@ionic/react' +import { callOutline, callSharp, logoTwitter, logoGithub, logoInstagram, shareOutline, shareSharp } from 'ionicons/icons'; + import { connect } from '../data/connect'; import * as selectors from '../data/selectors'; + import { Speaker } from '../models/Speaker'; + interface OwnProps extends RouteComponentProps { speaker?: Speaker; }; @@ -18,39 +24,114 @@ interface DispatchProps {}; interface SpeakerDetailProps extends OwnProps, StateProps, DispatchProps {}; const SpeakerDetail: React.FC = ({ speaker }) => { - + const [showActionSheet, setShowActionSheet] = useState(false); + const [actionSheetButtons, setActionSheetButtons] = useState([]); + const [actionSheetHeader, setActionSheetHeader] = useState(''); + + function openSpeakerShare(speaker: Speaker) { + setActionSheetButtons([ + { + text: 'Copy Link', + handler: () => { + console.log('Copy Link clicked'); + } + }, + { + text: 'Share via ...', + handler: () => { + console.log('Share via clicked'); + } + }, + { + text: 'Cancel', + role: 'cancel', + handler: () => { + console.log('Cancel clicked'); + } + } + ]); + setActionSheetHeader(`Share ${speaker.name}`); + setShowActionSheet(true); + } + + function openContact(speaker: Speaker) { + setActionSheetButtons([ + { + text: `Email ( ${speaker.email} )`, + handler: () => { + window.open('mailto:' + speaker.email); + } + }, + { + text: `Call ( ${speaker.phone} )`, + handler: () => { + window.open('tel:' + speaker.phone); + } + } + ]); + setActionSheetHeader(`Share ${speaker.name}`); + setShowActionSheet(true); + } + + function openExternalUrl(url: string) { + window.open(url, '_blank'); + } + if (!speaker) { return
Speaker not found
} return ( - - - - - - {speaker.name} - - - - -
- {speaker.name} -
- - - - - - - - - + + + + + + + + openContact(speaker)}> + + + openSpeakerShare(speaker)}> + + + + + + +
+ {speaker.name}/ +

{speaker.name}

-

{speaker.about}

+
+

{speaker.about} Say hello on social media!

+ +
+ + openExternalUrl(`https://twitter.com/${speaker.twitter}`)}> + + Twitter + + + openExternalUrl('https://github.com/ionic-team/ionic')}> + + GitHub + + + openExternalUrl('https://instagram.com/ionicframework')}> + + Instagram + +
+ setShowActionSheet(false)} + buttons={actionSheetButtons} + /> ); }; diff --git a/src/pages/SpeakerList.scss b/src/pages/SpeakerList.scss index 12fcf270..64b9fa35 100644 --- a/src/pages/SpeakerList.scss +++ b/src/pages/SpeakerList.scss @@ -1,24 +1,48 @@ #speaker-list { - .scroll { - background: #ededed; - } - .speaker-card { - height: 100%; display: flex; flex-direction: column; } - .speaker-card ion-card-header { - padding: 0; + /* Due to the fact the cards are inside of columns the margins don't overlap + * properly so we want to remove the extra margin between cards + */ + ion-col:not(:last-of-type) .speaker-card { + margin-bottom: 0; + } + + .speaker-card .speaker-item { + --min-height: 85px; + } + + .speaker-card .speaker-item h2 { + font-size: 18px; + font-weight: 500; + letter-spacing: 0.02em; + } + + .speaker-card .speaker-item p { + font-size: 13px; + letter-spacing: 0.02em; } - .speaker-card ion-card-header .item { - padding: 4px 16px; + .speaker-card ion-card-header { + padding: 0; } .speaker-card ion-card-content { flex: 1 1 auto; + + padding: 0; + } + + .ios ion-list { + margin-bottom: 10px; + } + + .md ion-list { + border-top: 1px solid var(--ion-color-step-150, #d7d8da); + padding: 0; - } + } } \ No newline at end of file diff --git a/src/pages/SpeakerList.tsx b/src/pages/SpeakerList.tsx index 834a969a..c308699b 100644 --- a/src/pages/SpeakerList.tsx +++ b/src/pages/SpeakerList.tsx @@ -1,8 +1,8 @@ import React from 'react'; -import { IonHeader, IonToolbar, IonTitle, IonContent, IonPage, IonButtons, IonMenuButton, IonList, IonGrid, IonRow, IonCol } from '@ionic/react'; +import { IonHeader, IonToolbar, IonTitle, IonContent, IonPage, IonButtons, IonMenuButton, IonGrid, IonRow, IonCol } from '@ionic/react'; import SpeakerItem from '../components/SpeakerItem'; import { Speaker } from '../models/Speaker'; -import { Session } from '../models/Session'; +import { Session } from '../models/Schedule'; import { connect } from '../data/connect'; import * as selectors from '../data/selectors'; import './SpeakerList.scss'; @@ -11,7 +11,7 @@ interface OwnProps { }; interface StateProps { speakers: Speaker[]; - speakerSessions: { [key: number]: Session[] }; + speakerSessions: { [key: string]: Session[] }; }; interface DispatchProps { }; @@ -22,7 +22,7 @@ const SpeakerList: React.FC = ({ speakers, speakerSessions }) return ( - + @@ -31,22 +31,26 @@ const SpeakerList: React.FC = ({ speakers, speakerSessions }) - - + + + + Speakers + + + - + {speakers.map(speaker => ( ))} - ); diff --git a/src/pages/Tutorial.scss b/src/pages/Tutorial.scss index e6c8c56f..a114ff77 100644 --- a/src/pages/Tutorial.scss +++ b/src/pages/Tutorial.scss @@ -1,38 +1,37 @@ #tutorial-page { ion-toolbar { - // TODO test transparent and fullscreen --background: transparent; --border-color: transparent; } - + .swiper-slide { display: block; } - + .slide-title { margin-top: 2.8rem; } - + .slide-image { max-height: 50%; max-width: 60%; margin: 36px 0; pointer-events: none; } - + b { font-weight: 500; } - + p { padding: 0 40px; font-size: 14px; line-height: 1.5; color: var(--ion-color-step-600, #60646b); - + b { color: var(--ion-text-color, #000000); } } - + } \ No newline at end of file diff --git a/src/pages/Tutorial.tsx b/src/pages/Tutorial.tsx index 37aed95b..0a98611d 100644 --- a/src/pages/Tutorial.tsx +++ b/src/pages/Tutorial.tsx @@ -1,6 +1,7 @@ import React, { useState, useRef } from 'react'; -import { IonContent, IonPage, IonHeader, IonToolbar, IonButtons, IonButton, IonSlides, IonSlide, IonIcon } from '@ionic/react'; +import { IonContent, IonPage, IonHeader, IonToolbar, IonButtons, IonButton, IonSlides, IonSlide, IonIcon, useIonViewWillEnter } from '@ionic/react'; import { arrowForward } from 'ionicons/icons'; +import { setMenuEnabled } from '../data/sessions/sessions.actions'; import { setHasSeenTutorial } from '../data/user/user.actions'; import './Tutorial.scss'; import { connect } from '../data/connect'; @@ -9,17 +10,23 @@ import { RouteComponentProps } from 'react-router'; interface OwnProps extends RouteComponentProps {}; interface DispatchProps { - setHasSeenTutorial: typeof setHasSeenTutorial + setHasSeenTutorial: typeof setHasSeenTutorial; + setMenuEnabled: typeof setMenuEnabled; } interface TutorialProps extends OwnProps, DispatchProps { }; -const Tutorial: React.FC = ({ history, setHasSeenTutorial }) => { +const Tutorial: React.FC = ({ history, setHasSeenTutorial, setMenuEnabled }) => { const [showSkip, setShowSkip] = useState(true); const slideRef = useRef(null); + + useIonViewWillEnter(() => { + setMenuEnabled(false); + }); const startApp = async () => { await setHasSeenTutorial(true); + await setMenuEnabled(true); history.push('/tabs/schedule', { direction: 'none' }); }; @@ -81,7 +88,8 @@ const Tutorial: React.FC = ({ history, setHasSeenTutorial }) => { export default connect({ mapDispatchToProps: ({ - setHasSeenTutorial + setHasSeenTutorial, + setMenuEnabled }), component: Tutorial }); \ No newline at end of file diff --git a/src/theme.css b/src/theme.css deleted file mode 100644 index 3d4a42d4..00000000 --- a/src/theme.css +++ /dev/null @@ -1,179 +0,0 @@ - -/* Ionic Variables and Theming. For more information, please see -// https://beta.ionicframework.com/docs/theming/ -// The app direction is used to include -// rtl styles in your app. For more information, please see -// https://beta.ionicframework.com/docs/layout/rtl -// $app-direction: ltr; -// Ionic Colors -// -------------------------------------------------- -// Named colors makes it easy to reuse colors on various components. -// It's highly recommended to change the default colors -// to match your app's branding. Ionic provides eight layered colors -// that can be changed to theme an app. Additional colors can be -// added as well (see below). For more information, please see -// https://beta.ionicframework.com/docs/theming/advanced -// To easily create custom color palettes for your app’s UI, -// check out our color generator: -// https://beta.ionicframework.com/docs/theming/color-generator -*/ - -:root { - --ion-color-angular: #ac282b; - --ion-color-communication: #8e8d93; - --ion-color-tooling: #fe4c52; - --ion-color-services: #fd8b2d; - --ion-color-design: #fed035; - --ion-color-workshop: #69bb7b; - --ion-color-food: #3bc7c4; - --ion-color-documentation: #b16be3; - --ion-color-navigation: #6600cc; - - --ion-color-primary: #3880ff; - --ion-color-primary-rgb: 56, 128, 255; - --ion-color-primary-contrast: #ffffff; - --ion-color-primary-contrast-rgb: 255, 255, 255; - --ion-color-primary-shade: #3171e0; - --ion-color-primary-tint: #4c8dff; - - --ion-color-secondary: #0cd1e8; - --ion-color-secondary-rgb: 12, 209, 232; - --ion-color-secondary-contrast: #ffffff; - --ion-color-secondary-contrast-rgb: 255, 255, 255; - --ion-color-secondary-shade: #0bb8cc; - --ion-color-secondary-tint: #24d6ea; - - --ion-color-tertiary: #7044ff; - --ion-color-tertiary-rgb: 112, 68, 255; - --ion-color-tertiary-contrast: #ffffff; - --ion-color-tertiary-contrast-rgb: 255, 255, 255; - --ion-color-tertiary-shade: #633ce0; - --ion-color-tertiary-tint: #7e57ff; - - --ion-color-success: #10dc60; - --ion-color-success-rgb: 16, 220, 96; - --ion-color-success-contrast: #ffffff; - --ion-color-success-contrast-rgb: 255, 255, 255; - --ion-color-success-shade: #0ec254; - --ion-color-success-tint: #28e070; - - --ion-color-warning: #ffce00; - --ion-color-warning-rgb: 255, 206, 0; - --ion-color-warning-contrast: #ffffff; - --ion-color-warning-contrast-rgb: 255, 255, 255; - --ion-color-warning-shade: #e0b500; - --ion-color-warning-tint: #ffd31a; - - --ion-color-danger: #f04141; - --ion-color-danger-rgb: 245, 61, 61; - --ion-color-danger-contrast: #ffffff; - --ion-color-danger-contrast-rgb: 255, 255, 255; - --ion-color-danger-shade: #d33939; - --ion-color-danger-tint: #f25454; - - --ion-color-dark: #222428; - --ion-color-dark-rgb: 34, 34, 34; - --ion-color-dark-contrast: #ffffff; - --ion-color-dark-contrast-rgb: 255, 255, 255; - --ion-color-dark-shade: #1e2023; - --ion-color-dark-tint: #383a3e; - - --ion-color-medium: #989aa2; - --ion-color-medium-rgb: 152, 154, 162; - --ion-color-medium-contrast: #ffffff; - --ion-color-medium-contrast-rgb: 255, 255, 255; - --ion-color-medium-shade: #86888f; - --ion-color-medium-tint: #a2a4ab; - - --ion-color-light: #f4f5f8; - --ion-color-light-rgb: 244, 244, 244; - --ion-color-light-contrast: #000000; - --ion-color-light-contrast-rgb: 0, 0, 0; - --ion-color-light-shade: #d7d8da; - --ion-color-light-tint: #f5f6f9; -} - -/* Additional Ionic Colors -// -------------------------------------------------- -// In order to add colors to be used with Ionic components, -// the color should be added as a class with the convention `.ion-color-{COLOR}` -// where `{COLOR}` is the color to be used on the Ionic component -// and each variant is defined for the color. For more information, please see -// https://beta.ionicframework.com/docs/theming/advanced -*/ - -.ion-color-favorite { - --ion-color-base: #69bb7b; - --ion-color-base-rgb: 105, 187, 123; - --ion-color-contrast: #ffffff; - --ion-color-contrast-rgb: 255, 255, 255; - --ion-color-shade: #5ca56c; - --ion-color-tint: #78c288; -} - -.ion-color-twitter { - --ion-color-base: #1da1f4; - --ion-color-base-rgb: 29, 161, 244; - --ion-color-contrast: #ffffff; - --ion-color-contrast-rgb: 255, 255, 255; - --ion-color-shade: #1a8ed7; - --ion-color-tint: #34aaf5; -} - -.ion-color-google { - --ion-color-base: #dc4a38; - --ion-color-base-rgb: 220, 74, 56; - --ion-color-contrast: #ffffff; - --ion-color-contrast-rgb: 255, 255, 255; - --ion-color-shade: #c24131; - --ion-color-tint: #e05c4c; -} - -.ion-color-vimeo { - --ion-color-base: #23b6ea; - --ion-color-base-rgb: 35, 182, 234; - --ion-color-contrast: #ffffff; - --ion-color-contrast-rgb: 255, 255, 255; - --ion-color-shade: #1fa0ce; - --ion-color-tint: #39bdec; -} - -.ion-color-facebook { - --ion-color-base: #3b5998; - --ion-color-base-rgb: 59, 89, 152; - --ion-color-contrast: #ffffff; - --ion-color-contrast-rgb: 255, 255, 255; - --ion-color-shade: #344e86; - --ion-color-tint: #4f6aa2; -} - -/* Shared Variables -// -------------------------------------------------- -// To customize the look and feel of this app, you can override -// the CSS variables found in Ionic's source files. -// To view all the possible Ionic variables, see: -// https://beta.ionicframework.com/docs/theming/css-variables#ionic-variables -*/ - -:root { - --ion-headings-font-weight: 300; - - --ion-color-angular: #ac282b; - --ion-color-communication: #8e8d93; - --ion-color-tooling: #fe4c52; - --ion-color-services: #fd8b2d; - --ion-color-design: #fed035; - --ion-color-workshop: #69bb7b; - --ion-color-food: #3bc7c4; - --ion-color-documentation: #b16be3; - --ion-color-navigation: #6600cc; -} - -.md { - --ion-toolbar-background: var(--ion-color-primary); - --ion-toolbar-color: #fff; - --ion-toolbar-color-activated: #fff; -} - - - diff --git a/src/theme/variables.css b/src/theme/variables.css index fc2b32d1..7bb20392 100644 --- a/src/theme/variables.css +++ b/src/theme/variables.css @@ -1,34 +1,27 @@ +/* + * Ionic Variables and Theming + * ---------------------------------------------------------------------------- + * For more information, please see + * https://www.ionicframework.com/docs/theming/ + */ -/* Ionic Variables and Theming. For more information, please see -// https://beta.ionicframework.com/docs/theming/ -// The app direction is used to include -// rtl styles in your app. For more information, please see -// https://beta.ionicframework.com/docs/layout/rtl -// $app-direction: ltr; -// Ionic Colors -// -------------------------------------------------- -// Named colors makes it easy to reuse colors on various components. -// It's highly recommended to change the default colors -// to match your app's branding. Ionic provides eight layered colors -// that can be changed to theme an app. Additional colors can be -// added as well (see below). For more information, please see -// https://beta.ionicframework.com/docs/theming/advanced -// To easily create custom color palettes for your app’s UI, -// check out our color generator: -// https://beta.ionicframework.com/docs/theming/color-generator -*/ - -:root { - --ion-color-angular: #ac282b; - --ion-color-communication: #8e8d93; - --ion-color-tooling: #fe4c52; - --ion-color-services: #fd8b2d; - --ion-color-design: #fed035; - --ion-color-workshop: #69bb7b; - --ion-color-food: #3bc7c4; - --ion-color-documentation: #b16be3; - --ion-color-navigation: #6600cc; +/* + * Ionic Colors + * ---------------------------------------------------------------------------- + * Named colors make it easy to reuse colors on various components. + * It's highly recommended to change the default colors + * to match your app's branding. Ionic provides nine layered colors + * that can be changed to theme an app. Additional colors can be + * added as well (see below). For more information, please see + * https://www.ionicframework.com/docs/theming/colors + * + * To easily create custom color palettes for your app’s UI, + * check out our color generator: + * https://www.ionicframework.com/docs/theming/color-generator + */ + :root { + /** primary **/ --ion-color-primary: #3880ff; --ion-color-primary-rgb: 56, 128, 255; --ion-color-primary-contrast: #ffffff; @@ -36,124 +29,202 @@ --ion-color-primary-shade: #3171e0; --ion-color-primary-tint: #4c8dff; - --ion-color-secondary: #0cd1e8; - --ion-color-secondary-rgb: 12, 209, 232; + /** secondary **/ + --ion-color-secondary: #3dc2ff; + --ion-color-secondary-rgb: 61, 194, 255; --ion-color-secondary-contrast: #ffffff; --ion-color-secondary-contrast-rgb: 255, 255, 255; - --ion-color-secondary-shade: #0bb8cc; - --ion-color-secondary-tint: #24d6ea; + --ion-color-secondary-shade: #36abe0; + --ion-color-secondary-tint: #50c8ff; - --ion-color-tertiary: #7044ff; - --ion-color-tertiary-rgb: 112, 68, 255; + /** tertiary **/ + --ion-color-tertiary: #5260ff; + --ion-color-tertiary-rgb: 82, 96, 255; --ion-color-tertiary-contrast: #ffffff; --ion-color-tertiary-contrast-rgb: 255, 255, 255; - --ion-color-tertiary-shade: #633ce0; - --ion-color-tertiary-tint: #7e57ff; + --ion-color-tertiary-shade: #4854e0; + --ion-color-tertiary-tint: #6370ff; - --ion-color-success: #10dc60; - --ion-color-success-rgb: 16, 220, 96; + /** success **/ + --ion-color-success: #2dd36f; + --ion-color-success-rgb: 45, 211, 111; --ion-color-success-contrast: #ffffff; --ion-color-success-contrast-rgb: 255, 255, 255; - --ion-color-success-shade: #0ec254; - --ion-color-success-tint: #28e070; - - --ion-color-warning: #ffce00; - --ion-color-warning-rgb: 255, 206, 0; - --ion-color-warning-contrast: #ffffff; - --ion-color-warning-contrast-rgb: 255, 255, 255; - --ion-color-warning-shade: #e0b500; - --ion-color-warning-tint: #ffd31a; - - --ion-color-danger: #f04141; - --ion-color-danger-rgb: 245, 61, 61; + --ion-color-success-shade: #28ba62; + --ion-color-success-tint: #42d77d; + + /** warning **/ + --ion-color-warning: #ffc409; + --ion-color-warning-rgb: 255, 196, 9; + --ion-color-warning-contrast: #000000; + --ion-color-warning-contrast-rgb: 0, 0, 0; + --ion-color-warning-shade: #e0ac08; + --ion-color-warning-tint: #ffca22; + + /** danger **/ + --ion-color-danger: #eb445a; + --ion-color-danger-rgb: 235, 68, 90; --ion-color-danger-contrast: #ffffff; --ion-color-danger-contrast-rgb: 255, 255, 255; - --ion-color-danger-shade: #d33939; - --ion-color-danger-tint: #f25454; + --ion-color-danger-shade: #cf3c4f; + --ion-color-danger-tint: #ed576b; + /** dark **/ --ion-color-dark: #222428; - --ion-color-dark-rgb: 34, 34, 34; + --ion-color-dark-rgb: 34, 36, 40; --ion-color-dark-contrast: #ffffff; --ion-color-dark-contrast-rgb: 255, 255, 255; --ion-color-dark-shade: #1e2023; --ion-color-dark-tint: #383a3e; - --ion-color-medium: #989aa2; - --ion-color-medium-rgb: 152, 154, 162; + /** medium **/ + --ion-color-medium: #92949c; + --ion-color-medium-rgb: 146, 148, 156; --ion-color-medium-contrast: #ffffff; --ion-color-medium-contrast-rgb: 255, 255, 255; - --ion-color-medium-shade: #86888f; - --ion-color-medium-tint: #a2a4ab; + --ion-color-medium-shade: #808289; + --ion-color-medium-tint: #9d9fa6; + /** light **/ --ion-color-light: #f4f5f8; - --ion-color-light-rgb: 244, 244, 244; + --ion-color-light-rgb: 244, 245, 248; --ion-color-light-contrast: #000000; --ion-color-light-contrast-rgb: 0, 0, 0; --ion-color-light-shade: #d7d8da; --ion-color-light-tint: #f5f6f9; } -/* Additional Ionic Colors -// -------------------------------------------------- -// In order to add colors to be used with Ionic components, -// the color should be added as a class with the convention `.ion-color-{COLOR}` -// where `{COLOR}` is the color to be used on the Ionic component -// and each variant is defined for the color. For more information, please see -// https://beta.ionicframework.com/docs/theming/advanced -*/ + +/* + * Additional Ionic Colors + * ---------------------------------------------------------------------------- + * In order to add colors to be used within Ionic components, + * the color should be added as a class with the convention `.ion-color-{COLOR}` + * where `{COLOR}` is the color to be used on the Ionic component. + * For more information on adding new colors, please see + * https://ionicframework.com/docs/theming/colors#adding-colors + * + * To generate the code for a new color, check out our new color creator: + * https://ionicframework.com/docs/theming/colors#new-color-creator + */ + + :root { + --ion-color-favorite: #69bb7b; + --ion-color-favorite-rgb: 105,187,123; + --ion-color-favorite-contrast: #ffffff; + --ion-color-favorite-contrast-rgb: 255,255,255; + --ion-color-favorite-shade: #5ca56c; + --ion-color-favorite-tint: #78c288; + + --ion-color-twitter: #1da1f4; + --ion-color-twitter-rgb: 29,161,244; + --ion-color-twitter-contrast: #ffffff; + --ion-color-twitter-contrast-rgb: 255,255,255; + --ion-color-twitter-shade: #1a8ed7; + --ion-color-twitter-tint: #34aaf5; + + --ion-color-instagram: #5956d8; + --ion-color-instagram-rgb: 89,86,216; + --ion-color-instagram-contrast: #ffffff; + --ion-color-instagram-contrast-rgb: 255,255,255; + --ion-color-instagram-shade: #4e4cbe; + --ion-color-instagram-tint: #6a67dc; + + --ion-color-vimeo: #23b6ea; + --ion-color-vimeo-rgb: 35,182,234; + --ion-color-vimeo-contrast: #ffffff; + --ion-color-vimeo-contrast-rgb: 255,255,255; + --ion-color-vimeo-shade: #1fa0ce; + --ion-color-vimeo-tint: #39bdec; + + --ion-color-facebook: #3b5998; + --ion-color-facebook-rgb: 59,89,152; + --ion-color-facebook-contrast: #ffffff; + --ion-color-facebook-contrast-rgb: 255,255,255; + --ion-color-facebook-shade: #344e86; + --ion-color-facebook-tint: #4f6aa2; +} .ion-color-favorite { - --ion-color-base: #69bb7b; - --ion-color-base-rgb: 105, 187, 123; - --ion-color-contrast: #ffffff; - --ion-color-contrast-rgb: 255, 255, 255; - --ion-color-shade: #5ca56c; - --ion-color-tint: #78c288; + --ion-color-base: var(--ion-color-favorite); + --ion-color-base-rgb: var(--ion-color-favorite-rgb); + --ion-color-contrast: var(--ion-color-favorite-contrast); + --ion-color-contrast-rgb: var(--ion-color-favorite-contrast-rgb); + --ion-color-shade: var(--ion-color-favorite-shade); + --ion-color-tint: var(--ion-color-favorite-tint); } .ion-color-twitter { - --ion-color-base: #1da1f4; - --ion-color-base-rgb: 29, 161, 244; - --ion-color-contrast: #ffffff; - --ion-color-contrast-rgb: 255, 255, 255; - --ion-color-shade: #1a8ed7; - --ion-color-tint: #34aaf5; + --ion-color-base: var(--ion-color-twitter); + --ion-color-base-rgb: var(--ion-color-twitter-rgb); + --ion-color-contrast: var(--ion-color-twitter-contrast); + --ion-color-contrast-rgb: var(--ion-color-twitter-contrast-rgb); + --ion-color-shade: var(--ion-color-twitter-shade); + --ion-color-tint: var(--ion-color-twitter-tint); } .ion-color-google { - --ion-color-base: #dc4a38; - --ion-color-base-rgb: 220, 74, 56; - --ion-color-contrast: #ffffff; - --ion-color-contrast-rgb: 255, 255, 255; - --ion-color-shade: #c24131; - --ion-color-tint: #e05c4c; + --ion-color-base: var(--ion-color-google); + --ion-color-base-rgb: var(--ion-color-google-rgb); + --ion-color-contrast: var(--ion-color-google-contrast); + --ion-color-contrast-rgb: var(--ion-color-google-contrast-rgb); + --ion-color-shade: var(--ion-color-google-shade); + --ion-color-tint: var(--ion-color-google-tint); +} + +.ion-color-instagram { + --ion-color-base: var(--ion-color-instagram); + --ion-color-base-rgb: var(--ion-color-instagram-rgb); + --ion-color-contrast: var(--ion-color-instagram-contrast); + --ion-color-contrast-rgb: var(--ion-color-instagram-contrast-rgb); + --ion-color-shade: var(--ion-color-instagram-shade); + --ion-color-tint: var(--ion-color-instagram-tint); } .ion-color-vimeo { - --ion-color-base: #23b6ea; - --ion-color-base-rgb: 35, 182, 234; - --ion-color-contrast: #ffffff; - --ion-color-contrast-rgb: 255, 255, 255; - --ion-color-shade: #1fa0ce; - --ion-color-tint: #39bdec; + --ion-color-base: var(--ion-color-vimeo); + --ion-color-base-rgb: var(--ion-color-vimeo-rgb); + --ion-color-contrast: var(--ion-color-vimeo-contrast); + --ion-color-contrast-rgb: var(--ion-color-vimeo-contrast-rgb); + --ion-color-shade: var(--ion-color-vimeo-shade); + --ion-color-tint: var(--ion-color-vimeo-tint); } .ion-color-facebook { - --ion-color-base: #3b5998; - --ion-color-base-rgb: 59, 89, 152; + --ion-color-base: var(--ion-color-facebook); + --ion-color-base-rgb: var(--ion-color-facebook-rgb); + --ion-color-contrast: var(--ion-color-facebook-contrast); + --ion-color-contrast-rgb: var(--ion-color-facebook-contrast-rgb); + --ion-color-shade: var(--ion-color-facebook-shade); + --ion-color-tint: var(--ion-color-facebook-tint); +} + +.ion-color-github { + --ion-color-base: #211F1F; + --ion-color-base-rgb: 33,31,31; --ion-color-contrast: #ffffff; - --ion-color-contrast-rgb: 255, 255, 255; - --ion-color-shade: #344e86; - --ion-color-tint: #4f6aa2; + --ion-color-contrast-rgb: 255,255,255; + --ion-color-shade: #1d1b1b; + --ion-color-tint: #373535; } -/* Shared Variables -// -------------------------------------------------- -// To customize the look and feel of this app, you can override -// the CSS variables found in Ionic's source files. -// To view all the possible Ionic variables, see: -// https://beta.ionicframework.com/docs/theming/css-variables#ionic-variables -*/ +.ion-color-instagram { + --ion-color-base: #9537BC; + --ion-color-base-rgb: 149,55,188; + --ion-color-contrast: #ffffff; + --ion-color-contrast-rgb: 255,255,255; + --ion-color-shade: #8330a5; + --ion-color-tint: #a04bc3; +} + +/* + * Shared Variables + * ---------------------------------------------------------------------------- + * To customize the look and feel of this app, you can override + * the CSS variables found in Ionic's source files. + * To view all of the possible Ionic variables, see: + * https://ionicframework.com/docs/theming/css-variables#ionic-variables + */ :root { --ion-headings-font-weight: 300; @@ -169,6 +240,34 @@ --ion-color-navigation: #6600cc; } +/* + * App iOS Variables + * ---------------------------------------------------------------------------- + * iOS only CSS variables can go here + */ + +.ios { + +} + +/* + * App Material Design Variables + * ---------------------------------------------------------------------------- + * Material Design only CSS variables can go here + */ + +.md { + +} + +/* + * App Theme + * ---------------------------------------------------------------------------- + * Ionic apps can have different themes applied, which can + * then be further customized. These variables come last + * so that the above variables are used by default. + */ + /* * Dark Theme * ---------------------------------------------------------------------------- @@ -273,8 +372,7 @@ --ion-toolbar-background: #0d0d0d; - --ion-item-background: #1c1c1c; - --ion-item-background-activated: #313131; + --ion-item-background: #000000; } diff --git a/tslint.json b/tslint.json deleted file mode 100644 index 02ad813b..00000000 --- a/tslint.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": ["tslint-react"] -}