@fleetbase/solid-engine 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/ACL_SOLUTION.md +72 -0
  2. package/CSS_SCOPE_ISSUE.md +140 -0
  3. package/HOTFIX_SYNTAX_ERROR.md +100 -0
  4. package/LICENSE.md +651 -21
  5. package/MANUAL_ACL_SETUP.md +135 -0
  6. package/README.md +74 -27
  7. package/REFACTORING_SUMMARY.md +330 -0
  8. package/VERIFICATION_CHECKLIST.md +82 -0
  9. package/addon/components/modals/create-solid-folder.hbs +29 -0
  10. package/addon/components/modals/import-solid-resources.hbs +85 -0
  11. package/addon/controllers/data/content.js +17 -0
  12. package/addon/controllers/data/index.js +219 -0
  13. package/addon/controllers/home.js +84 -0
  14. package/addon/engine.js +1 -24
  15. package/addon/extension.js +26 -0
  16. package/addon/routes/data/content.js +11 -0
  17. package/addon/routes/data/index.js +17 -0
  18. package/addon/routes.js +2 -7
  19. package/addon/styles/solid-engine.css +1 -2
  20. package/addon/templates/account.hbs +3 -3
  21. package/addon/templates/application.hbs +2 -12
  22. package/addon/templates/data/content.hbs +48 -0
  23. package/addon/templates/{pods/explorer.hbs → data/index.hbs} +6 -5
  24. package/addon/templates/home.hbs +168 -10
  25. package/app/components/modals/{backup-pod.js → create-solid-folder.js} +1 -1
  26. package/app/components/modals/{resync-pod.js → import-solid-resources.js} +1 -1
  27. package/app/components/modals/{create-pod.js → setup-css-credentials.js} +1 -1
  28. package/composer.json +5 -11
  29. package/extension.json +2 -2
  30. package/index.js +0 -11
  31. package/package.json +9 -9
  32. package/server/migrations/2024_12_21_add_css_credentials_to_solid_identities_table.php +32 -0
  33. package/server/src/Client/OpenIDConnectClient.php +686 -15
  34. package/server/src/Client/SolidClient.php +104 -8
  35. package/server/src/Http/Controllers/DataController.php +261 -0
  36. package/server/src/Http/Controllers/OIDCController.php +42 -8
  37. package/server/src/Http/Controllers/SolidController.php +179 -85
  38. package/server/src/Models/SolidIdentity.php +13 -3
  39. package/server/src/Services/AclService.php +146 -0
  40. package/server/src/Services/PodService.php +863 -0
  41. package/server/src/Services/ResourceSyncService.php +336 -0
  42. package/server/src/Services/VehicleSyncService.php +289 -0
  43. package/server/src/Support/Utils.php +10 -0
  44. package/server/src/routes.php +25 -1
  45. package/addon/components/modals/backup-pod.hbs +0 -3
  46. package/addon/components/modals/create-pod.hbs +0 -5
  47. package/addon/components/modals/resync-pod.hbs +0 -3
  48. package/addon/controllers/pods/explorer/content.js +0 -12
  49. package/addon/controllers/pods/explorer.js +0 -149
  50. package/addon/controllers/pods/index/pod.js +0 -12
  51. package/addon/controllers/pods/index.js +0 -137
  52. package/addon/routes/pods/explorer/content.js +0 -10
  53. package/addon/routes/pods/explorer.js +0 -44
  54. package/addon/routes/pods/index/pod.js +0 -3
  55. package/addon/routes/pods/index.js +0 -21
  56. package/addon/templates/pods/explorer/content.hbs +0 -19
  57. package/addon/templates/pods/index/pod.hbs +0 -11
  58. package/addon/templates/pods/index.hbs +0 -19
  59. package/server/src/LegacyClient/Identity/IdentityProvider.php +0 -174
  60. package/server/src/LegacyClient/Identity/Profile.php +0 -18
  61. package/server/src/LegacyClient/OIDCClient.php +0 -350
  62. package/server/src/LegacyClient/Profile/WebID.php +0 -26
  63. package/server/src/LegacyClient/SolidClient.php +0 -271
@@ -0,0 +1,29 @@
1
+ <Modal::Default
2
+ @modalIsOpened={{@modalIsOpened}}
3
+ @options={{@options}}
4
+ @confirm={{@options.confirm}}
5
+ @decline={{@options.decline}}
6
+ >
7
+ <div class="modal-body-container">
8
+ <div class="space-y-4">
9
+ <InputGroup @name="Folder Name" @wrapperClass="mb-0">
10
+ <Input
11
+ @type="text"
12
+ @value={{@options.folderName}}
13
+ placeholder="Enter folder name (e.g., vehicles, drivers)"
14
+ class="w-full form-input"
15
+ />
16
+ </InputGroup>
17
+
18
+ <div class="text-sm text-gray-600 dark:text-gray-400">
19
+ <p>This will create a new folder in your Solid pod for organizing your data.</p>
20
+ </div>
21
+
22
+ {{#if @options.error}}
23
+ <div class="bg-red-50 dark:bg-red-900 border border-red-200 dark:border-red-700 rounded p-3">
24
+ <p class="text-sm text-red-800 dark:text-red-200">{{@options.error}}</p>
25
+ </div>
26
+ {{/if}}
27
+ </div>
28
+ </div>
29
+ </Modal::Default>
@@ -0,0 +1,85 @@
1
+ <Modal::Default
2
+ @modalIsOpened={{@modalIsOpened}}
3
+ @options={{@options}}
4
+ @confirm={{@options.confirm}}
5
+ @decline={{@options.decline}}
6
+ >
7
+ <div class="modal-body-container">
8
+ <div class="space-y-4">
9
+ <div>
10
+ <p class="text-gray-700 dark:text-gray-300 mb-4">
11
+ Select the Fleetops resources you want to import into your Solid pod:
12
+ </p>
13
+
14
+ <div class="space-y-3">
15
+ <label class="flex items-center p-3 bg-gray-50 dark:bg-gray-800 rounded cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700">
16
+ <input
17
+ type="checkbox"
18
+ checked={{@options.resourceTypes.vehicles}}
19
+ {{on "change" (fn @options.toggleResourceType "vehicles")}}
20
+ class="form-checkbox h-5 w-5 text-blue-600"
21
+ />
22
+ <div class="ml-3">
23
+ <div class="font-medium text-gray-900 dark:text-white">Vehicles</div>
24
+ <div class="text-sm text-gray-600 dark:text-gray-400">Import all vehicles from Fleetops</div>
25
+ </div>
26
+ </label>
27
+
28
+ <label class="flex items-center p-3 bg-gray-50 dark:bg-gray-800 rounded cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700">
29
+ <input
30
+ type="checkbox"
31
+ checked={{@options.resourceTypes.drivers}}
32
+ {{on "change" (fn @options.toggleResourceType "drivers")}}
33
+ class="form-checkbox h-5 w-5 text-blue-600"
34
+ />
35
+ <div class="ml-3">
36
+ <div class="font-medium text-gray-900 dark:text-white">Drivers</div>
37
+ <div class="text-sm text-gray-600 dark:text-gray-400">Import all drivers from Fleetops</div>
38
+ </div>
39
+ </label>
40
+
41
+ <label class="flex items-center p-3 bg-gray-50 dark:bg-gray-800 rounded cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700">
42
+ <input
43
+ type="checkbox"
44
+ checked={{@options.resourceTypes.contacts}}
45
+ {{on "change" (fn @options.toggleResourceType "contacts")}}
46
+ class="form-checkbox h-5 w-5 text-blue-600"
47
+ />
48
+ <div class="ml-3">
49
+ <div class="font-medium text-gray-900 dark:text-white">Contacts</div>
50
+ <div class="text-sm text-gray-600 dark:text-gray-400">Import all contacts/customers from Fleetops</div>
51
+ </div>
52
+ </label>
53
+
54
+ <label class="flex items-center p-3 bg-gray-50 dark:bg-gray-800 rounded cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700">
55
+ <input
56
+ type="checkbox"
57
+ checked={{@options.resourceTypes.orders}}
58
+ {{on "change" (fn @options.toggleResourceType "orders")}}
59
+ class="form-checkbox h-5 w-5 text-blue-600"
60
+ />
61
+ <div class="ml-3">
62
+ <div class="font-medium text-gray-900 dark:text-white">Orders</div>
63
+ <div class="text-sm text-gray-600 dark:text-gray-400">Import all orders from Fleetops</div>
64
+ </div>
65
+ </label>
66
+ </div>
67
+ </div>
68
+
69
+ {{#if @options.importProgress}}
70
+ <div class="bg-blue-50 dark:bg-blue-900 border border-blue-200 dark:border-blue-700 rounded p-3">
71
+ <div class="flex items-center">
72
+ <Spinner class="mr-3" />
73
+ <p class="text-sm text-blue-800 dark:text-blue-200">{{@options.importProgress}}</p>
74
+ </div>
75
+ </div>
76
+ {{/if}}
77
+
78
+ {{#if @options.error}}
79
+ <div class="bg-red-50 dark:bg-red-900 border border-red-200 dark:border-red-700 rounded p-3">
80
+ <p class="text-sm text-red-800 dark:text-red-200">{{@options.error}}</p>
81
+ </div>
82
+ {{/if}}
83
+ </div>
84
+ </div>
85
+ </Modal::Default>
@@ -0,0 +1,17 @@
1
+ import Controller from '@ember/controller';
2
+ import { action } from '@ember/object';
3
+ import { inject as service } from '@ember/service';
4
+
5
+ export default class DataContentController extends Controller {
6
+ @service hostRouter;
7
+
8
+ @action back() {
9
+ this.hostRouter.transitionTo('console.solid-protocol.data.index');
10
+ }
11
+
12
+ @action viewFile() {
13
+ if (this.model.url) {
14
+ window.open(this.model.url, '_blank');
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,219 @@
1
+ import Controller from '@ember/controller';
2
+ import { action } from '@ember/object';
3
+ import { inject as service } from '@ember/service';
4
+ import { tracked } from '@glimmer/tracking';
5
+ import { task, timeout } from 'ember-concurrency';
6
+
7
+ export default class DataIndexController extends Controller {
8
+ @service hostRouter;
9
+ @service fetch;
10
+ @service notifications;
11
+ @service modalsManager;
12
+ @service crud;
13
+ @tracked query = '';
14
+ queryParams = ['query'];
15
+ columns = [
16
+ {
17
+ label: 'Name',
18
+ valuePath: 'name',
19
+ width: '75%',
20
+ cellComponent: 'table/cell/pod-content-name',
21
+ onClick: this.viewContents,
22
+ },
23
+ {
24
+ label: 'Type',
25
+ valuePath: 'type',
26
+ cellClassNames: 'capitalize',
27
+ width: '5%',
28
+ },
29
+ {
30
+ label: 'Size',
31
+ valuePath: 'size',
32
+ width: '5%',
33
+ },
34
+ {
35
+ label: 'Created At',
36
+ valuePath: 'created_at',
37
+ width: '15%',
38
+ },
39
+ {
40
+ label: '',
41
+ cellComponent: 'table/cell/pod-content-actions',
42
+ ddButtonText: false,
43
+ ddButtonIcon: 'ellipsis-h',
44
+ ddButtonIconPrefix: 'fas',
45
+ ddMenuLabel: 'Actions',
46
+ cellClassNames: 'overflow-visible',
47
+ wrapperClass: 'flex items-center justify-end mx-2',
48
+ width: '10%',
49
+ actions: (content) => {
50
+ return [
51
+ {
52
+ label: content.type === 'folder' ? 'Browse Folder' : 'View Contents',
53
+ fn: this.viewContents,
54
+ },
55
+ {
56
+ separator: true,
57
+ },
58
+ {
59
+ label: 'Delete',
60
+ fn: this.deleteItem,
61
+ },
62
+ ];
63
+ },
64
+ sortable: false,
65
+ filterable: false,
66
+ resizable: false,
67
+ searchable: false,
68
+ },
69
+ ];
70
+
71
+ @action reload() {
72
+ this.hostRouter.refresh();
73
+ }
74
+
75
+ @action back() {
76
+ this.hostRouter.transitionTo('console.solid-protocol.home');
77
+ }
78
+
79
+ @action viewContents(content) {
80
+ if (content.type === 'folder') {
81
+ return this.hostRouter.transitionTo('console.solid-protocol.data.content', content.slug);
82
+ }
83
+
84
+ if (content.type === 'file') {
85
+ // Open file viewer or download
86
+ window.open(content.url, '_blank');
87
+ }
88
+ }
89
+
90
+ @action createFolder() {
91
+ this.modalsManager.show('modals/create-solid-folder', {
92
+ title: 'Create New Folder',
93
+ acceptButtonText: 'Create',
94
+ acceptButtonIcon: 'folder-plus',
95
+ folderName: '',
96
+ keepOpen: true,
97
+ confirm: async (modal) => {
98
+ const folderName = modal.getOption('folderName');
99
+ if (!folderName) {
100
+ return this.notifications.warning('Please enter a folder name.');
101
+ }
102
+
103
+ modal.startLoading();
104
+
105
+ try {
106
+ const response = await this.fetch.post(
107
+ 'data/folder',
108
+ {
109
+ name: folderName,
110
+ },
111
+ {
112
+ namespace: 'solid/int/v1',
113
+ }
114
+ );
115
+
116
+ if (response.success) {
117
+ this.notifications.success(`Folder "${folderName}" created successfully!`);
118
+ this.hostRouter.refresh();
119
+ return modal.done();
120
+ }
121
+
122
+ this.notifications.error(response.error || 'Failed to create folder.');
123
+ } catch (error) {
124
+ this.notifications.serverError(error);
125
+ } finally {
126
+ modal.stopLoading();
127
+ }
128
+ },
129
+ });
130
+ }
131
+
132
+ @action importResources() {
133
+ const resourceTypes = {
134
+ vehicles: false,
135
+ drivers: false,
136
+ contacts: false,
137
+ orders: false,
138
+ };
139
+
140
+ this.modalsManager.show('modals/import-solid-resources', {
141
+ title: 'Import Fleetops Resources',
142
+ acceptButtonText: 'Import Selected',
143
+ acceptButtonIcon: 'download',
144
+ resourceTypes,
145
+ importProgress: null,
146
+ toggleResourceType: (type) => {
147
+ resourceTypes[type] = !resourceTypes[type];
148
+ },
149
+ confirm: async (modal) => {
150
+ const selected = Object.keys(resourceTypes).filter((type) => resourceTypes[type]);
151
+
152
+ if (selected.length === 0) {
153
+ return this.notifications.warning('Please select at least one resource type to import.');
154
+ }
155
+
156
+ try {
157
+ modal.setOption('importProgress', `Importing ${selected.join(', ')}...`);
158
+
159
+ const response = await this.fetch.post(
160
+ 'data/import',
161
+ {
162
+ resource_types: selected,
163
+ },
164
+ {
165
+ namespace: 'solid/int/v1',
166
+ }
167
+ );
168
+
169
+ if (response.success) {
170
+ this.notifications.success(`Successfully imported ${response.imported_count} resources!`);
171
+ this.hostRouter.refresh();
172
+ return modal.done();
173
+ }
174
+
175
+ this.notifications.error(response.error || 'Failed to import resources.');
176
+ modal.setOption('importProgress', null);
177
+ } catch (error) {
178
+ modal.setOption('importProgress', null);
179
+ this.notifications.serverError(error);
180
+ }
181
+ },
182
+ });
183
+ }
184
+
185
+ @action deleteItem(item) {
186
+ this.modalsManager.confirm({
187
+ title: `Are you sure you want to delete this ${item.type}?`,
188
+ body: `Deleting "${item.name}" will permanently remove it from your storage. This is irreversible!`,
189
+ acceptButtonText: 'Delete Forever',
190
+ confirm: async () => {
191
+ try {
192
+ await this.fetch.delete(`data/${item.type}/${item.slug}`, {}, { namespace: 'solid/int/v1' });
193
+ this.notifications.success(`${item.type === 'folder' ? 'Folder' : 'File'} deleted successfully!`);
194
+ this.hostRouter.refresh();
195
+ } catch (error) {
196
+ this.notifications.serverError(error);
197
+ }
198
+ },
199
+ });
200
+ }
201
+
202
+ @action deleteSelected() {
203
+ const selected = this.table.selectedRows;
204
+
205
+ this.crud.bulkDelete(selected, {
206
+ modelNamePath: 'name',
207
+ acceptButtonText: 'Delete All',
208
+ onSuccess: () => {
209
+ return this.hostRouter.refresh();
210
+ },
211
+ });
212
+ }
213
+
214
+ @task({ restartable: true }) *search(event) {
215
+ yield timeout(300);
216
+ const query = typeof event.target.value === 'string' ? event.target.value : '';
217
+ this.hostRouter.transitionTo('console.solid-protocol.data.index', { queryParams: { query } });
218
+ }
219
+ }
@@ -1,10 +1,30 @@
1
1
  import Controller from '@ember/controller';
2
+ import { tracked } from '@glimmer/tracking';
2
3
  import { inject as service } from '@ember/service';
3
4
  import { task } from 'ember-concurrency';
5
+ import { debug } from '@ember/debug';
4
6
 
5
7
  export default class HomeController extends Controller {
6
8
  @service fetch;
7
9
  @service notifications;
10
+ @service hostRouter;
11
+ @service modalsManager;
12
+ @tracked authStatus = null;
13
+
14
+ constructor() {
15
+ super(...arguments);
16
+ this.checkAuthenticationStatus.perform();
17
+ }
18
+
19
+ @task *checkAuthenticationStatus() {
20
+ try {
21
+ const authStatus = yield this.fetch.get('authentication-status', {}, { namespace: 'solid/int/v1' });
22
+ this.authStatus = authStatus;
23
+ } catch (error) {
24
+ debug('Failed to check authentication status:' + error.message);
25
+ this.authStatus = { authenticated: false, error: error.message };
26
+ }
27
+ }
8
28
 
9
29
  @task *authenticate() {
10
30
  try {
@@ -20,4 +40,68 @@ export default class HomeController extends Controller {
20
40
  @task *getAccountIndex() {
21
41
  yield this.fetch.get('account', {}, { namespace: 'solid/int/v1' });
22
42
  }
43
+
44
+ @task *logout() {
45
+ try {
46
+ yield this.fetch.post('logout', {}, { namespace: 'solid/int/v1' });
47
+ this.notifications.success('Logged out successfully');
48
+ this.authStatus = { authenticated: false };
49
+ } catch (error) {
50
+ this.notifications.serverError(error);
51
+ }
52
+ }
53
+
54
+ @task *refreshStatus() {
55
+ yield this.checkAuthenticationStatus.perform();
56
+ }
57
+
58
+ @task *navigateToPods() {
59
+ yield this.hostRouter.transitionTo('console.solid-protocol.data');
60
+ }
61
+
62
+ @task *navigateToAccount() {
63
+ yield this.hostRouter.transitionTo('console.solid-protocol.account');
64
+ }
65
+
66
+ get isAuthenticated() {
67
+ return this.authStatus?.authenticated === true;
68
+ }
69
+
70
+ get userProfile() {
71
+ return this.authStatus?.profile?.parsed_profile || {};
72
+ }
73
+
74
+ get webId() {
75
+ return this.authStatus?.profile?.webid;
76
+ }
77
+
78
+ get userName() {
79
+ return this.userProfile.name || 'Unknown User';
80
+ }
81
+
82
+ get userEmail() {
83
+ return this.userProfile.email || 'No email available';
84
+ }
85
+
86
+ get serverUrl() {
87
+ // Extract server URL from webId or use default
88
+ const webId = this.webId;
89
+ if (webId) {
90
+ try {
91
+ const url = new URL(webId);
92
+ return `${url.protocol}//${url.host}`;
93
+ } catch (e) {
94
+ // Fallback
95
+ }
96
+ }
97
+ return 'http://localhost:3000';
98
+ }
99
+
100
+ get storageLocations() {
101
+ return this.userProfile.storage_locations || [];
102
+ }
103
+
104
+ get hasStorageLocations() {
105
+ return this.storageLocations.length > 0;
106
+ }
23
107
  }
package/addon/engine.js CHANGED
@@ -2,13 +2,9 @@ import Engine from '@ember/engine';
2
2
  import loadInitializers from 'ember-load-initializers';
3
3
  import Resolver from 'ember-resolver';
4
4
  import config from './config/environment';
5
- import services from '@fleetbase/ember-core/exports/services';
6
- import AdminSolidServerConfigComponent from './components/admin/solid-server-config';
7
- import SolidBrandIconComponent from './components/solid-brand-icon';
5
+ import { services, externalRoutes } from '@fleetbase/ember-core/exports';
8
6
 
9
7
  const { modulePrefix } = config;
10
- const externalRoutes = ['console', 'extensions'];
11
-
12
8
  export default class SolidEngine extends Engine {
13
9
  modulePrefix = modulePrefix;
14
10
  Resolver = Resolver;
@@ -16,25 +12,6 @@ export default class SolidEngine extends Engine {
16
12
  services,
17
13
  externalRoutes,
18
14
  };
19
- setupExtension = function (app, engine, universe) {
20
- // register menu item in header
21
- universe.registerHeaderMenuItem('Solid', 'console.solid-protocol', { iconComponent: SolidBrandIconComponent, iconComponentOptions: { width: 19, height: 19 }, priority: 5 });
22
-
23
- // register admin settings -- create a solid server menu panel with it's own setting options
24
- universe.registerAdminMenuPanel(
25
- 'Solid Protocol',
26
- [
27
- {
28
- title: 'Solid Server Config',
29
- icon: 'sliders',
30
- component: AdminSolidServerConfigComponent,
31
- },
32
- ],
33
- {
34
- slug: 'solid-server',
35
- }
36
- );
37
- };
38
15
  }
39
16
 
40
17
  loadInitializers(SolidEngine, modulePrefix);
@@ -0,0 +1,26 @@
1
+ import { MenuItem, ExtensionComponent } from '@fleetbase/ember-core/contracts';
2
+
3
+ export default {
4
+ setupExtension(app, universe) {
5
+ const menuService = universe.getService('menu');
6
+
7
+ // Register menu item in header
8
+ // const iconOptions = { iconComponent: new ExtensionComponent('@fleetbase/solid-engine', 'solid-brand-icon'), iconComponentOptions: { width: 19, height: 19 } };
9
+ menuService.registerHeaderMenuItem('Solid', 'console.solid-protocol', { priority: 5 });
10
+
11
+ // Register admin settings -- create a solid server menu panel with it's own setting options
12
+ universe.registerAdminMenuPanel(
13
+ 'Solid Protocol',
14
+ [
15
+ new MenuItem({
16
+ title: 'Solid Server Config',
17
+ icon: 'sliders',
18
+ component: new ExtensionComponent('@fleetbase/solid-engine', 'admin/solid-server-config'),
19
+ }),
20
+ ],
21
+ {
22
+ slug: 'solid-server',
23
+ }
24
+ );
25
+ },
26
+ };
@@ -0,0 +1,11 @@
1
+ import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
3
+
4
+ export default class DataContentRoute extends Route {
5
+ @service fetch;
6
+
7
+ model({ slug }) {
8
+ // Fetch folder/container contents within the user's pod
9
+ return this.fetch.get('data/folder', { slug }, { namespace: 'solid/int/v1' });
10
+ }
11
+ }
@@ -0,0 +1,17 @@
1
+ import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
3
+
4
+ export default class DataIndexRoute extends Route {
5
+ @service fetch;
6
+
7
+ queryParams = {
8
+ query: {
9
+ refreshModel: true,
10
+ },
11
+ };
12
+
13
+ model({ query }) {
14
+ // Fetch the user's primary pod data
15
+ return this.fetch.get('data', { query }, { namespace: 'solid/int/v1' });
16
+ }
17
+ }
package/addon/routes.js CHANGED
@@ -3,12 +3,7 @@ import buildRoutes from 'ember-engines/routes';
3
3
  export default buildRoutes(function () {
4
4
  this.route('home', { path: '/' });
5
5
  this.route('account');
6
- this.route('pods', function () {
7
- this.route('explorer', { path: '/explorer/:id' }, function () {
8
- this.route('content', { path: '/~/:slug' });
9
- });
10
- this.route('index', { path: '/' }, function () {
11
- this.route('pod', { path: '/pod/:slug' });
12
- });
6
+ this.route('data', function () {
7
+ this.route('content', { path: '/:slug' });
13
8
  });
14
9
  });
@@ -1,6 +1,4 @@
1
1
  .solid-fleetbase-home-container {
2
- margin: auto;
3
- width: 1200px;
4
2
  padding: 2rem;
5
3
  }
6
4
 
@@ -18,6 +16,7 @@
18
16
 
19
17
  body[data-theme='light'] .solid-fleetbase-home-container a:not([class*='text-']),
20
18
  body[data-theme='dark'] .solid-fleetbase-home-container a:not([class*='text-']),
19
+ .solid-fleetbase-home-container a:not(.next-content-panel-header-left),
21
20
  .solid-fleetbase-home-container a {
22
21
  color: #60a5fa;
23
22
  text-decoration: underline;
@@ -3,7 +3,7 @@
3
3
  <Layout::Section::Body class="overflow-y-scroll h-full">
4
4
  <div class="container mx-auto h-screen">
5
5
  <div class="max-w-3xl my-10 mx-auto">
6
- <ContentPanel @title="Solid Identity" @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
6
+ <ContentPanel @title="Solid Identity" @open={{true}} @wrapperClass="bordered-classic">
7
7
  <form class="flex flex-col md:flex-row" {{on "submit" (perform this.saveProfile)}}>
8
8
  <div class="w-32 flex flex-col justify-center mb-6 mr-6">
9
9
  <Image src={{this.user.avatar_url}} @fallbackSrc={{config "defaultValues.userImage"}} alt={{this.user.name}} class="w-32 h-32 rounded-md" />
@@ -19,7 +19,7 @@
19
19
  {{else}}
20
20
  <FaIcon @icon="image" class="mr-1.5" />
21
21
  <span>
22
- {{t "console.account.index.upload-new"}}
22
+ {{t "common.upload-new-photo"}}
23
23
  </span>
24
24
  {{/if}}
25
25
  </a>
@@ -31,7 +31,7 @@
31
31
  <InputGroup @name={{t "common.email"}} @type="email" @value={{this.user.email}} />
32
32
  </div>
33
33
  <div class="mt-3 flex items-center justify-end">
34
- <Button @buttonType="submit" @type="primary" @size="lg" @icon="save" @text={{t "common.save-button-text"}} @onClick={{perform this.saveProfile}} @isLoading={{not this.saveProfile.isIdle}} />
34
+ <Button @buttonType="submit" @type="primary" @size="lg" @icon="save" @text={{t "common.save-changes"}} @onClick={{perform this.saveProfile}} @isLoading={{not this.saveProfile.isIdle}} />
35
35
  </div>
36
36
  </div>
37
37
  </form>
@@ -1,17 +1,7 @@
1
1
  <EmberWormhole @to="sidebar-menu-items">
2
2
  <Layout::Sidebar::Item @route="console.solid-protocol.home" @icon="home">Home</Layout::Sidebar::Item>
3
- <Layout::Sidebar::Item @route="console.solid-protocol.pods" @icon="folder-tree">Pods</Layout::Sidebar::Item>
4
- {{!-- <Layout::Sidebar::Panel @open={{true}} @title="Pods">
5
- <Layout::Sidebar::Item @route="console.solid-protocol.pods" @icon="folder-tree">All</Layout::Sidebar::Item>
6
- {{#each this.pods as |pod|}}
7
- <LinkTo @route="pods.explorer" @model={{pod}} @query={{hash id=pod.id pod=pod.id}} class="next-nav-item">
8
- <div class="next-nav-item-icon-container">
9
- <FaIcon @icon="folder" @size="xs" />
10
- </div>
11
- <div class="truncate w-10/12 ">{{pod.name}}</div>
12
- </LinkTo>
13
- {{/each}}
14
- </Layout::Sidebar::Panel> --}}
3
+ <Layout::Sidebar::Item @route="console.solid-protocol.data" @icon="database">Data</Layout::Sidebar::Item>
4
+
15
5
  <Layout::Sidebar::Item @route="console.solid-protocol.account" @icon="user">Account</Layout::Sidebar::Item>
16
6
  </EmberWormhole>
17
7