Giter VIP home page Giter VIP logo

elgg-angular's Introduction

elgg-angular

Integrates AngularJS into Elgg

How it works

The ng/init view bootstraps

Modules, directives, filters, etc. are mapped to standard locations in the views system:

  • Modules: js/ng/modules/{moduleName}.js
  • Directives: js/ng/directives/{directiveName}/factory.js
  • Filters: js/ng/filters/{filterName}.js

The ng/init asynchronously bootstraps the current document using the required AngularJS modules for that page.

As of 0.0.1, this list of modules included on any given page is hardcoded, but this will likely become customizable soon as we will want to support:

  • Plugins defining their own modules to be loaded onto the page
  • Only loading the minimum set of modules needed for any given page

Contributing

Run tests: npm test Run karma: npm start

elgg-angular's People

Contributors

ewinslow avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar  avatar

elgg-angular's Issues

Implement local JS caching solution

Requests have to be made for the same endpoints over and over again, even though the data is highly cacheable. Would be cool to use a JS cache system that:

  • abstracts the various storage options (i.e. unified get/set interface. Always async)
  • automatically evicts stale entries
  • has some http-like expiry functionality like max-age, if-not-modified-since, etc.
  • Single-value cache instead of key-value map

Here is a potential interface:

// elgg/cache/Cache.js
define(function() {
  return class Cache {
    /**
     * @return {Promise.<JsonSerializable>} The object that was saved. Reject on cache miss.
     */
    async get() {}

    /**
     * @param {JsonSerializable} value
     * @return {Promise.<JsonSerializable>} The object that was saved. Reject on failure.
     */
    async set(value) {}
  };
});

Potential implementations:

  • FilesystemCache (Using HTML5 filesystem API)
  • InnoDbCache
  • LocalStorageCache
  • NullCache (always rejects attempts to cache)
  • ObjectCache (just using in-memory JS objects)
  • SessionStorageCache
  • WebSqlCache (probably won't do this since it is deprecated)

Re-invent the menu system for JS

Right now it's just rendered with HTML from the server. One request to server per comment on a page is a wee painful, and not very dynamic.

Instead, I think we need to render the menus on the client side, which basically requires a re-implementation of the server-side menus to work on the client.

Use cases:

  • Report spam
  • Edit
  • Delete
  • Like/Unlike
  • Off topic
  • Remove Ad
  • Navigate to related URL

Service: elggMenus (elgg/menus/Registry API Reference)

This class is registered as the elggMenus service.

get(menuName)

Get (or create) a menu definition.

/** @ngInject */
require('ng/modules/elgg').run(function(elggMenus) {
  var entityMenu = elggMenus.get('entity');

  // Configure the menu...
});

Examples

elgg/menus/Menu API Reference

Menus are collections of links and/or buttons typically rendered together on a page.

TODO:

  • Insert picture of a menu with the sections and items clearly labeled

items

The read-only items property allows you to control the list of items included in this menu. Items is a map so you can use the standard get/set/remove methods to manage what items are part of this menu.

Get an item. This will create a new one if it doesn't exist yet.

var item = menu.items.get('delete');

Set an item to a particular instance:

menu.items.set('delete', item);

Remove an item:

menu.items.remove('delete');
menu.items.remove(item);

Combine remove and set to move an item from one menu to another:

var otherMenuItem = otherMenu.items.remove('delete');
menu.items.set('delete', otherMenuItem);

sections

Each renders its items into "sections". See the elgg/menus/MenuSection docs for more details.

This is a read-only map just like the items map discussed above.

Getting a section will create a new one if it doesn't exist yet:

var section = menu.sections.get('default');

Setting a section puts all of them items in that section into the menu and loses all the other menu items that were a part of the old section by the same name.

menus.sections.set('default', section);

Removing a section also removes all the items currently associated with that section:

var section = menu.sections.remove('default');

elgg/menus/MenuSection API Reference

Each menu is divided into "sections". Each section has a label and can be ordered relative to the other sections.

elgg/menus/MenuItem API reference

action

Defines the default on-click/tap behavior of the menu item:

/** @ngInject */
item.action = function() {
  alert('You triggered the action');
};

Setting this will reset the href setting to null.

controller

If you need custom logic to complement your template, you can provide a controller:

item.controller = require('elgg/menus/entity/likes/Ctrl');

href

If you set the href, clicking the menu item will navigate to the specified page.

item.href = 'https://elgg.example.org/foo/bar';
item.href = '/foo/bar'
/** @ngInject */
item.href = function() {
  return '/foo/bar';
};

Setting this will set the action setting to null.

icon

Set this to a string id of the icon to show for this item.

item.icon = 'trash';

label

The label is just the text that is shown for the menu item.

There is actually no api for setting the label. Instead, override the language string:

return array(
  'menus:entity:items:delete:label' => 'Delete',
);

parent

This option allows setting up a hierarchy out of the menu items.

item.parent = 'more';
item.parent = menu.items.get('more');

priority

This determines the order in which the menu items are rendered. Items with lower absolute value numbers are listed first.

item.priority = 500; // default
item2.priority = 2;

section

The section param allows you to set how the menu item should be grouped:

item.section = 'default'; // This is the default behavior
item.section = menu.sections.get('default'); // equivalent

template

The template option allows you to completely take over the rendering of the menu item. You can use this to insert a custom directive.

item.template = '<elgg-likes-button entity="{{entity.data.guid}}"></elgg-likes-button>';
item.template = require('text!elgg/menus/entity/likes/template.html');

elgg-prop-*

Set arbitrary properties on an element.

elgg-prop-disabled="!!isDisabled()"

<elgg-menu-item> element for directive-local modifications to the menu

For example, to make an item inline-editable, the "Edit" menu item actually needs access to the scope of the component being edited. This requires adding an <elgg-menu-item> element inside the <elgg-menu> element. Also, if you're just building an application directly and not a plugin, this is a much more straightforward way to define the menu, since the menu items appear right in the source code where the menu is.

Example:

<elgg-menu type="entity" params="{entity: entity}">
  <elgg-menu-item type="edit" icon="pencil"
                  ng-click="isEditing = true" ng-if="!isEditing">
    Edit
  </elgg-menu-item>
</elgg-menu>

Use PHP-DI to inject dependencies into controllers

Right now we have to instantiate the dependencies in the resource controller constructors and that just feels not right, and still doesn't make them testable. But we're close!

We'll also want to be able to inject the $matches array.

Cannot edit comments

Forwarded to the home page with the error message that the 'discussion reply was not found'

demo link

Add a demo link to attract more developers! it works for me!

Unify elgg-comments and elgg-discussion-replies

These two elements are virtually identical right now. We need a way to unify them, or something.

One thing i can think that would be different: discussions can be "closed", ala github issues. Other entities with comments cannot. So the discussion replies may have that option in the ui, whereas the comments list wouldn't...

Documentation for new API

This is already way better than old web services, but it still needs more improvement (+ docs!).

Web Services

WARNING: This documentation is all a lie so far. Most features here are yet to be implemented.

Define a new API endpoint

First, add a new class like so:

<?php
namespace Hello\World;

/**
 * @ElggApi("/hello/{world}")
 */ 
class Resource {
  public function __construct($world) {
    $this->world = empty($world) ? "world": $world;
  }

  public function get() {
    return array('hello' => $this->world);
  }
}

Testing the controller

PHPUnit testing example

namespace Hello\World;

class ResourceTest extends \PHPUnit_Framework_TestCase {
  function testSaysHelloToWorldByDefault() {
    $resource = new Resource('');

    $result = $resource->get();

    $this->assertEquals($result['hello'], 'world');
  }

  function testSaysHelloToNamedEntity() {
    $resource = new Resource('foobar');

    $result = $resource->get();

    $this->assertEquals($result['hello'], 'foobar');
  }
}

You can also do a sanity check by just accessing http://elgg.example.com/api/hello/World

You should get a result like so:

{
  "hello": "World"
}

How it works

Elgg scans your classes to see if there's any annotated with @ElggApi("url/pattern"). It then registers that class as the handler for /api/url/pattern.

Depending on what HTTP method is used to request that resource, that is the method that will be called on your class.

Philosophy

Elgg takes a Resource-Method-Representation (RMR) approach to defining your API.

Add tests

We don't really have a good testing solution for plugin JS. We should figure this out, since the size of the JS is growing significantly and it will very quickly cease being easy to manually test all of it in 30 seconds.

Posting comments seems totally broken

I can fill out the form and submit it the comment doesn't get added to the stream and there is a flash of PHP errors there. Something about "canAnnotate on a non-object"

Add i18n support

Everything is hard-coded to English right now. We should either go with the current elgg.echo solution or come up with a new solution where we can bundle the translations closer to the actual component where they're used.

elgg-for-each

Replaces ng-repeat + collection-repeat. Meant to be closer to js api.

Features of ng-repeat:

  • track by
  • alias collection
  • alias key
  • alias value

Features of collection-repeat:

  • item height
  • item width

elgg-for-each="ctrl.getItems()"
elgg-for-each-options="{valueAs: '$value', keyAs: '$key', collectionAs: '$collection', itemHeight: '33%', itemWidth: '33%', trackBy: '$index'}"

Could also just have a simpler elgg-for:

elgg-for="item of items"
elgg-for="key in items"

elgg-for-each

Replaces ng-repeat + collection-repeat. Meant to be closer to js api.

Features of ng-repeat:

  • track by
  • alias collection
  • alias key
  • alias value

Features of collection-repeat:

  • item height
  • item width

elgg-for-each="ctrl.getItems()"
elgg-for-each-options="{valueAs: '$value', keyAs: '$key', collectionAs: '$collection', itemHeight: '33%', itemWidth: '33%', trackBy: '$index'}"

Could also just have a simpler elgg-for:

elgg-for="item of items"
elgg-for="key in items"

elgg-attr-*

Set arbitrary attributes on an element.

Exact same thing as ng-attr-*, except perhaps using es6 style interpolation:

elgg-attr-aria-label="${ctrl.ariaLabel}"

error with posting comments

Fatal error: Call to a member function canEdit() on a non-object in /var/www/community-test.elgg.org/engine/lib/navigation.php on line 432

elgg-on-*

Listen for arbitrary events, including custom ones:

elgg-on-click
elgg-on-focus
elgg-on-blur
etc...

no menu items are showing up

In order to get this on the community site, we need at least:

  • edit
  • delete
  • like
  • report spam
  • off topic
  • remove ad

Want a way to wrap an existing object in the Resource class

When you get a collection of items, you often have embedded resources.

I'd like there to be a way to use the Resource wrapper to do post/get/etc... on these resources but without necessarily making a fresh http request from the server (cuz that would get crazy).

Current ideas for an API for this:

<elgg-resource src="{{url}}" init="content"></elgg-resource>

or...

<elgg-resource src="{{url}}" content="content"></elgg-resource>

decorate services

elgg/di/decorator

Creates a module that decorates the given target...

$provide.decorate(function($injector, $delegate) {
    return $injector.instantiate(ctor, {
      '$delegate': $delegate
    });
});

Enable CSRF protection

This currently doesn't work and needs to be integrated into the angular http request. This also needs to be completely invisible to content authors otherwise they will forget to do it and that will be a frustrating experience when they get errors back from the server.

I believe we can accomplish this without any hacks using interceptors to decorate Angular http requests.

Handle pagination/overflow

Need to be able to view all comments beyond the default limit of 50. Some kind of automatic loading or request-more button is needed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.