diff --git a/.gitignore b/.gitignore index 71ad79d..a944ffb 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ /npm-debug.log* /testem.log /yarn-error.log +/.php-cs-fixer.cache # ember-try /.node_modules.ember-try/ diff --git a/.php-cs-fixer.cache b/.php-cs-fixer.cache deleted file mode 100644 index fa21dae..0000000 --- a/.php-cs-fixer.cache +++ /dev/null @@ -1 +0,0 @@ -{"php":"8.3.2","version":"3.49.0","indent":" ","lineEnding":"\n","rules":{"align_multiline_comment":true,"array_syntax":{"syntax":"short"},"backtick_to_shell_exec":true,"binary_operator_spaces":{"operators":{"=>":"align","=":"align"}},"blank_line_before_statement":{"statements":["return"]},"braces_position":{"allow_single_line_anonymous_functions":true,"allow_single_line_empty_anonymous_classes":true},"class_attributes_separation":{"elements":{"method":"one"}},"class_definition":{"single_line":true},"class_reference_name_casing":true,"clean_namespace":true,"concat_space":{"spacing":"one"},"declare_parentheses":true,"echo_tag_syntax":true,"empty_loop_body":{"style":"braces"},"empty_loop_condition":true,"fully_qualified_strict_types":true,"function_declaration":true,"general_phpdoc_tag_rename":{"replacements":{"inheritDocs":"inheritDoc"}},"global_namespace_import":{"import_classes":false,"import_constants":false,"import_functions":false},"include":true,"increment_style":{"style":"post"},"integer_literal_case":true,"lambda_not_used_import":true,"linebreak_after_opening_tag":true,"magic_constant_casing":true,"magic_method_casing":true,"method_argument_space":{"on_multiline":"ignore"},"native_function_casing":true,"native_type_declaration_casing":true,"no_alias_language_construct_call":true,"no_alternative_syntax":true,"no_binary_string":true,"no_blank_lines_after_phpdoc":true,"no_empty_comment":true,"no_empty_phpdoc":true,"no_empty_statement":true,"no_extra_blank_lines":{"tokens":["attribute","case","continue","curly_brace_block","default","extra","parenthesis_brace_block","square_brace_block","switch","throw","use"]},"no_leading_namespace_whitespace":true,"no_mixed_echo_print":true,"no_multiline_whitespace_around_double_arrow":true,"no_null_property_initialization":true,"no_short_bool_cast":true,"no_singleline_whitespace_before_semicolons":true,"no_spaces_around_offset":true,"no_superfluous_phpdoc_tags":{"remove_inheritdoc":true},"no_trailing_comma_in_singleline":true,"no_unneeded_braces":{"namespaces":true},"no_unneeded_control_parentheses":{"statements":["break","clone","continue","echo_print","others","return","switch_case","yield","yield_from"]},"no_unneeded_import_alias":true,"no_unset_cast":true,"no_unused_imports":true,"no_useless_concat_operator":true,"no_useless_nullsafe_operator":true,"no_whitespace_before_comma_in_array":true,"normalize_index_brace":true,"nullable_type_declaration_for_default_null_value":true,"object_operator_without_whitespace":true,"operator_linebreak":{"only_booleans":true},"ordered_imports":{"imports_order":["class","function","const"],"sort_algorithm":"alpha"},"ordered_types":{"null_adjustment":"always_last","sort_algorithm":"none"},"php_unit_fqcn_annotation":true,"php_unit_method_casing":true,"phpdoc_align":true,"phpdoc_annotation_without_dot":true,"phpdoc_indent":true,"phpdoc_inline_tag_normalizer":true,"phpdoc_no_access":true,"phpdoc_no_alias_tag":true,"phpdoc_no_package":true,"phpdoc_no_useless_inheritdoc":true,"phpdoc_order":{"order":["param","return","throws"]},"phpdoc_return_self_reference":true,"phpdoc_scalar":true,"phpdoc_separation":{"groups":[["Annotation","NamedArgumentConstructor","Target"],["author","copyright","license"],["category","package","subpackage"],["property","property-read","property-write"],["deprecated","link","see","since"]]},"phpdoc_single_line_var_spacing":true,"phpdoc_summary":true,"phpdoc_tag_type":{"tags":{"inheritDoc":"inline"}},"phpdoc_to_comment":true,"phpdoc_trim":true,"phpdoc_trim_consecutive_blank_line_separation":true,"phpdoc_types":true,"phpdoc_types_order":{"null_adjustment":"always_last","sort_algorithm":"none"},"phpdoc_var_without_name":true,"semicolon_after_instruction":true,"simple_to_complex_string_variable":true,"single_class_element_per_statement":true,"single_import_per_statement":true,"single_line_comment_spacing":true,"single_line_comment_style":{"comment_types":["hash"]},"single_line_throw":true,"single_quote":true,"single_space_around_construct":true,"space_after_semicolon":{"remove_in_empty_for_expressions":true},"standardize_increment":true,"standardize_not_equals":true,"statement_indentation":{"stick_comment_to_next_continuous_control_statement":true},"switch_continue_to_break":true,"trailing_comma_in_multiline":true,"trim_array_spaces":true,"type_declaration_spaces":true,"types_spaces":true,"unary_operator_spaces":true,"whitespace_after_comma_in_array":true,"cast_spaces":true,"blank_line_after_opening_tag":true,"blank_line_between_import_groups":true,"blank_lines_before_namespace":true,"compact_nullable_type_declaration":true,"declare_equal_normalize":true,"lowercase_cast":true,"lowercase_static_reference":true,"new_with_parentheses":true,"no_blank_lines_after_class_opening":true,"no_leading_import_slash":true,"no_whitespace_in_blank_line":true,"ordered_class_elements":{"order":["use_trait"]},"return_type_declaration":true,"short_scalar_cast":true,"single_trait_insert_per_statement":true,"ternary_operator_spaces":true,"visibility_required":true,"blank_line_after_namespace":true,"constant_case":true,"control_structure_braces":true,"control_structure_continuation_position":true,"elseif":true,"indentation_type":true,"line_ending":true,"lowercase_keywords":true,"no_break_comment":true,"no_closing_tag":true,"no_multiple_statements_per_line":true,"no_space_around_double_colon":true,"no_spaces_after_function_name":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_line_after_imports":true,"spaces_inside_parentheses":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"encoding":true,"full_opening_tag":true},"hashes":{"server\/tests\/Feature.php":"9c85d3fc3571920ba5e59e6d460c5220","server\/src\/Providers\/RegistryBridgeServiceProvider.php":"58096e732d9cbf3b78f9fad4e9d2ddc4","server\/src\/Models\/RegistryUser.php":"c210bf9221b71148b95b130a1acdd1c4","server\/src\/Http\/Controllers\/Internal\/v1\/RegistryAuthController.php":"ff7e415c21ea0e16300512b58044e077","server\/src\/Http\/Controllers\/Internal\/v1\/RegistryController.php":"3eb08bbe917a48fa3e44ad436cb7692e","server\/src\/routes.php":"4d549319dc0031dbd27103b68f8a62c3",".php-cs-fixer.php":"97d0e7d944ae71fb5a3344df8ae2cd44","server\/src\/Requests\/AddRegistryUserRequest.php":"4c6dabd5b92f00552a557bb98c2c4101","server\/src\/Http\/Requests\/AddRegistryUserRequest.php":"fcf4a10fffa42e90130939577b79b297","server\/src\/Http\/Resources\/RegistryUser.php":"ed3f6b8f7fb792693d325b2b50fe81f9","server\/src\/Http\/Requests\/AuthenticateRegistryUserRequest.php":"a1aaefc85f959cad0873e866c526c94f","server\/src\/Models\/RegistryExtension.php":"93550d881c6a8e67817d1022ad1c1fab","server\/src\/Http\/Requests\/CreateRegistryExtensionRequest.php":"9f6b938816da7d089ec9b11a4056e545","server\/src\/Http\/Filter\/RegistryExtensionFilter.php":"62bc434d2449cb788ab77b2b8c692da0","server\/src\/Http\/Controllers\/Internal\/v1\/RegistryExtensionController.php":"06b34a93626e54a0a9aafa61484a79b4","server\/src\/Http\/Controllers\/RegistryBridgeController.php":"4239a6dd658e0b39532830de9ae66d32"}} \ No newline at end of file diff --git a/addon/controllers/developers/extensions/edit.js b/addon/controllers/developers/extensions/edit.js index 9fb42c3..6cd117b 100644 --- a/addon/controllers/developers/extensions/edit.js +++ b/addon/controllers/developers/extensions/edit.js @@ -7,11 +7,20 @@ import { task } from 'ember-concurrency'; export default class DevelopersExtensionsEditController extends Controller { @service store; @service fetch; - @service currentUser; - @tracked uploadedFile; + @service notifications; + @tracked isReady = false; + @tracked subscriptionModelOptions = ['flat_rate', 'tiered', 'usage']; + @tracked billingPeriodOptions = ['daily', 'weekly', 'monthly', 'quarterly', 'yearly']; + @tracked uploadQueue = []; + acceptedFileTypes = ['image/jpeg', 'image/png', 'image/gif']; @task *save() { - yield this.model.save(); + try { + yield this.model.save(); + this.validateExtensionForReview(); + } catch (error) { + this.notifications.warning(error.message); + } } @task *uploadIcon(file) { @@ -34,11 +43,54 @@ export default class DevelopersExtensionsEditController extends Controller { ); } - @action addTag(tag) { - this.model.tags.pushObject(tag); + @task *uploadBuild(file) { + yield this.fetch.uploadFile.perform(file, { + path: `uploads/extensions/${this.model.id}/builds`, + subject_uuid: this.model.id, + subject_type: 'registry-bridge:registry-extension', + type: 'extension_build', + meta: { + version: this.model.version, + }, + }); + } + + @action queueFile(file) { + // since we have dropzone and upload button within dropzone validate the file state first + // as this method can be called twice from both functions + if (['queued', 'failed', 'timed_out', 'aborted'].indexOf(file.state) === -1) { + return; + } + + // Queue and upload immediatley + this.uploadQueue.pushObject(file); + this.fetch.uploadFile.perform( + file, + { + path: `uploads/extensions/${this.model.id}/screenshots`, + subject_uuid: this.model.id, + subject_type: 'registry-bridge:registry-extension', + type: 'extension_screenshot', + }, + (uploadedFile) => { + this.model.screenshots.pushObject(uploadedFile); + this.uploadQueue.removeObject(file); + }, + () => { + this.uploadQueue.removeObject(file); + // remove file from queue + if (file.queue && typeof file.queue.remove === 'function') { + file.queue.remove(file); + } + } + ); + } + + @action removeFile(file) { + return file.destroyRecord(); } - @action removeTag(index) { - this.model.tags.removeAt(index); + validateExtensionForReview() { + // run checks to see if extension is ready fo review } } diff --git a/addon/controllers/developers/extensions/new.js b/addon/controllers/developers/extensions/new.js index fa3207a..2dea00a 100644 --- a/addon/controllers/developers/extensions/new.js +++ b/addon/controllers/developers/extensions/new.js @@ -1,6 +1,7 @@ import Controller from '@ember/controller'; import { tracked } from '@glimmer/tracking'; import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; import { task } from 'ember-concurrency'; export default class DevelopersExtensionsNewController extends Controller { @@ -18,4 +19,14 @@ export default class DevelopersExtensionsNewController extends Controller { } return this.hostRouter.transitionTo('console.registry-bridge.developers.extensions.edit', this.extension); } + + @action cancel() { + this.reset(); + return this.hostRouter.transitionTo('console.registry-bridge.developers.extensions'); + } + + reset() { + this.extension.destroyRecord(); + this.extension = this.store.createRecord('registry-extension'); + } } diff --git a/addon/controllers/explore/category.js b/addon/controllers/explore/category.js new file mode 100644 index 0000000..ffdb2fa --- /dev/null +++ b/addon/controllers/explore/category.js @@ -0,0 +1,6 @@ +import Controller from '@ember/controller'; +import { tracked } from '@glimmer/tracking'; + +export default class ExploreCategoryController extends Controller { + @tracked category; +} diff --git a/addon/models/registry-extension.js b/addon/models/registry-extension.js index a1f0d28..a2d225c 100644 --- a/addon/models/registry-extension.js +++ b/addon/models/registry-extension.js @@ -1,4 +1,5 @@ -import Model, { attr, belongsTo } from '@ember-data/model'; +import Model, { attr, belongsTo, hasMany } from '@ember-data/model'; +import { action } from '@ember/object'; export default class RegistryExtensionModel extends Model { /** @ids */ @@ -13,22 +14,24 @@ export default class RegistryExtensionModel extends Model { @belongsTo('company') company; @belongsTo('user') user; @belongsTo('file') icon; + @hasMany('file') screenshots; /** @attributes */ @attr('string', { defaultValue: 'https://flb-assets.s3.ap-southeast-1.amazonaws.com/static/default-extension-icon.svg' }) icon_url; @attr('string') name; @attr('string') subtitle; @attr('boolean') payment_required; - @attr('number') price; - @attr('number') sale_price; + @attr('string') price; + @attr('string') sale_price; @attr('boolean') on_sale; @attr('boolean') subscription_required; - @attr('string') subscription_billing_period; - @attr('string') subscription_model; - @attr('number') subscription_amount; - @attr('object') subscription_tiers; + @attr('string', { defaultValue: 'flat_rate' }) subscription_model; + @attr('string', { defaultValue: 'monthly' }) subscription_billing_period; + @attr('string') subscription_amount; + @attr('array') subscription_tiers; + @attr('string', { defaultValue: 'USD' }) currency; @attr('string') slug; - @attr('string') version; + @attr('string', { defaultValue: '1.0.0' }) version; @attr('string') fa_icon; @attr('string') description; @attr('string') promotional_text; @@ -49,4 +52,35 @@ export default class RegistryExtensionModel extends Model { @attr('date') created_at; @attr('date') updated_at; @attr('date') deleted_at; + + /** @methods */ + /** + * Adds a new tag to the tags array. + * + * This method takes a tag and adds it to the 'tags' array property + * of the current instance. The 'pushObject' method is used, which is + * typically available in Ember.js or similar frameworks that extend + * JavaScript array functionalities. + * + * @param {string} tag - The tag to be added to the tags array. + */ + @action addTag(tag) { + this.tags.push(tag); + this.tags = [...this.tags]; + } + + /** + * Removes a tag from the tags array at a specific index. + * + * This method takes an index and removes the element at that position + * from the 'tags' array property of the current instance. The 'removeAt' + * method is used, which is typically available in Ember.js or similar + * frameworks that provide extended array functionalities. + * + * @param {number} index - The index of the tag to be removed from the tags array. + */ + @action removeTag(index) { + this.tags.removeAt(index); + this.tags = [...this.tags]; + } } diff --git a/addon/routes.js b/addon/routes.js index b9bdbdc..5edd66e 100644 --- a/addon/routes.js +++ b/addon/routes.js @@ -8,5 +8,12 @@ export default buildRoutes(function () { this.route('edit', { path: '/edit/:public_id' }); this.route('details', { path: '/:public_id' }); }); + this.route('analytics'); + this.route('payments'); + this.route('credentials'); + }); + this.route('explore', function () { + this.route('index', { path: '/' }); + this.route('category', { path: '/:category' }); }); }); diff --git a/addon/routes/explore/category.js b/addon/routes/explore/category.js new file mode 100644 index 0000000..3b50a9c --- /dev/null +++ b/addon/routes/explore/category.js @@ -0,0 +1,15 @@ +import Route from '@ember/routing/route'; +import { tracked } from '@glimmer/tracking'; + +export default class ExploreCategoryRoute extends Route { + @tracked category; + + model(params) { + this.category = params.category; + } + + setupController(controller) { + super.setupController(...arguments); + controller.category = this.category; + } +} diff --git a/addon/routes/explore/index.js b/addon/routes/explore/index.js new file mode 100644 index 0000000..ac898aa --- /dev/null +++ b/addon/routes/explore/index.js @@ -0,0 +1,3 @@ +import Route from '@ember/routing/route'; + +export default class ExploreIndexRoute extends Route {} diff --git a/addon/styles/registry-bridge-engine.css b/addon/styles/registry-bridge-engine.css new file mode 100644 index 0000000..8061bfc --- /dev/null +++ b/addon/styles/registry-bridge-engine.css @@ -0,0 +1,4 @@ +.developer-extensions-index-container { + margin: auto; + padding: 2rem 2.25rem; +} diff --git a/addon/templates/application.hbs b/addon/templates/application.hbs index 233fde1..a94650d 100644 --- a/addon/templates/application.hbs +++ b/addon/templates/application.hbs @@ -1,6 +1,10 @@ + + Explore All + Telematics + - Extensions + Extensions Analytics Payments Credentials diff --git a/addon/templates/developers/analytics.hbs b/addon/templates/developers/analytics.hbs index 92355f9..e2147ca 100644 --- a/addon/templates/developers/analytics.hbs +++ b/addon/templates/developers/analytics.hbs @@ -1,2 +1 @@ -{{page-title "Analytics"}} {{outlet}} \ No newline at end of file diff --git a/addon/templates/developers/credentials.hbs b/addon/templates/developers/credentials.hbs index ea517c0..e2147ca 100644 --- a/addon/templates/developers/credentials.hbs +++ b/addon/templates/developers/credentials.hbs @@ -1,2 +1 @@ -{{page-title "Credentials"}} {{outlet}} \ No newline at end of file diff --git a/addon/templates/developers/extensions/edit.hbs b/addon/templates/developers/extensions/edit.hbs index 946f414..81cf33f 100644 --- a/addon/templates/developers/extensions/edit.hbs +++ b/addon/templates/developers/extensions/edit.hbs @@ -1,4 +1,8 @@ - + +