diff --git a/assets/javascripts/discourse/components/hljs-code-view.js.es6 b/assets/javascripts/discourse/components/hljs-code-view.js.es6 new file mode 100644 index 0000000..5f47af8 --- /dev/null +++ b/assets/javascripts/discourse/components/hljs-code-view.js.es6 @@ -0,0 +1,17 @@ +import highlightSyntax from 'discourse/lib/highlight-syntax'; + +export default Ember.Component.extend({ + render(buffer) { + buffer.push("
");
+    buffer.push(Handlebars.Utils.escapeExpression(this.get('value')));
+    buffer.push("
"); + }, + + _refreshHighlight: Discourse.debounce(function() { + this.rerender(); + }, 50).observes('value'), + + _applyHighlight: function() { + highlightSyntax(this.$()); + }.on('didInsertElement') +}); diff --git a/assets/javascripts/discourse/controllers/admin-plugins-explorer.js.es6 b/assets/javascripts/discourse/controllers/admin-plugins-explorer.js.es6 index e900457..4da50b7 100644 --- a/assets/javascripts/discourse/controllers/admin-plugins-explorer.js.es6 +++ b/assets/javascripts/discourse/controllers/admin-plugins-explorer.js.es6 @@ -15,6 +15,10 @@ export default Ember.ArrayController.extend({ saveDisabled: Ember.computed.not('selectedItem.dirty'), runDisabled: Ember.computed.alias('selectedItem.dirty'), + results: Em.computed.alias('selectedItem.results'), + + editing: false, + everEditing: false, selectedItem: function() { const _id = this.get('selectedQueryId'); @@ -25,16 +29,6 @@ export default Ember.ArrayController.extend({ return item || NoQuery; }.property('selectedQueryId'), - results: Em.computed.alias('selectedItem.results'), - - addCreatedRecord(record) { - this.pushObject(record); - this.set('selectedQueryId', Ember.get(record, 'id')); - this.get('selectedItem').set('dirty', false); - this.set('showResults', false); - this.set('results', null); - }, - not_https: function() { return !( window.location.protocol === "https:" || @@ -43,6 +37,28 @@ export default Ember.ArrayController.extend({ ); }.property(), + othersDirty: function() { + const selected = this.get('selectedItem'); + return !!this.get('content').find(function(q) { + return q !== selected && q.get('dirty'); + }); + }.property('selectedItem', 'selectedItem.dirty'), + + setEverEditing: function() { + if (this.get('editing') && !this.get('everEditing')) { + this.set('everEditing', true); + } + }.observes('editing'), + + addCreatedRecord(record) { + this.pushObject(record); + this.set('selectedQueryId', Ember.get(record, 'id')); + this.get('selectedItem').set('dirty', false); + this.set('showResults', false); + this.set('results', null); + this.set('editing', true); + }, + save() { const self = this; this.set('loading', true); diff --git a/assets/javascripts/discourse/routes/admin-plugins-explorer.js.es6 b/assets/javascripts/discourse/routes/admin-plugins-explorer.js.es6 index 9091a82..1a1ee9e 100644 --- a/assets/javascripts/discourse/routes/admin-plugins-explorer.js.es6 +++ b/assets/javascripts/discourse/routes/admin-plugins-explorer.js.es6 @@ -7,6 +7,9 @@ export default Discourse.Route.extend({ const p1 = this.store.findAll('query'); const p2 = Discourse.ajax('/admin/plugins/explorer/schema.json', {cache: true}); return p1.then(function(model) { + model.forEach(function(query) { + query.markNotDirty(); + }); return p2.then(function(schema) { return { content: model, schema: schema }; }); diff --git a/assets/javascripts/discourse/templates/admin/plugins-explorer.hbs b/assets/javascripts/discourse/templates/admin/plugins-explorer.hbs index b8a9f07..c613299 100644 --- a/assets/javascripts/discourse/templates/admin/plugins-explorer.hbs +++ b/assets/javascripts/discourse/templates/admin/plugins-explorer.hbs @@ -20,6 +20,13 @@ {{/if}} +{{#if othersDirty}} +
+ {{fa-icon "warning"}} + {{i18n "explorer.others_dirty"}} +
+{{/if}} +
{{#if selectedItem.fake}} @@ -27,35 +34,44 @@ {{else}}
{{#if selectedItem}} -
- {{#if editing}} + {{#if editing}} +
{{text-field value=selectedItem.name}} - {{else}} +
+
+ {{textarea value=selectedItem.description}} +
+ {{else}} +

{{selectedItem.name}}

{{d-button action="editName" icon="pencil" class="no-text btn-small"}} - {{/if}} -
-
- {{#if editing}} - {{textarea value=selectedItem.description}} - {{else}} +
+
{{selectedItem.description}} - {{/if}} -
+
+ {{/if}} - -
-
-
- {{explorer-schema schema=schema hideSchema=hideSchema}} + {{! the SQL editor will show the first time you }} + {{#if everEditing}} +
+
+
+ {{explorer-schema schema=schema hideSchema=hideSchema}} +
+
+ {{ace-editor content=selectedItem.sql mode="sql"}} +
+
+
-
- {{ace-editor content=selectedItem.sql mode="sql"}} + {{else}} +
+ {{hljs-code-view value=selectedItem.sql codeClass="sql"}}
-
-
-
+ {{/if}} + +
diff --git a/assets/javascripts/discourse/views/admin-plugins-explorer.js.es6 b/assets/javascripts/discourse/views/admin-plugins-explorer.js.es6 index aaf83cb..0755a45 100644 --- a/assets/javascripts/discourse/views/admin-plugins-explorer.js.es6 +++ b/assets/javascripts/discourse/views/admin-plugins-explorer.js.es6 @@ -6,7 +6,17 @@ export default Ember.View.extend({ this.appEvents.trigger('ace:resize'); }.observes('controller.hideSchema'), + _onInsertEditor: function() { + const self = this; + Em.run.schedule('afterRender', this, function() { + self.trigger('didInsertEditor'); + }); + }.observes('controller.everEditing'), + _bindGrippie: function() { + if (this._state !== "inDOM") { + return; + } const $editPane = this.$().find('.query-editor'); if (!$editPane.length) { return; @@ -27,7 +37,7 @@ export default Ember.View.extend({ const mousemove = function(e) { const diff = self.get('startY') - e.screenY; const newHeight = self.get('startSize') - diff; - Em.Logger.debug("new height", newHeight); + //Em.Logger.debug("new height", newHeight); $targets.height(newHeight); self.appEvents.trigger('ace:resize'); }; @@ -35,7 +45,6 @@ export default Ember.View.extend({ let mouseup; mouseup = function(e) { mousemove(e); - Em.Logger.debug("mouseup"); $body.off('mousemove', mousemove); $body.off('mouseup', mouseup); self.set('startY', null); @@ -51,10 +60,12 @@ export default Ember.View.extend({ e.preventDefault(); }); - }.on('didInsertElement'), + }.on('didInsertElement', 'didInsertEditor'), _cleanup: function() { - this.get('grippie').off('mousedown'); - this.set('grippie', null); + if (this.get('controller.everEditing')) { + this.get('grippie').off('mousedown'); + this.set('grippie', null); + } }.on('willDestroyElement') }); diff --git a/assets/stylesheets/explorer.scss b/assets/stylesheets/explorer.scss index f681248..66c6ac7 100644 --- a/assets/stylesheets/explorer.scss +++ b/assets/stylesheets/explorer.scss @@ -104,6 +104,7 @@ ol { display: none; } &:hover ol { display: block; } + &:focus ol { display: block; } .enum-info { ol { @@ -114,7 +115,7 @@ background: white; list-style: none; left: -12em; - top: 10px; + top: 6px; z-index: 10; > li { width: 150%; @@ -138,8 +139,8 @@ .name h2 { display: inline-block; } - .desc textarea { - width: 200px; + .name input, .desc textarea { + width: calc(100% - 10px); } &:not(.editing) .desc { margin: 10px 0; diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 989c2df..a868a24 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -31,16 +31,17 @@ en: schema: title: "Database Schema" filter: "Search..." - sensitive: "The contents of this column may contain particularly sensitive or private information." + sensitive: "The contents of this column may contain particularly sensitive or private information. Please exercise caution when using the contents of this column." type_help: "Types" export: "Export" save: "Save Changes" saverun: "Save Changes and Run Query" run: "Run Query" - undo: "Revert" + undo: "Discard Changes" delete: "Delete" recover: "Undelete Query" download_json: "Download Results" + others_dirty: "A query has unsaved changes that will be lost if you navigate away." run_time: "Query completed in {{value}} ms." column: "Column {{number}}" explain_label: "Include query plan?"